1. 程式人生 > >Polynomial 一元多項式的表示及相加 (線性連結串列實現 嚴蔚敏版)

Polynomial 一元多項式的表示及相加 (線性連結串列實現 嚴蔚敏版)

1、貼程式碼:

#include <iostream>
#include <cstdio>
using namespace std;

struct Node {
	double coef;
	int expn;
	Node *next;
};

void CreatPolynomial(Node *&head, int n)		//	生成帶表頭結點的單鏈表,除頭結點外另生成n個結點
{
	head = (Node *)malloc(sizeof(Node));
	head->coef = 0;
	head->expn = 0;
	head->next = NULL;							//	初始化頭結點
	cout << "請輸入各項係數及指數:" << endl;
	Node *p = head;
	for(int i = 0; i < n; i++) {
		p->next = (Node *)malloc(sizeof(Node));	//	生成新結點,尾插入生成連結串列
		p = p->next;
		cin >> p->coef >> p->expn;
		p->next = NULL;
	}
}

void PrintPolynomial(Node *&head)
{
	if(head->next == NULL)							//	結果是0時直接輸出0
		putchar('0');
	else {
		for(Node *p = head->next; p != NULL; p = p->next) {
			if(p != head->next && p->coef >0)		//	當p非首項且指向的係數為正時才輸出'+'
				putchar('+');						//	之前只判定了p->coef >0
			
			if(p->coef == 1) {						//	係數為1或-1時特殊處理
				if(p->expn == 0)
					putchar('1');					//	判斷條件不能寫在一起:
			}										//	if(p->coef == 1 && p->expn == 0) putchar('1');
			else if(p->coef == -1)
				putchar('-');
			else
				cout << p->coef;
			
			switch(p->expn) {						//  指數為0或1時特殊處理
				
			case 0:
				break;
				
			case 1:
				putchar('x');
				break;
				
			default:
				p->expn < 0 ? printf("x^(%d)", p->expn) : printf("x^%d", p->expn);	//	指數小於0時打括號
				break;
			}
		}
	}
	cout << endl;
}
//	上面的函式中若係數為int型,那麼也可以改為switch結構,這是C語言的缺陷?

void Free(Node *&head)
{
	Node *q = NULL;
	for(Node *p = head; p != NULL; p = q) {
		q = p->next;
		free(p);
	}
}

char cmp(int a, int b)
{
	if(a > b)
		return '>';
	if(a < b)
		return '<';
	return '=';
}

void AddPolynomial(Node *&pA, Node *&pB)		//	傳進兩個連結串列的頭指標
{
	Node *ha = pA;
	Node *hb = pB;
	Node *qa = ha->next;						//	ha, hb分別跟在qa, qb的後一位置
	Node *qb = hb->next;						//	qa, qb分別指向Pa, Pb中當前比較元素
	while(qa && qb) 
	{
		double sum = 0;
		int a = qa->expn;
		int b = qb->expn;
		switch( cmp(a, b) ) {
			
		case '<':
			ha = qa;
			qa = qa->next;						//	非ha = ha->next;
			break;
			
		case '=':			
			sum = qa->coef + qb->coef;
			if(sum != 0.0) {
				qa->coef = sum;
				ha = qa;				
			}
			else {
				if(ha->next != qa)
					cout << "Error: ha->next != qa" << endl;
				ha->next = ha->next->next;		//  刪除和為0的結點,ha不變,還在qa後一位置
				free(qa);
			}
			if(hb->next != qb)
				cout << "Error: hb->next != qb" << endl;
			hb->next = hb->next->next;
			free(qb);
			qb = hb->next;
			qa = ha->next;
			break;
			
		case '>':
			hb->next = hb->next->next;			//	刪除qb指向的結點
			qb->next = ha->next;				//	將qb插入ha後qa前
			ha->next = qb;
			
			qb = hb->next;						//	not qb = ha->next
			ha = ha->next;
			break;
			
		default:
			cout << "Error!" << endl;
			break;
		}
	}
	if(qb)
		ha->next = qb;
	free(hb);
}

int main(void)
{
//	freopen("cin.txt", "r", stdin);
	Node *A = NULL;
	Node *B = NULL;
	int lenA;
	int lenB;
	while(cout << "請輸入A的項數:" << endl, cin >> lenA) {
		CreatPolynomial(A, lenA);					//	生成A連結串列		
		cout << "請輸入B的項數:" << endl;			//	生成B連結串列
		cin >> lenB;
		CreatPolynomial(B, lenB);
		
		cout << " A = ";							//	輸出A連結串列
		PrintPolynomial(A);
		cout << " B = ";							//	輸出B連結串列
		PrintPolynomial(B);
		
		AddPolynomial(A, B);						//	A = A + B
		cout << "A+B= ";
		PrintPolynomial(A);							//	輸出和
		cout << endl;
		
		Free(A);									//	務必釋放結點
	}
	return 0;
}

2、執行:

附一些寶貴的測試資料:

5
-2 -1
-3 0
8 1
3 5
-2 7
5
4 -1
6 0
3 5
1 7
1 8

3
2 1
5 8
-3.1 11
3
7 0
-5 8
11 9

4
6 -3
-1 1
4.4 2
-1.2 9
3
6 -3
-4.4 2
-7.8 15

6
1 0
1 1
1 2
1 3
1 4
1 5
2
-1 3
-1 4

2
1 1
1 3
2
-1 1
-1 3

2
1 1
1 100
2
1 100
1 200

3
1 1
1 2
1 3
0

以上資料的執行結果:


3、想法:

1)那個函式完全對著書寫的,不過之前吃了些苦頭奮鬥。用帶頭結點的連結串列好啊!(針對本題,不然首項的那些特殊情況要煩死人。)

2)在輸出上花了些工夫,不過還怕有些小錯誤,之前也想了很多情況,夠複雜的了!

2012/5/1更新:

程式碼中“初始化”結構體可用memset