數據結構之一元多項式的加法和乘法


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("\n\n");
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項的多項式\n");
493     CreatePolyn(Pa, 4);
494     printf("Pa:\n");
495     PrintPolyn(Pa);
496     CreatePolyn(Pb, 3);
497     printf("\nPb:\n");
498     PrintPolyn(Pb);
499     AddPolyn(Pa, Pb);
500     printf("\nPa+Pb:\n");
501     PrintPolyn(Pa);
502     DestroyList(Pa);
503 /*******************************測試一元多項式乘法*******************************/
504     Pa = (polynomial *)malloc(sizeof(polynomial));
505     Pb = (polynomial *)malloc(sizeof(polynomial));
506     printf("分別輸入一個4項的多項式和一個3項的多項式\n");
507     CreatePolyn(Pa, 4);
508     printf("Pa:\n");
509     PrintPolyn(Pa);
510     CreatePolyn(Pb, 3);
511     printf("\nPb:\n");
512     PrintPolyn(Pb);
513     printf("\nPa * Pb\n");
514     Multpolyn(Pa, Pb);
515     PrintPolyn(Pa);
516     DestroyList(Pa);
517 return 0;
518 }

這么多行的代碼不容易啊,雖然里面還有好多函數還沒有實現,等待慢慢補充吧(雖然可能性不大,過段時間估計看着都頭疼了吧,還是要給自己個勇氣嘛)。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM