数据结构(严蔚敏)2.4一元多项式

学习记录,仅供参考,希望可以指出错误

 

根据带头结点的线性链表改编,即elemtype也变成了struct结构

数据结构(严蔚敏)2.4一元多项式

 

 

 

 

 

 

#include<stdio.h>
#include<stdlib.h>
//改由带头结点的线性链表
#define OK 1
#define ERROR 0
typedef int status;

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

typedef struct lnode{
    elemtype data;
    struct lnode *next;
}*link,*position;

typedef struct{
    link head,tail;
    int len;
}linklist;

typedef linklist polynomial;

status makenode(link &p,elemtype e){//分配由p指向的值为e的结点,并返回OK,若分配失败返回ERROR
    p=new lnode;
    p->data=e;
    p->next=NULL;
    if(p) return OK;
    else return ERROR;
}

void freenode(link &p){//释放p所指向的结点
    free(p);
    p=NULL;
}

status initlist(linklist &l){//构造空的线性链表l(空表里还是有一个结点的
    link p=new lnode;
    l.len=0;
    l.head=l.tail=p;
    p->next=NULL;
    if(p) return OK;
    return ERROR;
}

position gethead(linklist l){//返回l中头结点的位置
    return l.head;
}

position getlast(linklist l){//返回l中最后一个结点的位置
    return l.tail;
}

void clearlist(linklist &l){//将线性链表l重置为空表,并释放原链表的结点空间
    link p,q;
    p=l.head;
    while(p){
        q=p->next;
        free(p);
        p=q;
    }
    p=new lnode;
    l.head=l.tail=p;
    p->next=NULL;
    l.len=0;
}

void destorylist(linklist &l){//销毁线性链表l,l不再存在
    clearlist(l);
    free(l.head);
    l.head=l.tail=NULL;
}

void insfirst(linklist &l,link h,link s){//已知h指向线性链表的头结点,将s所指结点插入在第一个结点之前(头!=一 
    s->next=h->next;
    h->next=s;
    if(h==l.tail) l.tail=h->next;
    l.len++;
}

status delfirst(linklist &l,link h,link &q){//已知h指向线性链表的头结点,删除链表中的第一个结点并以q返回
    q=h->next;
    if(q){//如果链表非空
        h->next=q->next;
        q->next=NULL;
        if(!h->next)
            l.tail=h;
        l.len--;
        return OK;
    }
    return ERROR;
}

void append(linklist &l,link s){//将指针s所指(彼此以指针相链)的一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
    int inc=0;
    l.tail->next=s;
    while(s){//link的元素个数
        l.tail=s;
        s=s->next;
        inc++;
    }
    l.len=l.len+inc;
}

void remove(linklist &l,link &q){//删除线性链表L中的尾结点并以q返回,改变链表L的尾结点指向新的尾结点
    link p=gethead(l);
    while(p->next!=l.tail&&p->next!=NULL){//找到要某个结点的前一个
        p=p->next;
    }
    q=p->next;
    l.tail=p;
    l.len--;
}

position priorpos(linklist l,link p){//已知p指向l中的一个结点,返回p所指结点的前驱,若无返回null
    link q=gethead(l);
    while(q->next!=p&&q->next!=NULL){
        q=q->next;
    }
    if(q->next==NULL) return NULL;
    return q;
}

position nextpos(link p){//已知p指向l中的一个结点,返回p所指结点的后继,若无返回null
    if(!p) return NULL;
    return p->next;
}

void insbefore(linklist &l,link &p,link &s){//已知p指向l中的一个结点,将s所指的结点插入在p所指的结点之前,并修改指针p指向新插入的结点
    link q=priorpos(l,p);//找p的前趋
    if(!q) q=gethead(l);//如果没有前趋
    s->next=p;
    q->next=s;
    p=s;
    l.len++;
}

void insafter(linklist &l,link &p,link s){//已知p指向l中的一个结点,将s所指的结点插入在p所指的结点之后,并修改指针p指向新插入的结点
    if(p==l.tail)
        l.tail=s;//如果p是最后一个结点,则修改最后一个结点为s
    s->next=p->next;
    p->next=s;
    p=s;
    l.len++;
}

void setcurelem(link &p,elemtype e){//已知p指向线性链表中的一个结点,用e更新结点中数据元素的指
    p->data=e;
}

elemtype getcurelem(link p){//已知p指向线性链表中的一个结点,返回他的值
    return p->data;
}

int listempty(linklist l){//判断是否为空
    if(l.len==0) return 0;
    else return l.len;
}

int listlength(linklist l){//返回元素个数
    return l.len;
}

int locatepos(linklist l,int i,link &p){//返回p所指示l中第i个结点的位置并返回OK,否则返回ERROR
    if(i<0||i>l.len) return 0;
    p=l.head;
    int count=0;
    while(count<i){
        count++;
        p=p->next;
    }
    return 1;
}

int xishuk(elemtype e,elemtype k){//如果不存在该系数,返回0
    if(e.expn==k.expn)
        return 0;
    if(e.expn<k.expn) return -1;
    return 1;
}
status locateelem(linklist l,elemtype e,position &q,int (*compare)(elemtype,elemtype)){//返回l中第一个与e满足函数compare判定关系的元素的位置,若不存在返回Null
    link p=gethead(l);    
    while(p->next){
    p=nextpos(p);
    if(!(*compare)(p->data,e)){q=p; return OK;}//返回第一个系数为k的
    }  
    q=p;
    return ERROR;//说明没有满足的
}

void visit1(elemtype e){//输出所有系数
    printf("%f    ",e.coef);
}
void listtraverse(linklist l,void (*visit)(elemtype)){//依次对L的每个元素调用函数visit,一旦visit失败则操作失败
    link p=gethead(l)->next;
    while(p){
        visit(p->data);
        p=nextpos(p);
    }
    printf("\n");
}

status listinsert(linklist &l,int i,elemtype e){//在带头结点的单链线性表l的第i个元素之前添加元素e
    link p,q;
    if(!locatepos(l,i-1,p)) return ERROR;
    if(!makenode(q,e)) return ERROR;
    insfirst(l,p,q);
    return OK;
}

void scanf_xxlb(linklist &l){
    printf(" num is:");
    int num;
    scanf("%d",&num);
    printf("\n to:\n");
    for(int i=1;i<=num;i++){
        elemtype e;
        scanf("%f",&e.coef);
        scanf("%d",&e.expn);
        listinsert(l,i,e);
    }
}

void printf_xxlb(linklist l){
    printf("\n printf:\n");
    link p=gethead(l);
    for(int i=0;i<l.len;i++){
        p=nextpos(p);
        printf("%fx^%d    ",p->data.coef,p->data.expn);
    }
    printf("\n");
}


//status locateelem(linklist l,elemtype e,position &q,int(*compare)(elemtype,elemtype)){}//在上方
        
void printpolyn(polynomial p){//打印输出一元多项式
    printf("\n printf:\n");
    link q=gethead(p);
    for(int i=0;i<p.len;i++){
        q=nextpos(q);
        printf("%fx^%d    ",q->data.coef,q->data.expn);
    }
    printf("\n");
}

int sortcom(elemtype a,elemtype b){//
    if(a.expn < b.expn)return 1;
    if(a.expn == b.expn)return -1;
    return 0;
}
status orderinsert(linklist &l,elemtype e,int(*compare)(elemtype,elemtype)){//按照有序判定函数compare()的约定,将值为e的结点插入到有序链表l的合适位置上
    link q;
    makenode(q,e);
    for(int i=1;i<=l.len;i++){
    link p;
    locatepos(l,i,p);
    switch(sortcom(e,p->data)){
    case 1://找到了
        insfirst(l,priorpos(l,p),q);    
        return OK;
    case -1://找到了指数相同的,就改变系数
        e.coef=e.coef+p->data.coef;
        setcurelem(p,e);
        return ERROR;
    }
    }
    link last=getlast(l);//没找到,添加到末尾
    insafter(l,last,q);
    return OK;
}

status sortpolyn(polynomial &p){//按照指数排序
    if(p.len<2) return ERROR;//如果小于2,则不用排序
    link hq=gethead(p);
    link tq=nextpos(hq);//这时候tq是第一个
    while(nextpos(tq)){//如果tq的下一个不为空
        link xq=tq;
        link nextp=nextpos(tq);
        int a=getcurelem(nextp).expn;//当前
        int b=getcurelem(tq).expn;//当前的上一个
        int sign=0;
        while(a<=b){//如果当前的指数小于当前的上一个
            sign++;//标记不为0了
            link del;delfirst(p,tq,del);//删除当前
         if(a==b){            
            elemtype e;e.coef=del->data.coef+tq->data.coef;e.expn=a;
            tq->data=e;
            nextp=tq;
            tq=priorpos(p,nextp);
         }else{                    
            insfirst(p,priorpos(p,tq),del);//把当前添加到上一个的上一个的后面
            nextp=del;//修改当前
            }
            tq=priorpos(p,nextp);//修改当前的上一个
            a=getcurelem(nextp).expn;//当前
            b=getcurelem(tq).expn;//当前的上一个
        }
        if(sign==0) tq=nextpos(xq);//如果标记为0,就说明没有进行排序
    }
    return OK;
}

//算法2.22
void createpolyn(polynomial &p,int m){//输入m项的系数和指数,建立表示一元多项式的有序链表
    //比如当输入n,6之后在输入m,6因为指数是相同的,所以m,6不会加入到队列(没设置自动合并
    initlist(p);    link h=gethead(p);
    elemtype e;    e.coef=0.0;e.expn=-1;
    setcurelem(h,e);
    for(int i=1;i<=m;++i){
        printf("输入:\n");scanf("%f",&e.coef);scanf("%d",&e.expn);
        link q;
        if(!locateelem(p,e,q,xishuk)){//如果不存在该指数项
            link s;
            if(makenode(s,e)) insfirst(p,q,s);                
        }
        //orderinsert(p,e,sortcom);插入的时候就自动按照指数进行操作了
        //link s;makenode(s,e);append(p,s);sortpolyn(pa);//插完再排序
        
    }
}

void destorypolyn(polynomial &p){//销毁一元多项式p
    clearlist(p);
    free(p.head);
    p.head=p.tail=NULL;
}



int polynlength(polynomial p){//返回一元多项式p中的项数
    return p.len;
}

//算法2.23
void addpolyn(polynomial &pa,polynomial &pb){//加法,好像只能是他的qa和qb的指数呈上升,比如x+2x^3+3x^4,不能2x^3+x+3x^4
    link ha=gethead(pa),hb=gethead(pb);
    link qa=nextpos(ha),qb=nextpos(hb);//qa是当前结点
    while(qa&&qb){
    elemtype a=getcurelem(qa),b=getcurelem(qb);
     switch(xishuk(a,b)){//判断b的结点的指数对于a的比较
        case -1://多项式pa中当前结点的指数小
            ha=qa;qa=nextpos(qa);break;
        case 0://两者指数相等
            elemtype sum;
            sum.coef=a.coef+b.coef; 
            sum.expn=a.expn;
            if(sum.coef!=0){
                setcurelem(qa,sum);ha=qa;}
            else{
                delfirst(pa,ha,qa);freenode(qa);}
            delfirst(pb,hb,qb);freenode(qb);qb=nextpos(hb);
            qa=nextpos(ha);break;
        case 1://多项式pb中当前结点的指数小
            delfirst(pb,hb,qb);insfirst(pa,ha,qb);
            qb=nextpos(hb);ha=nextpos(ha);break;        
        }
        }
    if(listempty(pb)) append(pa,qb);
    freenode(hb);
}

void subtractpolyn(polynomial &pa,polynomial &pb){//减法,根据上面的改编的
    link ha=gethead(pa),hb=gethead(pb);
    link qa=nextpos(ha),qb=nextpos(hb);//qa是当前结点
    while(qa&&qb){
    elemtype a=getcurelem(qa),b=getcurelem(qb);
     switch(xishuk(a,b)){//判断b的结点的指数对于a的比较
        case -1://多项式pa中当前结点的指数小
            ha=qa;qa=nextpos(qa);break;
        case 0://两者指数相等,就进行计算
            elemtype sum;
            sum.coef=a.coef-b.coef; 
            sum.expn=a.expn;
            if(sum.coef!=0){
                setcurelem(qa,sum);printf_xxlb(pa);ha=qa;}
            else{
                delfirst(pa,ha,qa);freenode(qa);}
            delfirst(pb,hb,qb);freenode(qb);qb=nextpos(hb);
            qa=nextpos(ha);break;
        case 1://多项式pb中当前结点的指数小
            elemtype e;
            e.coef=-b.coef;
            e.expn=b.expn;
            setcurelem(qb,e);
            delfirst(pb,hb,qb);insfirst(pa,ha,qb);
            qb=nextpos(hb);ha=nextpos(ha);break;        
        }
        }
    if(listempty(pb)) append(pa,qb);
    freenode(hb);
}

polynomial multiplypolyn(polynomial &pa,polynomial &pb){//乘法
    link ha=gethead(pa),hb=gethead(pb);
    link qa=nextpos(ha),qb=nextpos(hb);//qa是当前结点
    polynomial pc;
    initlist(pc);
    while(qa){
        elemtype a=qa->data;
        polynomial pd;
        initlist(pd);
        link qtb=qb;
        int i=1;
        while(qtb){
            elemtype b=qtb->data;
            elemtype e;
            e.coef=a.coef*b.coef;
            e.expn=a.expn+b.expn;
            listinsert(pd,i,e);i++;
            qtb=nextpos(qtb);
        }
        addpolyn(pc,pd);
    
        qa=nextpos(qa);
    }
    return pc;

}


void main(){
    polynomial pa;
    printf("*******************测试createpolyn\n");
    createpolyn(pa,9);
    //printf("*******************测试createpolyn\n");
    //createpolyn(pb,2);

    //addpolyn(pa,pb);
    //subtractpolyn(pa,pb);
    //polynomial pc=multiplypolyn(pa,pb);
    printf("*******************测试printpolyns\n");
    printf_xxlb(pa);
    }

 

上一篇:循环链表+动态约瑟夫问题


下一篇:数据结构(严蔚敏)2.3.2双向链表(循环)