数据结构——链表经典实例(多项式运算的实现)

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define TRUE            1
#define FALSE           0
#define OK              1
#define ERROR           0
#define INFEASIBLE      -1
#define OVERLOW         -2

/*--------------------------------------
             Data Element
--------------------------------------*/

typedef struct{
    float coef;//系数
    int expn;//指数
}term,ElemType;

typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode,*Link,*Position;

typedef struct HeadNode{
    Link head,tail;
    int len;
}LinkList;

typedef LinkList polynomail;
typedef int status;

/*---------------------------------------
            OP of Link List
---------------------------------------*/

status MakeNode( Link &p, ElemType e){
    p=(Link)malloc(sizeof(LNode));
    p->data=e;
    return OK;
}

status InitList( LinkList &L){
    L.head=(Link)malloc(sizeof(LNode));
    ElemType e;
    e.coef=0, e.expn=-1;
    L.head->data=e;
    L.head->next=NULL;
    L.tail=L.head;
    L.len=0;
    return OK;
}


status SetCurElem(Link &p,ElemType e){
    p->data=e;
    return OK;
}

status InsAfter( Link q, Link s){
    //将结点s插入到结点q之后
    s->next=q->next;
    q->next=s;
    return OK;
}


status ListEmpty(LinkList P){
    if(P.head->next==NULL) return TRUE;
    return FALSE;
}


status Append( LinkList &L, Link s){
    //将一串元素s插入到链表L的末尾,同时改变链表的长度以及尾指针
    L.tail->next=s; 
    L.len++;
    while(s->next!=NULL){
        s=s->next;L.len++;
    }
    L.tail=s;
    return OK;
}
            

int cmp( term e1, term e2){
    if(e1.expn<e2.expn) return -1;
    if(e1.expn==e2.expn) return 0;
    if(e1.expn>e2.expn) return 1;
}


Position GetHead( LinkList L){
    return L.head;
}


Position GetLast( LinkList L){
    return L.tail;
}


Position NextPos( LinkList L, Link p){
    p=p->next;
    return p;
}

status DelFirst( Link h, Link q){
    //已知h是头结点,删除h后的第一个结点q
    h->next=q->next;
    return OK;
}    

/*------------------------------------------
           OP of polynomial
------------------------------------------*/
void CreatePolyn(polynomail &P,int m){
    /*CreatePolyn(polynomail &P,int m)--使用尾差法创建一个具有m项的多项式P,
    它为P.len中存放有多项式的项数,P.tail指向多项式的尾结点,P.head为多项式的
    头结点,头结点不存放数据,统一初始化为P.head->data.coef=0,
    P.head->data.expn=-1。调用时需要按照从高次项向低次项的顺序输入数据。
    */
    InitList(P);    
    Link s,q;
    term e;
    int i;
    printf("\nPlease input %d terms in order:\n",m);
    for(i=1;i<=m;i++){
        scanf("%f%d",&e.coef,&e.expn);
        if(MakeNode(s,e)){
            q=GetLast(P);InsAfter(q,s); P.tail=s; P.len++;
        }
    }
    printf("\nCreate polynomail succeed!\n");
}

int PrintPolyn( polynomail &P){
    //遍历打印多项式
    Link p=P.head;

        if(p->next==NULL) {
    printf("\nEmpty LinkList!\n"); return OK;
        }
        printf("\ncoef\texpn\n");
        while(p!=NULL){
        if(p->data.expn>=0) printf("%.2f\t%d\n",p->data.coef,p->data.expn);
        p=p->next;
        }
        printf("\nPrint succeed!\n");
        return OK;
}
    
void AddPolyn( polynomail &Pa, polynomail &Pb){
    /*Pa=Pa+Pb,最终结果保存在Pa中。算法的时间复杂度取决于两个多项式Pa,Pb
    之间最高次项较低的那个多项式的长度。最坏情况下,假如每次循环都需要进系数相加,
    case 0中所有操作的时间复杂度均为O(1),循环外的Append(Pa,Pb)的时间复杂度也是
    O(1),因此AddPolyn(Pa,Pb)的时间复杂度为O(n)
    */
    Link ha=GetHead(Pa);    //头结点h不存储term
    Link hb=GetHead(Pb);
    Link qa=NextPos(Pa,ha);
    Link qb=NextPos(Pb,hb);
    while(qa!=NULL && qb!=NULL){
    term a= qa->data;
    term b= qb->data;
    switch(cmp(a,b)){    //cmp比较的是term之间指数的大小
        case 1:
        ha=qa; qa=NextPos( Pa,qa); break;
        case 0:
        term sum;
        sum.expn=a.expn;
        sum.coef=a.coef+b.coef;
        if(sum.coef!=0){
            SetCurElem( qa,sum); ha=qa;}
        else{
            DelFirst(ha,qa); free(qa);}
        DelFirst(hb,qb); free(qb); qb=NextPos(Pb,hb);
        qa=NextPos(Pa,ha); break;
        case -1:
        DelFirst(hb,qb); InsAfter(ha,qb);Pa.len++;
        qb=NextPos(Pb,hb); ha=NextPos(Pa,ha);break;
    }
    }
    if(!ListEmpty(Pb)) Append(Pa,qb);
}

void SubPolyn( polynomail &Pa, polynomail &Pb){
    /*Pa=Pa-Pb,最终结果保存在Pa中,Pb被释放。SubPolyn(Pa,Pb)相对于
    AddPolyn(Pa,Pb),只多了一个操作:将多项式Pb的系数取负号。该操作的
    的时间复杂度为O(n),因此SubPolyn(pa,pb)的时间复杂度为O(n)。
    */
    Link ha=GetHead(Pa);    //头结点h不存储term
    Link hb=GetHead(Pb);
    Link qa=NextPos(Pa,ha);
    Link qb=NextPos(Pb,hb);
    while(qb!=NULL){
    qb->data.coef=-qb->data.coef; qb=NextPos(Pb,qb);
    }
    qb=NextPos(Pb,hb);
    while(qa!=NULL && qb!=NULL){
    term a= qa->data;
    term b= qb->data;
    switch(cmp(a,b)){    //cmp比较的是term之间指数的大小
        case 1:
        ha=qa; qa=NextPos( Pa,qa); break;
        case 0:
        term sum;
        sum.expn=a.expn;
        sum.coef=a.coef+b.coef;
        if(sum.coef!=0){
            SetCurElem( qa,sum); ha=qa;}
        else{
            DelFirst(ha,qa); free(qa);}
            DelFirst(hb,qb); free(qb); qb=NextPos(Pb,hb);
            qa=NextPos(Pa,ha); break;
        case -1:
        DelFirst(hb,qb); InsAfter(ha,qb);Pa.len++;
        qb=NextPos(Pb,hb); ha=NextPos(Pa,ha);break;
    }
    }
    if(!ListEmpty(Pb)) Append(Pa,qb);
    free(hb);
}


void MultiPolyn( polynomail &Pa, polynomail &Pb){
    /*Pa=Pa*Pb,最终结果保存在Pa中。MultiPolyn(Pa,Pb)的基本操作为
    AddPolyn(Pd,Pc)(复杂度为O(n))和多形式和单项式的乘法(复杂度为O(n))
    基本操作位于一个循环数为Pb.len的循环中,因此MultiPolyn(Pa,Pb)的时间复杂度
    为O(n^2)。
    */
    polynomail Pc,Pd; 
    Link ha=GetHead(Pa);    
    Link hb=GetHead(Pb);
    Link qa=NextPos(Pa,ha);
    Link qb=NextPos(Pb,hb);
    Link s,qc;        
    int i,j,lena=Pa.len,lenb=Pb.len;
    term a,b,c;

    InitList(Pd);          
    for(i=1;i<=lenb;i++){
    InitList(Pc);        //Pc用于记录多项式Pa每次乘以Pb各项所得到的多项式
    for(j=1;j<=lena;j++){
        a= qa->data;
        b= qb->data;
        c.coef=a.coef*b.coef; c.expn=a.expn+b.expn;
            if(MakeNode(s,c)){
            qc=GetLast(Pc);InsAfter(qc,s); Pc.tail=s; Pc.len++;
            }//if
        qa=NextPos(Pa,qa);    
        }//for(j)           
        qa=NextPos(Pa,ha);      //注意此时qa一定要指向多项式Pa的首项
        qb=NextPos(Pb,qb);    
        AddPolyn(Pd,Pc);      //Pd+=Pc
    }//for(i)
    Pa=Pd; 
}
    

void DivPolyn( polynomail &Pa, polynomail &Pb){
    /*Pa=Pd*Pb+Pa,最终的商存储在Pd中,余式存储在Pa中。DivPolyn(Pa,Pb)的
    基本操作为MultiPolyn(Pc,Pb),该基本操作位于一个循环数为多项式Pa和Pb最高
    项次数之差的循环之中。因此,考虑最坏情况,该算法的时间复杂度为O(n^3)。
    */
    polynomail Pc,Pd; 
    Link ha=GetHead(Pa);    
    Link hb=GetHead(Pb);
    Link qa=NextPos(Pa,ha);
    Link qb=NextPos(Pb,hb);
    Link s,qc;
    term a,b,c;

    InitList( Pd);
    a=qa->data; b=qb->data;    
    while(a.expn>=b.expn){
    InitList (Pc);
    c.expn=a.expn-b.expn;
    c.coef=a.coef/b.coef;
    if(MakeNode(s,c)){
        qc=GetLast(Pc);InsAfter(qc,s); Pc.tail=s; Pc.len++;
    }
        AddPolyn( Pd,Pc); MultiPolyn( Pc,Pb);  SubPolyn( Pa,Pc);    //Pd用来存储商,SubPolyn()中Pc会被free
    qa=NextPos(Pa,qa);                     //Pd+=Pc,Pc*=Pb,Pa-=Pc,最终Pa中存储的是余式
    a=qa->data;
    }//while
    printf("The quotient polynomail is :\n");            
    PrintPolyn(Pd); 
    printf("The complement minor is :\n");
    PrintPolyn(Pa);
}
    
/*-------------------------------------
       function main
--------------------------------------*/
/*
int main(){
    //test for AddPolyn(),SubPolyn() and MultiPolyn()
    polynomail P1;
    polynomail P2;
    
    CreatePolyn(P1,2);  
    CreatePolyn(P2,4);
    printf("\nThe length of poly1 is %d\n",P1.len);
    PrintPolyn( P1);
    printf("\nThe length of poly2 is %d\n",P2.len);
    PrintPolyn( P2);

    SubPolyn( P1,P2);

    PrintPolyn( P1);
    printf("\nThe length of poly1 is %d\n",P1.len);
    return OK;
}
*/

int main(){
    //test for DivPolyn()
    polynomail P1;
    polynomail P2;
    
    CreatePolyn(P1,3);  
    CreatePolyn(P2,2);
    printf("\nThe length of poly1 is %d\n",P1.len);
    PrintPolyn( P1);
    printf("\nThe length of poly2 is %d\n",P2.len);
    PrintPolyn( P2);

    DivPolyn( P1,P2);

    return OK;
}

 

posted @ 2016-03-23 22:15  Jarning_Gau  阅读(623)  评论(0)    收藏  举报