• 数据结构之一元多项式的加法和乘法


    Polynomial.h
      1 #define _CRT_SECURE_NO_DEPRECATE
      2 #include "Polynomial.h"
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 
      6 int ListLength(NormLinkList *L)
      7 {
      8     int num = 0;
      9     Link p = NextPos(L, GetHead(L));
     10     while(p)
     11     {
     12         num++;
     13         p = NextPos(L, p);
     14     }
     15     return num;
     16 }//PolynLength()个人觉得这两个函数功能一样
     17 
     18 Status MakeNode(Link *p, ElemType e)
     19 {
     20     //分配由*p指向的值为e的节点,并返回OK;若分配失败,则返回ERROR(此处使用了指向指针的指针p,*p为节点的地址)
     21     *p = (Link)malloc(sizeof(NormLNode));
     22     if(!(*p))
     23         return ERROR;
     24     (*p)->data = e;
     25     (*p)->next = NULL;
     26     return OK;
     27 }
     28 
     29 void FreeNode(Link p)
     30 {
     31     //释放p所指节点
     32     free(p);
     33 }
     34 
     35 
     36 Status InitList(NormLinkList *L)
     37 {
     38     //构造一个空的线性链表L
     39     L->head = (Link)malloc(sizeof(NormLNode));//生成头节点
     40     if(!(L->head))
     41         return ERROR;
     42     L->head->next = NULL;
     43     L->tail = L->head;
     44     L->len = 0;
     45     return OK;
     46 }
     47 
     48 
     49 Status DestroyList(NormLinkList *L)
     50 {
     51     //销毁线性链表L,L不再存在
     52     Link p = L -> head -> next;//p指向L的第一个节点
     53     Link q;
     54     while(p)
     55     {
     56         q = p -> next;
     57         free(p);
     58         p = q;
     59     }
     60     free(L -> head);//释放头节点空间
     61     free(L);
     62     return OK;
     63 }
     64 
     65 
     66 Status ClearList(NormLinkList *L)
     67 {
     68     //将线性链表L重置为空表(仅有头节点),并释放原链表的存储空间
     69     Link p = L -> head -> next;//p指向L的第一个节点
     70     Link q;
     71     while(p)
     72     {
     73         q = p -> next;
     74         free(p);
     75         p = q;
     76     }
     77     L -> head -> next = NULL;
     78     L -> tail = L -> head;
     79     L -> len = 0;
     80     return OK;
     81 }
     82 
     83 
     84 Status InsFirst(Link h, Link s)
     85 {
     86     //将s所指节点插入在第一个节点之前
     87     if(h && s)
     88     {
     89         s -> next = h -> next;
     90         h -> next = s;
     91         return OK;
     92     }
     93     else
     94         return ERROR;
     95 }
     96 
     97 
     98 Status DelFirst(Link h, Link *q)
     99 {
    100     //删除链表中的第一个节点,并用q返回
    101     *q = h -> next;//*q指向待删除节点
    102     h -> next = (*q) -> next;
    103     (*q)->next = NULL;//非常重要,否则*q会链接到剩余的节点
    104     return OK;
    105 }
    106 
    107 
    108 Status Append(NormLinkList *L, Link s)
    109 {
    110     //将指针s所指(彼此以指针相链接)的一串节点链接在线性链表L的最后一个节点之后,
    111     //并改变链表L的尾指针指向新的尾节点
    112     Link p = s, q = s;//p指向s,q保持在p前面
    113     int j = 0;//指示s中的节点个数,用于更新L->len,考虑到了s为空的情况,此时while条件不满足,j为0
    114     if(!UpdateTail(L))
    115         return ERROR;
    116     L -> tail -> next = s;
    117     while(p)
    118     {
    119         //退出时,q指向s中最后一个节点,j为s中的节点个数
    120         j++;
    121         q = p;
    122         p = p -> next;
    123     }
    124     L -> tail = q;
    125     L -> len += j;
    126     return OK;
    127 }
    128 
    129 
    130 Status UpdateTail(NormLinkList *L)
    131 {
    132     //注意L为空表的情况
    133     //更新L的尾节点,并更新链表长度
    134     Link p = L -> head -> next, q = L -> head -> next;//p指向链表第一个节点,q保持在p前面
    135     int j = 0;//指示s中的节点个数,用于更新L->len,考虑到了s为空的情况,此时while条件不满足,j为0
    136     if(!(L->head->next))//考虑L为空的情况,此时若执行后面语句,会导致L->tail指向NULL,使得Append函数的L->tail->next = s;语句访存冲突
    137         return OK;
    138     while(p)
    139     {
    140         //退出时,q指向L中最后一个节点,j为L中的节点个数(仅在L非空时有效)
    141         j++;
    142         q = p;
    143         p = p -> next;
    144     }
    145     L -> tail = q;
    146     L -> len = j;
    147     return OK;
    148 }
    149 
    150 
    151 Position GetHead(NormLinkList *L)
    152 {
    153     //返回线性链表L中头节点的位置
    154     return L -> head;
    155 }
    156 
    157 
    158 Position NextPos(NormLinkList *L, Link p)
    159 {
    160     //已知p指向线性链表L中的一个节点,返回p所指节点的直接后继的位置,若无后继,则返回NULL
    161     return p->next;
    162 }
    163 
    164 
    165 ElemType GetCurElem(Link p)
    166 {
    167     //已知p指向线性链表中的一个节点,返回p所指节点中数据元素的值
    168     return p -> data;
    169 }
    170 
    171 
    172 Status LocatePos(NormLinkList *L, int i, Link *p)
    173 {
    174     //用*p返回线性链表L中第i个节点的位置并返回OK,i值不合法时返回ERROR。此处p为指向指针的指针,用于返回第i个节点的地址
    175     //0 <= i <= 表长;(i取0时,返回头节点位置,用于在L的第一个节点前插入元素,ListInsert_NL调用时会用到)
    176     Link q = L -> head;//q指向L中的头节点
    177     int j = 0;
    178     while(q && j < i)
    179     {
    180         //退出时,q == NULL,或者j == i
    181         q = q->next;
    182         j++;
    183     }
    184     if(!q || j > i)//q为空,或者 i < 0,即第i个元素不存在
    185         return ERROR;
    186     *p = q;//此时q指向L中第i个节点的位置
    187     return OK;
    188 }
    189 
    190 
    191 Status SetCurElem(Link p, ElemType e)
    192 {
    193     //已知p指向线性链表中的一个节点,用e更新p所指节点中数据元素的值
    194     if(p)
    195         p->data = e;
    196     else
    197         return ERROR;
    198     return OK;
    199 }
    200 
    201 
    202 Status LocateElem(NormLinkList *L, ElemType e, Position *q, Status (* compare)(ElemType, ElemType))
    203 {
    204     //若有序链表L中存在与e满足判定函数compare()取值为0的元素,则*q指示L中第一个值为e的节点的位置,并返回TRUE
    205     //否则*q指示第一个与e满足判定函数compare()取值>0的元素的前驱的位置,并返回FALSE。此处p为指向指针的指针,用于返回满足条件的节点的地址
    206     Position p = L -> head, r = L -> head -> next;//p指向L中的头节点,r作为p的直接后继
    207     while(r && (* compare)(r -> data, e) < 0)
    208     {
    209         //退出时,要么r为NULL,要么r->data的指数项等于或者大于e的指数项
    210         p = r;
    211         r = r->next;
    212     }
    213     if(r == NULL)
    214     {
    215         //要么表为空,要么e的指数项大于L中的最高指数项,此时返回r的直接前驱p
    216         *q = p;
    217         return FALSE;
    218     }
    219     else
    220     {
    221         //r不为空
    222         if((* compare)(r->data, e) == 0)
    223         {
    224             //存在与e指数项相同的节点,此时r指向该节点
    225             *q = r;
    226             return TRUE;
    227         }
    228         else
    229         {
    230             //不存在与e指数项相同的节点,此时r->data的指数项大于e的指数项,此时返回r的直接前驱p
    231             *q = p;
    232             return FALSE;
    233         }
    234     }
    235 
    236 }
    237 
    238 
    239 Status ListEmpty(NormLinkList *L)
    240 {
    241     //若线性链表L为空表,则返回TRUE,否则返回FALSE
    242     if(L -> head -> next == NULL)
    243         return TRUE;
    244     else
    245         return FALSE;
    246 }
    247 
    248 
    249 Status ListInsert_NL(NormLinkList *L, int i, ElemType e)
    250 {
    251     //在带头节点的单链线性表L的第i个元素之前插入元素e
    252     Link *h = (Link *)malloc(sizeof(Link));
    253     Link *s = (Link *)malloc(sizeof(Link));
    254     if(!LocatePos(L, i-1, h))//i值在链表范围之外,即i<=0,或者i>表长;否则,通过*h返回L中的第i-1个节点的位置
    255         return ERROR;
    256     if(!MakeNode(s, e))//结点存储分配失败;否则,通过*s返回新生成的节点地址
    257         return ERROR;
    258     InsFirst(*h, *s);//将节点*s插入到节点*h后面
    259     return OK;
    260 }
    261 
    262 
    263 Status MergeList_NL(NormLinkList *La, NormLinkList *Lb, NormLinkList *Lc, int (* compare)(ElemType, ElemType))
    264 {
    265     //UpdateTail函数中未处理表为空的情况
    266     //已知单链线性表La和Lb的元素按值非递减排列
    267     //归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列
    268     Position ha = GetHead(La);
    269     Position hb = GetHead(Lb);//ha,hb分别指向La,Lb的头节点
    270     Position pa = NextPos(La, ha);
    271     Position pb = NextPos(Lb, hb);//pa,pb分别指向La,Lb的当前节点(第一个节点)
    272     ElemType a, b;
    273     Link *q = (Link *)malloc(sizeof(Link));
    274     while(pa && pb)
    275     {
    276         //pa,pb均不为空
    277         a = GetCurElem(pa);
    278         b = GetCurElem(pb);//a,b为两表中待比较元素
    279         if((* compare)(a, b) <= 0)
    280         {
    281             //a <= b
    282             DelFirst(ha, q);
    283             Append(Lc, *q);
    284             pa = NextPos(La, ha);
    285         }
    286         else
    287         {
    288             //a > b
    289             DelFirst(hb, q);
    290             Append(Lc,*q);
    291             pb = NextPos(Lb, hb);
    292         }
    293     }
    294     if(pa)
    295         Append(Lc, pa);
    296     else
    297         Append(Lc, pb);
    298     FreeNode(ha);
    299     FreeNode(hb);
    300     return OK;
    301 }
    302 
    303 
    304 int cmp(term a, term b)
    305 {
    306     //根据a的指数值<(或=)(或>)b的指数值,分别返回-1,0,+1
    307     if(a.expn < b.expn)
    308         return -1;
    309     else if(a.expn == b.expn)
    310         return 0;
    311     else
    312         return 1;
    313 }
    314 
    315 
    316 void CreatePolyn(polynomial *P, int m)
    317 {
    318     //输入m项的系数和指数,建立表示一元多项式的有序链表P
    319     //最多能输入m项,若输入指数相同的项,则后输入项会被丢弃
    320     Position h;
    321     Position *q = (Position *)malloc(sizeof(Position));//指针使用前一定要先初始化
    322     Position *s = (Position *)malloc(sizeof(Position));
    323     term e;
    324     int i;
    325     InitList(P);
    326     h = GetHead(P);
    327     e.coef = 0.0;
    328     e.expn = -1;
    329     SetCurElem(h, e);
    330     for(i = 1; i <= m; i++)
    331     {
    332         scanf("%f %d", &(e.coef), &(e.expn));
    333         if(!(LocateElem(P, e, q, cmp)))
    334         {
    335             //当前链表不存在该指数项
    336             if(MakeNode(s, e))//生成节点并插入链表
    337                 InsFirst(*q, *s);
    338         }
    339     }
    340 }
    341 
    342 
    343 void PrintPolyn(polynomial *P)
    344 {
    345     //打印输出一元多项式
    346     Position p = P -> head -> next;//p指向链表P的第一个节点
    347     int i = 1;
    348     while(p)
    349     {
    350         if(i != 1)
    351             printf(" + ");
    352         printf("%fx^%d", p->data.coef, p->data.expn);
    353         p = p->next;
    354         i++;
    355     }
    356     printf("
    
    ");
    357 }
    358 
    359 
    360 void AddPolyn(polynomial *Pa, polynomial *Pb)
    361 {
    362     //完成多项式相加运算,即:Pa = Pa + Pb,并销毁一元多项式Pb
    363     term a, b;
    364     int diff;
    365     float sum;
    366     Position *dp = (Position *)malloc(sizeof(Position));//*dp中用于保存被删除节点的地址
    367     Position ha = GetHead(Pa);
    368     Position hb = GetHead(Pb);//ha,hb分别指向Pa,Pb的头节点
    369     Position qa = NextPos(Pa, ha);
    370     Position qb = NextPos(Pb, hb);//qa,qb分别指向Pa,Pb的当前待处理结点
    371     while(qa && qb)
    372     {
    373         //qa与qb均为非空
    374         a = GetCurElem(qa);
    375         b = GetCurElem(qb);//a,b为当前待比较元素
    376         diff = cmp(a, b);
    377         if(diff == -1)
    378         {
    379             //多项式Pa中当前结点的指数值小
    380             ha = qa;
    381             qa = NextPos(Pa, qa);//ha指向qa,qa往后走
    382         }
    383         else if(diff == 0)
    384         {
    385             sum = a.coef + b.coef;
    386             if(sum != 0.0)
    387             {
    388                 //修改多项式Pa中当前结点的系数值
    389                 a.coef = sum;
    390                 SetCurElem(qa, a);//教材此处有误,第二个参数应为term类型
    391                 ha = qa;//此处为后面qa = NextPos(Pa, ha)做准备,使得当qa指向节点不被删除时,ha即相当于qa
    392             }
    393             else
    394             {
    395                 //删除多项式Pa中当前结点
    396                 DelFirst(ha, dp);//此处使用dp,为了跟DelFirst的函数原型匹配,因此与教材写法不同
    397                 FreeNode(*dp);//实际*dp的内容就是qa
    398             }
    399             DelFirst(hb,dp);//此处使用dp,为了跟DelFirst的函数原型匹配,因此与教材写法不同
    400             FreeNode(*dp);//实际*dp的内容就是qb
    401             qb = NextPos(Pb, hb);
    402             qa = NextPos(Pa, ha);
    403         }
    404         else
    405         {
    406             //多项式Pb中当前结点的指数值小
    407             DelFirst(hb, dp);//此处使用dp,为了跟DelFirst的函数原型匹配,因此与教材写法不同
    408             InsFirst(ha, *dp);//将Pb的当前节点接在ha后面,实际*dp的内容就是qb
    409             qb = NextPos(Pb, hb);
    410             ha = NextPos(Pa, ha);//ha指向刚插入的节点,即*dp
    411         }
    412     }//while
    413     if(!ListEmpty(Pb))
    414         Append(Pa, qb);//链接Pb中剩余节点
    415     FreeNode(hb);
    416 }
    417 
    418 
    419 void Multpolyn(polynomial *Pa, polynomial *Pb)
    420 {
    421     //实现两个一元多项式的乘法
    422     float coef0 = 0.0; int expn0 = 0; ElemType a;
    423     Link mid0 = NULL, mid1 = NULL, mid2 = NULL;
    424     Link PaH = GetHead(Pa);
    425     polynomial *pa = (polynomial *)malloc(sizeof(polynomial));
    426     polynomial *Pc = (polynomial *)malloc(sizeof(polynomial));
    427     polynomial *Pd = (polynomial *)malloc(sizeof(polynomial));
    428 
    429     PaH = NextPos(Pa, PaH);//PaH -> next
    430     a = GetCurElem(PaH);//PaH->data
    431     coef0 = a.coef;
    432     expn0 = a.expn;
    433 
    434     InitList(pa); InitList(Pc); InitList(Pd);//init
    435 
    436     pa -> head -> data = GetCurElem(GetHead(Pa));//Pa ->head->data;
    437     mid0 = NextPos(Pa, (GetHead(Pa)));//mid0 = Pa -> head->next
    438     pa -> head -> next = NULL;
    439     mid1 =GetHead(pa);//pa -> head;
    440     while(mid0)
    441     {
    442         //完成Pa的copy
    443         mid1 -> next = (Link)malloc(sizeof(NormLNode));
    444         mid1 = NextPos(pa,mid1);//mid1 -> next,
    445         mid1 ->next = NULL;
    446         mid1->data = GetCurElem(mid0);
    447         //mid1 -> data.coef = mid0 -> data.coef, mid1 -> data.expn = mid0 -> data.expn;
    448         mid0 = NextPos(Pa, mid0);//mid0 -> next;
    449     }
    450     pa -> tail = mid1, pa -> len = Pa -> len;//处理pa的尾结点和长度
    451 
    452     mid0 = NextPos(Pa, GetHead(Pa));//Pa -> head -> next
    453     while(mid0)
    454     {
    455         //完成Pa 与 Pb第一项相乘
    456         mid0 -> data.coef = mid0 -> data.coef * coef0, mid0 -> data.expn = mid0 -> data.expn + expn0;
    457         mid0 = NextPos(Pa, mid0);//mid0 -> next;
    458     }
    459 
    460     //完成后续工作
    461     //mid0 = pa -> head -> next;
    462     //mid1 = Pc -> head;
    463     mid2 = NextPos(Pb,NextPos(Pb,GetHead(Pb)));//Pb -> head -> next -> next;
    464     while(mid2)
    465     {
    466         mid1 = GetHead(Pc);//Pc -> head;
    467         mid0 = NextPos(pa,GetHead(pa));//pa -> head -> next;
    468         while(mid0)
    469         {
    470             mid1 -> next = (Link)malloc(sizeof(NormLNode));
    471             mid1 = NextPos(Pc, mid1);//mid1 -> next;
    472             mid1 -> data.coef = mid0 -> data.coef * mid2 -> data.coef;
    473             mid1 -> data.expn = mid0 -> data.expn +mid2 -> data.expn;
    474             mid0 = NextPos(pa, mid0);//mid0 -> next;
    475         }
    476         mid1 -> next = NULL;//处理尾巴,否则Append()函数中while循环无法判定
    477         Pc -> tail = mid1;
    478         AddPolyn(Pa, Pc);
    479         Pc = (polynomial *)malloc(sizeof(polynomial));
    480         InitList(Pc);
    481         mid2 = NextPos(Pb, mid2);//mid2 -> next;
    482     }
    483     Pa -> len = ListLength(Pa);
    484 }
    485 
    486 
    487 int main()
    488 {
    489 /*******************************测试一元多项式加法*******************************/
    490     polynomial *Pa = (polynomial *)malloc(sizeof(polynomial));
    491     polynomial *Pb = (polynomial *)malloc(sizeof(polynomial));
    492     printf("分别输入一个4项的多项式和一个3项的多项式
    ");
    493     CreatePolyn(Pa, 4);
    494     printf("Pa:
    ");
    495     PrintPolyn(Pa);
    496     CreatePolyn(Pb, 3);
    497     printf("
    Pb:
    ");
    498     PrintPolyn(Pb);
    499     AddPolyn(Pa, Pb);
    500     printf("
    Pa+Pb:
    ");
    501     PrintPolyn(Pa);
    502     DestroyList(Pa);
    503 /*******************************测试一元多项式乘法*******************************/
    504     Pa = (polynomial *)malloc(sizeof(polynomial));
    505     Pb = (polynomial *)malloc(sizeof(polynomial));
    506     printf("分别输入一个4项的多项式和一个3项的多项式
    ");
    507     CreatePolyn(Pa, 4);
    508     printf("Pa:
    ");
    509     PrintPolyn(Pa);
    510     CreatePolyn(Pb, 3);
    511     printf("
    Pb:
    ");
    512     PrintPolyn(Pb);
    513     printf("
    Pa * Pb
    ");
    514     Multpolyn(Pa, Pb);
    515     PrintPolyn(Pa);
    516     DestroyList(Pa);
    517 return 0;
    518 }

    这么多行的代码不容易啊,虽然里面还有好多函数还没有实现,等待慢慢补充吧(虽然可能性不大,过段时间估计看着都头疼了吧,还是要给自己个勇气嘛)。 

  • 相关阅读:
    eclipse部署
    jsp—eclipse配置
    虚拟路径和虚拟主机
    tomcat配置
    初来乍到K
    【转】https://和http://区别
    【转】编码格式
    【转】如何使用瑞萨E10A调试SH系列不带片内FLASH的单片机
    【转】UML
    软考_系统架构师
  • 原文地址:https://www.cnblogs.com/x-1204729564/p/5940280.html
Copyright © 2020-2023  润新知