詳解線性結構 —— 一元多項式的乘法與加法運算

原題

設計函數分別求兩個一元多項式的乘積與和。ide

輸入格式:

輸入分2行,每行分別先給出多項式非零項的個數,再以指數遞降方式輸入一個多項式非零項係數和指數(絕對值均爲不超過1000的整數)。數字間以空格分隔。函數

輸出格式:

輸出分2行,分別以指數遞降方式輸出乘積多項式以及和多項式非零項的係數和指數。數字間以空格分隔,但結尾不能有多餘空格。零多項式應輸出0 0。spa

輸入樣例:

4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1設計

輸出樣例:

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 03d

 原題連接指針

 

題解

  這道題目不算太難,就是代碼比較長。下面會給出這道題最直接簡單的解法。code

  首先,咱們是經過鏈表的形式來存儲多項式,每個鏈表節點包含有係數,指數,以及指向下一個節點的指針。blog

1 struct LNode{
2     int coef, exp;
3     LNode *next;
4 };

  咱們的main函數以下:排序

1 int main() {
2     LNode *L1 = creatList();        // 建立第1個多項式 
3     LNode *L2 = creatList();        // 建立第2個多項式 
4     
5     printList(polyMult(L1, L2));    // 兩個多項式求和,並打印輸出 
6     printList(polyAdd(L1, L2));     // 兩個多項式相乘,並打印輸出 
7     
8     return 0;
9 }

  其中,creatList函數是用來建立一個鏈表,函數代碼以下:get

 1 LNode* creatList() {
 2     int n;
 3     scanf("%d", &n);
 4 
 5     LNode *head = new LNode;    // 爲頭指針設立一個頭節點
 6     head -> next = NULL;
 7     LNode *p = head;
 8 
 9     while (n--) {
10         LNode *q = new LNode;
11         q -> next = NULL;
12         scanf("%d %d", &q -> coef, &q -> exp);
13         p = p -> next = q;
14     }
15 
16     return head;
17 }
creatList

  須要注意的是,咱們的鏈表都帶有頭指針。

  下面來說解polyAdd函數。

 1 LNode* polyAdd(LNode *L1, LNode *L2) {
 2     // 讓指針後移一個單位,指向第一個存放數據的節點
 3     L1 = L1 -> next;
 4     L2 = L2 -> next;
 5 
 6     // 建立一個求和鏈表
 7     LNode *head = new LNode;
 8     head -> next = NULL;
 9     // 指向求和鏈表的最後一個節點,經過尾插法來插入新節點
10     LNode *p = head;
11 
12     while (L1 && L2) {
13         LNode *q = new LNode;
14         q -> next = NULL;
15 
16         // L1所指向節點的exp大於L2所指向節點的exp
17         if (L1 -> exp > L2 -> exp) {
18             q -> coef = L1 -> coef;
19             q -> exp = L1 -> exp;
20             p = p -> next = q;
21             L1 = L1 -> next;
22         }
23         // L2所指向節點的exp大於L1所指向節點的exp
24         else if (L1 -> exp < L2 -> exp) {
25             q -> coef = L2 -> coef;
26             q -> exp = L2 -> exp;
27             p = p -> next = q;
28             L2 = L2 -> next;
29         }
30         // L2所指向節點的exp等於L1所指向節點的exp
31         else {
32             q -> coef = L1 -> coef + L2 -> coef;
33             q -> exp = L1 -> exp;
34 
35             // 係數求和後爲0,不須要插入,同時把申請的節點釋放掉
36             if (q -> coef == 0) delete q;
37             // 係數不爲零就要插入
38             else p = p -> next = q;
39 
40             L1 = L1 -> next;
41             L2 = L2 -> next;
42         }
43     }
44 
45     // 找到不爲空的那個多項式
46     LNode *L = L1 ? L1 : L2;
47     // 把不爲空的多項式剩餘的節點都接到求和鏈表的後面
48     while (L) {
49         p = p -> next = L;
50         L = L -> next;
51     }
52 
53     return head;
54 }
polyAdd

  因爲鏈表帶有頭節點,因此先讓指針後移一個單位,指向第一個存放數據的節點。

  而後咱們須要建立一個鏈表,用來存儲兩個多項式相加後的結果。

  以後咱們進入循環,來進行多項式的相加,循環的條件是兩個多項式都存在,不爲空。

  因爲題目的要求是按指數遞降方式輸出,因此咱們按下面的判斷規則來把相加的結果插入到新的鏈表中。

  1.若是L1所指向節點的exp大於L2所指向節點的exp,也就是L1 -> exp > L2 -> exp,則不須要相加,只須要把L1所指向節點的coef和exp拷貝到新的節點中,而後把新節點插入到求和的鏈表中。同時,還要讓L1指針向後移動一個位置。

  2.若是L2所指向節點的exp大於L1所指向節點的exp,也就是L2 -> exp > L1 -> exp,則不須要相加,只須要把L2所指向節點的coef和exp拷貝到新的節點中,而後把新節點插入到求和的鏈表中。同時,還要讓L2指針向後移動一個位置。

  3.若是L2所指向節點的exp等於L1所指向節點的exp,也就是L2 -> exp == L1 -> exp,咱們就須要對兩個這節點的coef進行相加,把相加的結果存放到新節點的coef中,同時也要把當前的exp存放到新節點中。再來對相加後的coef進行判斷,若是相加後的coef == 0,那麼就不須要把它插入到求和的鏈表中,同時把新節點經過關鍵字delete刪除。若是相加後的coef != 0,咱們就把新節點插入到求和的鏈表中。最後,別忘了讓L1和L2向後移動一個位置。

  當退出循環後,說明其中一個多項式已經爲空了,這個時候咱們只須要找到那個尚未空的多項式,而後把該多項式剩餘的那部分節點都接到求和鏈表的後面,就完成了兩個多項式求和這個過程了。固然,若是退出時兩個多項式都爲空了,咱們一樣能夠把其中的一個多項式接到求和鏈表的後面,只不過這個時候接的是NULL。

  下面來是polyMult函數。

 1 LNode* polyMult(LNode *L1, LNode *L2) {
 2     // 讓指針後移一個單位,指向第一個存放數據的節點
 3     L1 = L1 -> next;
 4     L2 = L2 -> next;
 5 
 6     //  建立一個求積鏈表
 7     LNode *head = new LNode;
 8     head -> next = NULL;
 9 
10     while (L1) {
11         // 因爲在內層循環中L2指針會改變,須要用headOfL2來保存第二個多項式鏈表的首地址
12         LNode *headOfL2 = L2;
13 
14         while (L2) {
15             LNode *p = new LNode;
16             p -> next = NULL;
17             // 新節點存放多項式相乘的結果
18             p -> coef = L1 -> coef * L2 -> coef;
19             p -> exp = L1 -> exp + L2 -> exp;
20 
21             // 從頭開始遍歷求積鏈表,找到指數比新節點小的那個節點,返回那個節點的前一個節點的地址
22             LNode *pre = head;
23             while (pre -> next && pre -> next -> exp > p -> exp) {
24                 pre = pre -> next;
25             }
26             //  pre -> next == NULL或者pre -> next -> exp < p -> exp,直接插入就能夠了
27             if (pre -> next == NULL || pre -> next -> exp < p -> exp) {
28                 p -> next = pre -> next;
29                 pre -> next = p;
30             }
31             //  pre -> next -> exp == p -> exp,不須要插入新節點,要判斷是否須要刪除求積鏈表中指數相同的那個節點
32             else {
33                 // 指數相同的兩個節點進行係數相加
34                 pre -> next -> coef += p -> coef;
35                 // 若是係數爲零,就要刪除那個節點
36                 if (pre -> next -> coef == 0) {
37                     LNode *temp = pre -> next;
38                     pre -> next = temp -> next;
39                     delete temp;
40                 }
41                 // 不管怎麼樣都不須要把新節點插入,把它釋放放
42                 delete p;
43             }
44 
45             L2 = L2 -> next;
46         }
47 
48         // 讓L2從新指向第二個多項式鏈表的表頭
49         L2 = headOfL2;
50         L1 = L1 -> next;
51     }
52 
53     return head;
54 }
polyMult

  咱們經過逐項相乘的方法來實現兩個多項式的求和。好比說,對於x2 - 1和x + x2 + 1這兩個多項式,咱們先讓第一個多項式中的x2去乘第二個多項式的每一項,獲得x3 + x4 + x2,把結果插入到求積的鏈表中,而後再讓第一個多項式中的下一個項-1去乘第二個多項式的每一項,獲得多項式-x - x2 - 1。固然,在程序中咱們不是先把結果算出來再插入到求積鏈表中,而是每計算一次,就把該結果插入到求積鏈表中。因此,真正難的地方就在於,如何把計算結果插入到求積鏈表中,同時保證咱們的結果是按指數遞降的方式存放的。

  來看咱們的程序,爲了實現上面說的逐項相乘,首先咱們須要一個嵌套循環。外層循環的條件是第一個多項式不爲空,內層循環的條件是第二個多項式不爲空。這樣咱們就實現了用第一個多項式的每一項去乘以第個多項式的每一項。

  咱們是在內層的循環中進行多項式相乘計算,以及插入操做。

  先把多項式相乘後的coef和exp存放到新節點中,而後把它插入到求積鏈表中。

  何時插入呢?就是在求積鏈表中找到那個指數exp比新節點的指數exp小的那個節點,而後咱們把新節點的插入到那個指數exp比它小的節點以前就能夠了。

  因此,爲了把新節點插入到該節點的前面,咱們應該經過一個循環來遍歷找到該節點的前驅,也就是說找到該節點的前一個節點。否則若是咱們只獲得該節點的地址,是不能夠把新節點插入到該節點的前面的。因此咱們經過pre這個指針來存放前一個節點的地址。並經過pre -> next來表示前一個節點的下一個節點,也就是須要與新節點進行比較的節點。循環的條件就是進行比較的節點不爲空,也就是pre -> next != NULL,以及進行比較的節點的指數exp大於新節點的指數exp,也就是pre -> next -> next > p -> exp。

  退出循環有三種可能,第一種是pre -> next == NULL,也就是說,新節點的指數比求積鏈表中的任何一個節點的指數都要小,咱們直接把新節點插入到表尾就能夠了。

  第二種是pre -> next -> exp < p -> exp,咱們找到了比新節點指數小的節點,並獲得了該節點的前一個節點的地址,咱們就能夠把新節點插入到比它指數小的那個節點的前面。

  第三種是pre-> next -> exp == p -> exp,因爲指數都同樣,這個時候咱們就要進行係數相加,並對相加的結果加以判斷。若是相加後的係數爲零,那麼咱們應該去除掉這一項,在求積鏈表中把該節點釋放掉。若是不爲零,就直接在求積鏈表中修改該節點的係數就能夠了,不須要把新節點插入到求積鏈表中。

  最後是printList函數。

 1 void printList(LNode *L) {
 2     // 這個if語句的做用是,若是傳入的多項式爲空,爲了讓它也有東西能夠輸出,咱們應該爲他加入0,0這個項
 3     if (L -> next == NULL) {
 4         LNode *p = new LNode;
 5         p -> next = NULL;
 6         p -> coef = p -> exp = 0;
 7         L -> next = p;
 8     }
 9 
10     L = L -> next;
11     while (L) {
12         printf("%d %d", L -> coef, L -> exp);
13         if (L -> next) putchar(' ');
14         else putchar('\n');
15 
16         L = L -> next;
17     }
18 }
printList

  好了到此爲止,咱們已經把一元多項式的乘法與加法運算這個問題解決了,下面給出完整的代碼。

 

完整代碼

  1 #include <cstdio>
  2 
  3 struct LNode{
  4     int coef, exp;
  5     LNode *next;
  6 };
  7 
  8 LNode* creatList();
  9 void printList(LNode *L);
 10 LNode* polyAdd(LNode *L1, LNode *L2);
 11 LNode* polyMult(LNode *L1, LNode *L2);
 12 
 13 int main() {
 14     LNode *L1 = creatList();
 15     LNode *L2 = creatList();
 16 
 17     printList(polyMult(L1, L2));
 18     printList(polyAdd(L1, L2));
 19 
 20     return 0;
 21 }
 22 
 23 LNode* creatList() {
 24     int n;
 25     scanf("%d", &n);
 26 
 27     LNode *head = new LNode;
 28     head -> next = NULL;
 29     LNode *p = head;
 30 
 31     while (n--) {
 32         LNode *q = new LNode;
 33         q -> next = NULL;
 34         scanf("%d %d", &q -> coef, &q -> exp);
 35         p = p -> next = q;
 36     }
 37 
 38     return head;
 39 }
 40 
 41 void printList(LNode *L) {
 42     if (L -> next == NULL) {
 43         LNode *p = new LNode;
 44         p -> next = NULL;
 45         p -> coef = p -> exp = 0;
 46         L -> next = p;
 47     }
 48 
 49     L = L -> next;
 50     while (L) {
 51         printf("%d %d", L -> coef, L -> exp);
 52         if (L -> next) putchar(' ');
 53         else putchar('\n');
 54 
 55         L = L -> next;
 56     }
 57 }
 58 
 59 LNode* polyAdd(LNode *L1, LNode *L2) {
 60     L1 = L1 -> next;
 61     L2 = L2 -> next;
 62 
 63     LNode *head = new LNode;
 64     head -> next = NULL;
 65     LNode *p = head;
 66 
 67     while (L1 && L2) {
 68         LNode *q = new LNode;
 69         q -> next = NULL;
 70 
 71         if (L1 -> exp > L2 -> exp) {
 72             q -> coef = L1 -> coef;
 73             q -> exp = L1 -> exp;
 74             p = p -> next = q;
 75             L1 = L1 -> next;
 76         }
 77         else if (L1 -> exp < L2 -> exp) {
 78             q -> coef = L2 -> coef;
 79             q -> exp = L2 -> exp;
 80             p = p -> next = q;
 81             L2 = L2 -> next;
 82         }
 83         else {
 84             q -> coef = L1 -> coef + L2 -> coef;
 85             q -> exp = L1 -> exp;
 86 
 87             if (q -> coef == 0) delete q;
 88             else p = p -> next = q;
 89 
 90             L1 = L1 -> next;
 91             L2 = L2 -> next;
 92         }
 93     }
 94 
 95     LNode *L = L1 ? L1 : L2;
 96     while (L) {
 97         p = p -> next = L;
 98         L = L -> next;
 99     }
100 
101     return head;
102 }
103 
104 LNode* polyMult(LNode *L1, LNode *L2) {
105     L1 = L1 -> next;
106     L2 = L2 -> next;
107 
108     LNode *head = new LNode;
109     head -> next = NULL;
110 
111     while (L1) {
112         LNode *headOfL2 = L2;
113 
114         while (L2) {
115             LNode *p = new LNode;
116             p -> next = NULL;
117             p -> coef = L1 -> coef * L2 -> coef;
118             p -> exp = L1 -> exp + L2 -> exp;
119 
120             LNode *pre = head;
121             while (pre -> next && pre -> next -> exp > p -> exp) {
122                 pre = pre -> next;
123             }
124             if (pre -> next == NULL || pre -> next -> exp < p -> exp) {
125                 p -> next = pre -> next;
126                 pre -> next = p;
127             }
128             else {
129                 pre -> next -> coef += p -> coef;
130                 if (pre -> next -> coef == 0) {
131                     LNode *temp = pre -> next;
132                     pre -> next = temp -> next;
133                     delete temp;
134                 }
135                 delete p;
136             }
137 
138             L2 = L2 -> next;
139         }
140 
141         L2 = headOfL2;
142         L1 = L1 -> next;
143     }
144 
145     return head;
146 }

 

擴展

  咱們來擴展一下,題目是以指數遞降方式輸入一個多項式非零項係數和指數,咱們來改變一下輸入的條件。就是,咱們不要求以指數遞降方式來輸入,能夠隨便輸入,但要求輸入完成後,多項式是以指數遞降的方式來排序的。咱們只須要對creatList函數稍微改寫就能夠了。

 1 LNode* creatList() {
 2     int n;
 3     scanf("%d", &n);
 4 
 5     LNode *head = new LNode;
 6     head -> next = NULL;
 7 
 8     while (n--) {
 9         LNode *p = new LNode;
10         p -> next = NULL;
11         scanf("%d %d", &p -> coef, &p -> exp);
12 
13         LNode *pre = head;
14         while (pre -> next && pre -> next -> exp > p -> exp) {
15             pre = pre -> next;
16         }
17         p -> next = pre -> next;
18         pre -> next = p;
19     }
20 
21     return head;
22 }

  有沒有發現,插入的過程和上面多項式求積後插入很像,其實他們的原理是同樣的。這樣子,咱們就不須要按照指數遞降的順序來輸入,也能夠實現指數遞降得順序輸出。

相關文章
相關標籤/搜索