碎語
一直恐懼、一直害怕,也一直躲避。總是沉醉在if、for、while的舒服綿軟里,這樣是不能有任何進步的!
數據結構是有些難度,但是也只是自己的畏難情結,耐下心,仔細分析,其實並沒有什么好畏懼的!(就像操作系統聽成了天書,慢一點嘛,慢慢消化和理解)。
一道MOOC的基礎題
具體描述摘抄如下:
線性結構2 一元多項式的乘法與加法運算 (20 point(s))
設計函數分別求兩個一元多項式的乘積與和。
輸入格式:
輸入分2行,每行分別先給出多項式非零項的個數,再以指數遞降方式輸入一個多項式非零項系數和指數(絕對值均為不超過1000的整數)。數字間以空格分隔。
輸出格式:
輸出分2行,分別以指數遞降方式輸出乘積多項式以及和多項式非零項的系數和指數。數字間以空格分隔,但結尾不能有多余空格。零多項式應輸出0 0。
輸入樣例:
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 0
解題思路
這題如果放在我沒學數據結構之前,我肯定是兩個數組直接完事了,但是現在我偏不!就是要多學一點,即:結構+動態分配+鏈表指針+函數封裝。
我知道,第一眼看到這種稍微長了一些的代碼,會有點害怕,不過,耐下心來,慢慢理解就好了(*^-^*)
/* 學習使用動態數組和鏈表 */
#include <cstdio>
#include <cstdlib>
//首先從數據結構設計開始
typedef struct PolyNode *Polynomial;
struct PolyNode {
int coef;
int expon;
Polynomial link;
};
//使用的鏈表結構,coef系數,expon指數
//然后考慮main()的程序框架
Polynomial ReadPoly();
Polynomial ReadPoly();
Polynomial Add(Polynomial P1, Polynomial P2);
Polynomial Mult(Polynomial P1, Polynomial P2);
void PrintPoly(Polynomial P);
int main()
{
Polynomial P1, P2, PP, PS;
P1 = ReadPoly();
P2 = ReadPoly();
PP = Mult(P1, P2);
PrintPoly(PP);
PS = Add(P1, P2);
PrintPoly(PS);
return 0;
}
//讀入多項式
//考慮把結點的連接單獨寫一個函數
void Attach(int c, int e, Polynomial *pRear)
{
Polynomial P;
P = (Polynomial)malloc(sizeof(struct PolyNode));
P->coef = c;
P->expon = e;
P->link = NULL;
(*pRear)->link = P;
*pRear = P;
}
//考慮讀入多項式,需要一個頭結點、尾結點、臨時結點
//第一個數字為項數,后面的每一對分別是系數和指數
Polynomial ReadPoly()
{
Polynomial P, Rear, t;
int c, e, N;
scanf("%d", &N);
P = (Polynomial)malloc(sizeof(struct PolyNode)); //需要先申請一個頭結點
P->link = NULL;
Rear = P;
while (N--) {
scanf("%d %d", &c, &e);
Attach(c, e, &Rear);
}
t = P;
P = P->link;
free(t); //最后把申請的頭結點去掉
return P; //返回的第一個結點
}
//下面考慮實現加法和乘法
//加法很簡單,指數相等就相加
Polynomial Add(Polynomial P1, Polynomial P2)
{
Polynomial t1, t2, P, Rear, t; //臨時結點是為了最后去掉頭結點
t1 = P1; t2 = P2;
P = (Polynomial)malloc(sizeof(struct PolyNode));
P->link = NULL;
Rear = P; //初始化尾結點,通過尾插法
while (t1 && t2) {
if (t1->expon == t2->expon) {
if (t1->coef + t2->coef) {
Attach(t1->coef + t2->coef, t1->expon, &Rear);
}
t1 = t1->link;
t2 = t2->link;
}
else if (t1->expon > t2->expon) {
Attach(t1->coef, t1->expon, &Rear);
t1 = t1->link;
}
else {
Attach(t2->coef, t2->expon, &Rear);
t2 = t2->link;
}
}
//下面考慮t1和t2分別剩余的處理
//因為只會存在其中一個有剩余,所以直接按順序接上
while (t1) {
Attach(t1->coef, t1->expon, &Rear);
t1 = t1->link;
}
while (t2) {
Attach(t2->coef, t2->expon, &Rear);
t2 = t2->link;
}
t = P;
P = P->link;
free(t);
return P;
}
//乘法的處理
//先用P2的最高項乘P1把初始的多項式先鏈出來
//然后P1移到第二項,P2從頭來,Rear也從頭來,進行逐項的計算和插入
Polynomial Mult(Polynomial P1, Polynomial P2)
{
Polynomial t1, t2, P, Rear, t;
int c, e;
if (!P1 || !P2) return NULL;
t1 = P1; t2 = P2;
P = (Polynomial)malloc(sizeof(struct PolyNode));
P->link = NULL;
Rear = P;
while (t2) {
Attach(t1->coef * t2->coef, t1->expon + t2->expon, &Rear);
t2 = t2->link;
}
t1 = t1->link;
//現在讓Rear重新指向頭結點,進行后面的逐項插入
//t1從第二項開始,t2從頭開始
while (t1) {
t2 = P2; Rear = P;
while (t2) {
c = t1->coef * t2->coef;
e = t1->expon + t2->expon;
//注意,題目的多項式是由高冪到低冪排序的
while (Rear->link && Rear->link->expon > e)
Rear = Rear->link;
if (Rear->link && Rear->link->expon == e) {
//Rear->link->coef += c; 這里還需要考系數相加為零的情況
if (Rear->link->coef + c)
Rear->link->coef += c;
else {
t = Rear->link;
Rear->link = t->link;
free(t);
}
}
//多定義一個t的目的,就在於會臨時使用
else {
t = (Polynomial)malloc(sizeof(struct PolyNode));
//t-link = NULL;定義空結點才這樣做,現在不是!!
t->coef = c;
t->expon = e;
//現在要把這個結點接在Rear后面
t->link = Rear->link;
Rear->link = t;
Rear = Rear->link;
//現在Rear就指向了剛剛插入的項
}
t2 = t2->link;
}
t1 = t1->link;
}
//最后全部結束,把一開始申請的頭結點去掉
t = P;
P = P->link;
free(t);
return P;
}
//最后一步,將鏈表打印出來
void PrintPoly(Polynomial P)
{
//注意要打印系數和指數之間的空格,且最后沒有空格
if (!P) {
printf("0 0\n");
return;
}
int flag = 1;
while (P) {
if (flag)
flag = 0;
else
printf(" ");
printf("%d %d", P->coef, P->expon);
P = P->link;
}
//最后還少一個換行
printf("\n");
}
