利用鏈表實現一元多項式的數學運算。如一元多項式
能夠利用其係數𝑝和指數𝑒組合的方式實現鏈式存儲。經過對線性表的基本操做,例如插入,刪除,查找等能夠實現一元多項式的複雜運算,好比加,減,乘,除等運算。
利用鏈表存儲一元多項式,經過對鏈表的操做實現多項式的運算。
對於多項式:𝐴(𝑥) = 7 + 3𝑥 + 9𝑥 + 5𝑥,𝐵(𝑥) = 8𝑥 + 22𝑥 − 9𝑥,實現加,減,乘和微分,輸出結果。
代碼結構爲主分形式,主函數主要爲一些提示,具體的輸入輸出則將參數傳遞到分函數中實現。分函數有建立一元多項式、多項式升冪排序、比較項指數大小、打印多項式、加法運算、減法運算、微分運算和乘法運算等。比較須要關注的是乘法方面的實現,思路是將乘法運算分解爲一系列的加法運算。不過在這裏着實糾結了好多天,原本呢以爲實現乘法本身應該爲它再另外構造一個加法算法提供接口,以便實現它的加法迭代。但是呢,這樣徹底行不通,打印出來的都是0.0,本身徹底不曉得爲何,重複對着代碼思考了好屢次了,以爲沒什麼毛病,但就是行不通——算法
而後呢,大概是前天吧!本身搗弄了半天代碼調試依舊不會的狀況下,決定迴歸輸出調試,因而就在乘法函數裏註釋掉了迭代用的加法,另外在加法循環體外面上頭加了兩句打印語句想看看多項式A和多項式B的每一項相乘後獲得的結果是咋樣的。數組
因而乎奇蹟就誕生了,用x^1+2x^2+3x^3和x^1做爲測試數據,莫名其妙地乘法結果就給打印出來了,徹底沒有用到我費了九牛二虎之力寫出來的迭代加法——數據結構
不過顯示結果仍是有點小bug,顯示出來的是正確結果的相反數,並且主函數返回值也不是正常的0,而是莫名其妙的3221225477函數
接着本着修bug的精神就在乘法函數裏運算部分乘了個負一,這下結果就好看了,以下(返回值依舊不正常)測試
可是,天下怎麼會有憑空掉餡餅這等好事!?本身再用上面給出的複雜測試數據跑了下,這下就沒那麼好看了,得出來的是一個明顯錯誤的結果(。﹏。*)
並且也發現了微分算法部分的一個小bug——
好吧,只能後續繼續改進了,本身應該是在指針理解上出現了問題,回頭去《深刻理解C指針》。
另外,假如用戶輸入的兩個一元多項式爲相同的話,輸出也會有點不正常,須要弄弄。看來有點眉目了spa
11.25這天晚上,我終於弄明白了bug的原因——丫蛋本身沒把Pd給初始化!,並且打印函數若是給它的參數是個空地址的話,它會在那兒瞎轉悠幾圈,而後返回個不是0的返回值,直接結束程序——(還修復了打印首項有時會出現加號的小bug).net
還存在一個問題,就是若是輸入的兩個多項式是相同的話,減法那部分結果會不顯示任何值,而不是0。得弄弄3d
(已解決)指針
OK,下面就貼下本身的代碼了,折騰帶註釋版本,以及去掉無關注釋~純淨版本^_^調試
#include<stdio.h> #include<stdlib.h> typedef struct term{ float coef; int expn; struct term *next; }term,*LinkList; typedef LinkList polynomial; int cmp(LinkList pa,LinkList pb) //比較各項指數大小 { if(pa->expn > pb->expn) return 1; else if(pa->expn == pb->expn) return 0; else return -1; } int LocateElem(LinkList L,LinkList t,LinkList *q) /*定位項數指數大小,使多項式按升冪排序 這裏的*q起到內存保護的做用*/ { LinkList p1=L->next; LinkList p2=L; while(p1) { if(t->expn > p1->expn) { p1=p1->next; p2=p2->next; } else if(t->expn == p1->expn) { *q=p1; return 1; } else { *q=p2; return 0; } } *q=p2; return 0; } void CreatePolyn(polynomial P) //創建多項式所需的各項具體值 { LinkList t; LinkList q; P->coef=0.0; P->expn=-1; P->next=NULL; printf("Please input coefficient and exponent below in format like 1,2 and end with 0,0:\n"); t=(LinkList)malloc(sizeof(term)); // if(!t) exit(OVERFLOW); //借鑑教材《數據結構(C語言版)》的代碼風格...沒用 t->next=NULL; scanf("%f,%d",&t->coef,&t->expn); while(t->coef||t->expn) //約定0,0結束輸入,實現動態輸入多項式 { if(!LocateElem(P,t,&q)) /*每次輸入的指數都應不一樣,轉移指針P->q,並且實現指數排序(這裏 &q 博大精深, 利用指針的指針之妙法確保指針不被篡改,在LocateElem內部又機智地取回———)*/ { t->next=q->next; /*1.q->next = NULL,2.q->next = t, 也改變了P->next的值 P與q共享內存*/ q->next=t; //對t, 頭插法, 對q, 尾插法 } t=(LinkList)malloc(sizeof(term)); // if(!t) exit(OVERFLOW); t->next=NULL; scanf("%f,%d",&t->coef,&t->expn); } } void printPolyn(polynomial P) //打印多項式 { LinkList q; q=P->next; if(!q) { printf("0\n"); //針對兩多項式相同的狀況 } while(q) { if(q->coef==0) /*主要針對微分的常數項狀況,但是出現了下一項變爲首項但其前面加號沒有去掉的狀況。。。*/ { printf(""); q=q->next; /*將此if結構與下面if結構分開,不耦合,解決打印首項帶加號問題*/ } if(q->expn==0) //判斷指數是否爲零及正負,調整輸出格式 { printf("%.2f",q->coef); q=q->next; } else if(q->expn>0) { printf("%.2f*x^%d",q->coef,q->expn); q=q->next; } else { printf("%.2f*x^(%d)",q->coef,q->expn); q=q->next; } if(q) //判斷下一項係數正負,調整輸出格式 { if(q->coef>0) printf("+"); else printf(""); } else printf("\n"); } } void AddPolyn(polynomial Pa,polynomial Pb,polynomial Pc) /*不徹底參照教科書上的思路,而是另外開闢空間存儲和,不釋放原來數據空間*/ { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=Pc; LinkList head=qc; LinkList s; float sum; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: s=(LinkList)malloc(sizeof(term)); //if(!s) exit(OVERFLOW); *s=*qa; qc->next=s; qc=s; qa=qa->next; break; case 0: sum=qa->coef+qb->coef; if(sum!=0.0) { s=(LinkList)malloc(sizeof(term)); //if(!s) exit(OVERFLOW); *s=*qa; s->coef=sum; qc->next=s; qc=s; qa=qa->next; qb=qb->next; } else { qc->next=qa->next; qa=qa->next; qb=qb->next; } break; case 1: s=(LinkList)malloc(sizeof(term)); // if(!s) exit(OVERFLOW); *s=*qb; qc->next=s; qc=s; qb=qb->next; break; } } qc->next=qa?qa:qb; //添加NULL尾巴 Pc=head; } void SubPolyn(polynomial Pa,polynomial Pb,polynomial Pc) /*思路同前面加法,減法變加法,前面加負號, 另外開闢空間存儲差*/ { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=Pc; LinkList head=qc; LinkList s; float differ; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qb) //爲減數加負號 { qb->coef=0-(qb->coef); qb=qb->next; } qb=Pb->next; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: s=(LinkList)malloc(sizeof(term)); // if(!s) exit(OVERFLOW); *s=*qa; qc->next=s; qc=s; qa=qa->next; break; case 0: differ=qa->coef+qb->coef; if(differ!=0.0) { s=(LinkList)malloc(sizeof(term)); // if(!s) exit(OVERFLOW); *s=*qa; s->coef=differ; qc->next=s; qc=s; qa=qa->next; qb=qb->next; } else { qc->next=qa->next; qa=qa->next; qb=qb->next; } break; case 1: s=(LinkList)malloc(sizeof(term)); // if(!s) exit(OVERFLOW); *s=*qb; qc->next=s; qc=s; qb=qb->next; break; } } qc->next=qa?qa:qb; Pc=head; } void AddPolyn_multi(polynomial Pa,polynomial Pb) /*構造一個能夠用於乘法項數迭代的特殊加法,釋放空間,和儲存至Pa,方便迭代累加*/ { LinkList qa=Pa->next; //這兩句致使項數錯位了? LinkList qb=Pb->next; //LinkList qa=Pa; //LinkList qb=Pb; LinkList qc=Pa; LinkList head=qc; LinkList s,s1,s2; float sum; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: qc->next=qa; qc=qa; qa=qa->next; break; case 0: sum=qa->coef+qb->coef; if(sum!=0.0) { s=qb; qa->coef=sum; qc->next=qa; qc=qa; qa=qa->next; qb=qb->next; free(s); } else { s1=qa; s2=qb; qc->next=qa->next; qa=qa->next; qb=qb->next; free(s1); free(s2); } break; case 1: qc->next=qb; qc=qb; qb=qb->next; break; } } qc->next=qa?qa:qb; Pa=head; //千思萬慮老子終於把你給揪出來了,原來是形參搞得鬼!? //printPolyn(Pa); //pirntf("\n"); // free(Pb); /*這句語句挺有問題,要是該指數項惟有Pb纔有呢,相加後依然連接到Pb的內存空間上 */ } void MultiPolyn(polynomial Pa,polynomial Pb,polynomial Pc) /*乘法運算,分解爲一系列的加法運算*/ { LinkList qa=Pa->next; LinkList qb=Pb->next; // LinkList qc=Pc; LinkList head; LinkList qd; LinkList t[20],d[20],h[20];/*,s1,s2; 這些結構體指針數組所對應的空間也應該爲它們加個指數值爲負一的內存! 有啊!!!*/ int i,j; //float product; /******下面添加的這兩句因爲思考疏忽耗費了我大半個月的精力********/ Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; /******以上*********/ while(qa&&qb) { for(j=0;j<20;j++) { d[j]=(LinkList)malloc(sizeof(term)); // if(!d[j]) exit(OVERFLOW); d[j]->coef=0.0; d[j]->expn=-1; d[j]->next=NULL; h[j]=d[j]; qd=qa; for(i=0;i<20;i++) /*二維數組應該有兩個中括號吧? 不,不用,用了指針 */ { //leave it alone! t[i]=(LinkList)malloc(sizeof(term)); // if(!t[i]) exit(OVERFLOW); *t[i]=*qd; t[i]->coef=(qd->coef)*(qb->coef)*(-1); t[i]->expn=qd->expn+qb->expn; d[j]->next=t[i]; d[j]=t[i]; qd=qd->next; if(!qd) { d[j]->next=NULL; break; } } qb=qb->next; if(!qb) { h[j+1]=NULL; break; } } } //printPolyn(h[0]); //printPolyn(h[1]); //printPolyn(h[2]); //printPolyn(h[3]); /*很是奇怪,加了這兩句就能夠運行乘法了,不過打印出來的倒是相反數,並且返回值不是0,而是3221225477 //如今不用那個特殊加法也能夠了!?難道是由於我建立的那僞二維數組實現了地址的複用??? 測試發現,若是碰到空地址,好比這個h[3],會進入一段時間死循環。。。果不其然 //本身應該是在指針的理解上出現了一些問題,得去攻讀下o'reilly的《深刻理解c指針》了 */ //Not effective??? for(j=0;j<20;j++) //對了,每一列指數值不必定相同的吖! { if(!h[j+1]) //原來是你把我辛辛苦苦生成的結果的頭指針給改了的#.# { head=h[j]; break; //不,不是它的錯,是下面的Pc->next出現了兩個-1指數項! } // printPolyn(h[j+1]); AddPolyn_multi(h[j+1],h[j]); head=h[j+1]; } // qc->next=qa?qa:qb; Pc->next=head; //擦!你丫蛋沒初始化就跑進來了 //free(Pb); /*乘法部分邏輯上是沒什麼問題的咯,問題應該是出如今構造加法那裏,哪裏沒有接上 */ } //(後來補充)看來不是構造加法問題 void diff(polynomial Pa, polynomial Pb) { LinkList qa=Pa->next; LinkList head; Pb->coef=0.0; Pb->expn=-1; Pb->next=NULL; head=Pb; // Pb=Pb->next; while(qa) { Pb->next=(LinkList)malloc(sizeof(term)); // if(!Pb->next) exit(OVERFLOW); Pb=Pb->next; Pb->coef=(qa->coef)*(float)(qa->expn); //coef和expn類型不一樣,須要進行類型轉化 Pb->expn=qa->expn-1; Pb->next=NULL; qa=qa->next; } Pb=head; } int main() { polynomial Pa; polynomial Pb; polynomial Pc; polynomial Pd; Pa=(LinkList)malloc(sizeof(term)); Pb=(LinkList)malloc(sizeof(term)); Pc=(LinkList)malloc(sizeof(term)); // Pc->next=NULL; Pd=(LinkList)malloc(sizeof(term)); // Pd->next=NULL; CreatePolyn(Pa); printf("Pa="); printPolyn(Pa); CreatePolyn(Pb); printf("Pb="); printPolyn(Pb); /* Pc = Pa; Pd = Pb; */ printf("\nPa'="); diff(Pa,Pc); printPolyn(Pc); printf("Pa+Pb="); AddPolyn(Pa,Pb,Pc); printPolyn(Pc); printf("Pa-Pb="); SubPolyn(Pa,Pb,Pc); printPolyn(Pc); printf("Pa*Pb="); MultiPolyn(Pa,Pb,Pd); printPolyn(Pd); // printf("\n"); /* printf("Pb'="); diff(Pb,Pc); printPolyn(Pc); */ return 0;
#include<stdio.h> #include<stdlib.h> typedef struct term{ float coef; int expn; struct term *next; }term,*LinkList; typedef LinkList polynomial; int cmp(LinkList pa,LinkList pb) { if(pa->expn > pb->expn) return 1; else if(pa->expn == pb->expn) return 0; else return -1; } int LocateElem(LinkList L,LinkList t,LinkList *q) { LinkList p1=L->next; LinkList p2=L; while(p1) { if(t->expn > p1->expn) { p1=p1->next; p2=p2->next; } else if(t->expn == p1->expn) { *q=p1; return 1; } else { *q=p2; return 0; } } *q=p2; return 0; } void CreatePolyn(polynomial P) { LinkList t; LinkList q; P->coef=0.0; P->expn=-1; P->next=NULL; printf("Please input coefficient and exponent in format like 1,2 and end with 0,0 :\n"); t=(LinkList)malloc(sizeof(term)); t->next=NULL; scanf("%f,%d",&t->coef,&t->expn); while(t->coef||t->expn) { if(!LocateElem(P,t,&q)) { t->next=q->next; q->next=t; } t=(LinkList)malloc(sizeof(term)); t->next=NULL; scanf("%f,%d",&t->coef,&t->expn); } } void printPolyn(polynomial P) { LinkList q; q=P->next; if(!q) { printf("0\n"); } while(q) { if(q->coef==0) { printf(""); q=q->next; } if(q->expn==0) { printf("%.2f",q->coef); q=q->next; } else if(q->expn>0) { printf("%.2f*x^%d",q->coef,q->expn); q=q->next; } else { printf("%.2f*x^(%d)",q->coef,q->expn); q=q->next; } if(q) { if(q->coef>0) printf("+"); else printf(""); } else printf("\n"); } } void AddPolyn(polynomial Pa,polynomial Pb,polynomial Pc) { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=Pc; LinkList head=qc; LinkList s; float sum; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: s=(LinkList)malloc(sizeof(term)); *s=*qa; qc->next=s; qc=s; qa=qa->next; break; case 0: sum=qa->coef+qb->coef; if(sum!=0.0) { s=(LinkList)malloc(sizeof(term)); *s=*qa; s->coef=sum; qc->next=s; qc=s; qa=qa->next; qb=qb->next; } else { qc->next=qa->next; qa=qa->next; qb=qb->next; } break; case 1: s=(LinkList)malloc(sizeof(term)); *s=*qb; qc->next=s; qc=s; qb=qb->next; break; } } qc->next=qa?qa:qb; Pc=head; } void SubPolyn(polynomial Pa,polynomial Pb,polynomial Pc) { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=Pc; LinkList head=qc; LinkList s; float differ; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qb) { qb->coef=0-(qb->coef); qb=qb->next; } qb=Pb->next; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: s=(LinkList)malloc(sizeof(term)); *s=*qa; qc->next=s; qc=s; qa=qa->next; break; case 0: differ=qa->coef+qb->coef; if(differ!=0.0) { s=(LinkList)malloc(sizeof(term)); *s=*qa; s->coef=differ; qc->next=s; qc=s; qa=qa->next; qb=qb->next; } else { qc->next=qa->next; qa=qa->next; qb=qb->next; } break; case 1: s=(LinkList)malloc(sizeof(term)); *s=*qb; qc->next=s; qc=s; qb=qb->next; break; } } qc->next=qa?qa:qb; Pc=head; } void diff(polynomial Pa,polynomial Pb) { LinkList qa=Pa->next; LinkList head; Pb->coef=0.0; Pb->expn=-1; Pb->next=NULL; head=Pb; while(qa) { Pb->next=(LinkList)malloc(sizeof(term)); Pb=Pb->next; Pb->coef=(qa->coef)*(float)(qa->expn); Pb->expn=qa->expn-1; Pb->next=NULL; qa=qa->next; } Pb=head; } void AddPolyn_multi(polynomial Pa,polynomial Pb) { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList qc=qa; LinkList head=qc; LinkList s,s1,s2; float sum; while(qa&&qb) { switch(cmp(qa,qb)) { case -1: qc->next=qa; qc=qa; qa=qa->next; break; case 0: sum=qa->coef+qb->coef; if(sum!=0.0) { s=qb; qa->coef=sum; qc->next=qa; qc=qa; qa=qa->next; qb=qb->next; free(s); } else { s1=qa; s2=qb; qc->next=qa->next; qa=qa->next; qb=qb->next; free(s1); free(s2); } break; case 1: qc->next=qb; qc=qb; qb=qb->next; break; } } qc->next=qa?qa:qb; Pa=head; } void MultiPolyn(polynomial Pa,polynomial Pb,polynomial Pc) { LinkList qa=Pa->next; LinkList qb=Pb->next; LinkList head; LinkList qd; LinkList t[20],d[20],h[20]; int i,j; Pc->coef=0.0; Pc->expn=-1; Pc->next=NULL; while(qa&&qb) { for(j=0;j<20;j++) { d[j]=(LinkList)malloc(sizeof(term)); d[j]->coef=0.0; d[j]->expn=-1; d[j]->next=NULL; h[j]=d[j]; qd=qa; for(i=0;i<20;i++) { t[i]=(LinkList)malloc(sizeof(term)); *t[i]=*qd; t[i]->coef=(qd->coef)*(qb->coef)*(-1); t[i]->expn=qd->expn+qb->expn; d[j]->next=t[i]; d[j]=t[i]; qd=qd->next; if(!qd) { d[j]->next=NULL; break; } } qb=qb->next; if(!qb) { h[j+1]=NULL; break; } } } for(j=0;j<20;j++) { if(!h[j+1]) { head=h[j]; break; } AddPolyn_multi(h[j+1],h[j]); head=h[j+1]; } Pc->next=head; } int main() { polynomial Pa; polynomial Pb; polynomial Pc; polynomial Pd; Pa=(LinkList)malloc(sizeof(term)); Pb=(LinkList)malloc(sizeof(term)); Pc=(LinkList)malloc(sizeof(term)); Pd=(LinkList)malloc(sizeof(term)); CreatePolyn(Pa); printf("Pa="); printPolyn(Pa); CreatePolyn(Pb); printf("Pb="); printPolyn(Pb); printf("\nPa'="); diff(Pa,Pc); printPolyn(Pc); printf("Pa+Pb="); AddPolyn(Pa,Pb,Pc); printPolyn(Pc); printf("Pa-Pb="); SubPolyn(Pa,Pb,Pc); printPolyn(Pc); printf("Pa*Pb="); MultiPolyn(Pa,Pb,Pd); printPolyn(Pd); return 0; }
利用單鏈表實現一元多項式的表示及相加