一元多項式是鏈表的一個應用。
還是老規矩:
程序在碼雲上可以下載。
地址:https://git.oschina.net/601345138/DataStructureCLanguage.git
簡單看看程序的實現:
//------------------------------------引入的頭文件--------------------------------------
#include <stdio.h> //使用了標準庫函數 printf(),scanf()
#include <stdlib.h> //使用了動態內存分配函數 malloc(),free()
//------------------------------------自定義符號常量------------------------------------
#define OVERFLOW -2 //內存溢出錯誤常量
#define OK 1 //表示操作正確的常量
#define ERROR 0 //表示操作錯誤的常量
#define TRUE 1
#define FALSE 0
//-----------------------------------自定義數據類型-------------------------------------
typedef int Status; //用typedef給int起個別名,也便於程序的維護
typedef float ElemType; //用typedef給float起個別名,也便於程序的維護
//一元多項式的C語言表示
typedef struct{ //項的表示,多項式的項作爲LinkList的數據元素
float coef; //係數
int expn; //指數
}PElemType; //數據類型名PElemType
typedef struct LNode{
PElemType data; //上面被typedef定義的結構體類型作爲一元多項式的元素類型
struct LNode *next; //單鏈表的指針域
}* Link,* Position;
typedef struct{ //鏈表類型
Link head,tail; //頭指針head和尾指針tail分別指向線性鏈表中的頭結點和尾結點
int len; //指示線性鏈表中數據元素的個數
}LinkList;
typedef LinkList Polynomial; //用帶表頭結點的有序鏈表表示一元多項式
//******************************** 一元多項式的基本操作 ************************************
//------------------------------ 1.線性表的基本算法 ----------------------------------------
Status MakeNode(Link &p, PElemType e){ //生成結點
//分配由p指向值爲e的結點
if(!(p = (Link)malloc(sizeof(LNode)))){
printf("內存分配失敗!\n");
exit(OVERFLOW);
}//if
p->data = e;
return TRUE;
}//MakeNode
void FreeNode(Link &p){ //釋放結點
//釋放p所指向的結點
free(p);
p = NULL;
}//FreeNode
void InitList(LinkList &L){ //初始化表
//構造一個空的線性鏈表L
Link p = NULL;
if(!(p = (Link)malloc(sizeof(LNode)))){
printf("內存分配失敗!\n");
exit(OVERFLOW);
}//if
else{
p->next = NULL;
L.head = L.tail = p;
L.len = 0;
}//if
}//InitList
void ClearList(LinkList &L){ //清空鏈表
//將線性鏈表L置成空表,並釋放原鏈表的結點空間
Link p = NULL,q = NULL;
if(L.head != L.tail){ //不是空表
p = q = L.head->next;
L.head->next = NULL;
while(p != L.tail){
p = q->next;
free(q);
q = p;
}//while
free(q);
L.tail = L.head;
L.len = 0;
}//if
}//ClearList
void DestoryList(LinkList &L){ //銷燬鏈表
//銷燬線性鏈表L,L不再存在
ClearList(L); //清空鏈表
FreeNode(L.head);
L.tail = NULL;
L.len = 0;
}//DestoryList
void InsFirst(LinkList &L, Link h, Link s){ //插入結點 (形參增加L,因爲需要修改L)
//已知h爲線性表的頭結點,將s所指結點插在第一個結點之前
s->next = h->next;
h->next = s;
if(h == L.tail) { //h指向尾結點
L.tail = h->next; //修改尾指針
}//if
L.len++;
}//InsFirst
Status DelFirst(LinkList &L, Link h, Link &q){ //刪除結點 (形參增加L,因爲需要修改L)
//h指向L的一個結點,把h當做頭結點,刪除鏈表中第一個結點並以q返回
//若鏈表爲空(h指向尾結點),q=NULL,返回FALSE
q = h->next;
if(q){ //鏈表非空
h->next = q->next;
if(!h->next) { //刪除尾結點
L.tail = h; //修改尾指針
}//if
L.len--;
return OK;
}//if
else {
return ERROR;
}//else
}//DelFirst
void Append(LinkList &L, Link s){ //追加
//將指針s(s->data爲第一個數據元素)所指(彼此以指針相鏈,以NULL結尾)的
//一串結點鏈接在線性鏈表L的最後一個結點之後,並改變鏈表L的尾指針指向新的尾結點
int i = 1;
L.tail->next = s;
while(s->next){
s = s->next;
i++;
}//while
L.tail = s;
L.len += i;
}//Append
Position PriorPos(LinkList L, Link p){ //獲取前驅位置
//已知p指向線性鏈表中的一個結點,返回p所指結點的直接前驅位置,若無直接前驅,則返回NULL
Link q = NULL;
q = L.head->next;
if(q == p) { //無前驅
return NULL;
}//if
else{
while(q->next != p) { //q不是p的直接前驅
q = q->next;
}//while
return q;
}//else
}//PriorPos
void SetCurElem(Link p,PElemType e){ //設置(更新)元素的值
//已知p指向線性鏈表中的一個結點,用e更新p所指結點中的數據元素的值
p->data=e;
}//SetCurElem
PElemType GetCurElem(Link p){ //獲取元素的值
//已知p指向線性鏈表中的一個結點,返回p所指結點數據元素的值
return p->data;
}//GetCurElem
Position GetHead(LinkList L){ //獲得頭結點位置
//返回線性鏈表L中頭結點的位置
return L.head;
}//GetHead
Position NextPos(Link p){ //獲得後繼位置
//已知p指向線性鏈表中的一個結點,返回p所指結點直接後繼的位置
return p->next;
}//NextPos
Status ListEmpty(LinkList L){ //判空
//若線性鏈表L爲空表,則返回TRUE,否則返回FALSE
if(L.len) {
return FALSE;
}//if
else {
return TRUE;
}//else
}//ListEmpty
//--------------------------------2.一元多項式的算法------------------------------------------
//-----------------------------有序比較函數------------------------------
int compare(PElemType a, PElemType b){ //比較a,b指數值大小
//依a的指數值<(或=)(或>) b的指數值,分別返回-1,0和+1
if(a.expn < b.expn) {
return -1;
}//if
else if(a.expn == b.expn) {
return 0;
}//else if
else{
return 1;
}//else
}//compare
//-------------------------------定位函數--------------------------------
Status LocateElem(Polynomial P, PElemType e, Position &q,
int (*compare)(PElemType ,PElemType)){ //定位函數
/*若有序鏈表L中存在與e滿足判定函數compare()取值爲0的元素,
則q指示L中第一個值爲e的結點的位置,並返回TRUE;
否則q指示第一個與e滿足判定函數compare()取值>0的元素的前驅的位置,並返回FALSE */
Link p = P.head, p1 = NULL;
do{
p1 = p;
p = p->next;
}while(p && (compare(p->data, e) < 0)); //沒到表尾且p->data.expn < e.expn
if(!p || compare(p->data, e) > 0){ //到表尾或compare(p->data,e)>0
q = p1;
return FALSE;
}//if
else{ //找到
q = p;
return TRUE;
}//else
}//LocateElem
//----------------------------------------按序插入--------------------------------------
void OrderInsertMerge(Polynomial &P, PElemType e,
int (*compare)(PElemType ,PElemType)){ //按序插入
//按有序判定函數compare()的約定,將值爲e的結點插入或合併到升序鏈表L的適當位置
Position q = NULL, s = NULL;
if(LocateElem(P, e, q, compare)){ //L中存在該指數項
q->data.coef += e.coef; //改變當前結點係數的值
if(!q->data.coef){ //係數爲0
//刪除多項式L中的當前結點
if(!(s = PriorPos(P, q))){ //s爲當前結點的前驅且q無前驅
s = P.head;
}//if
DelFirst(P, s, q);
FreeNode(q);
}//if
}//if
else{ //生成指數項並鏈入鏈表
MakeNode(s, e); //生成結點
InsFirst(P, q, s);
}//else
}//OrderInsertMerge
//-----------------------------一元多項式的創建與銷燬---------------------------------------
void createPolyn(Polynomial &P, int m){ //一元多項式的創建
//輸入m項的係數和指數,建立表示一元多項式的有序鏈表P
PElemType e;
Position h = NULL, q = NULL, s = NULL;
InitList(P);
h = GetHead(P); //得到頭結點的位置,頭結點的位置爲函數的返回值
e.coef = 0.0;
e.expn = -1;
SetCurElem(h, e); //設置頭結點的數據元素
for(int i = 1; i <= m; ++i){ //依次輸入m個非零項
printf("請輸入多項式%d的係數:",i);
scanf("%f", &e.coef);
printf("請輸入多項式%d的指數:",i);
scanf("%d", &e.expn);
if(!LocateElem(P, e, q, compare)){ //當前鏈表中不存在該指數項
if(MakeNode(s, e)) //生成結點並插入鏈表
InsFirst(P, q, s);
}//if
}//for
}//createPolyn
void DestoryPolyn(Polynomial &P){ //一元多項式的銷燬
//銷燬一元多項式P
DestoryList(P);
} //AddPolyn
//-------------------------------計算一元多項式項數---------------------------------
int PolynLength(Polynomial P){
//返回一元多項式的項數
return P.len;
}//AddPolyn
//--------------------------------打印一元多項式-----------------------------------
void Print(PElemType e){
printf("%.2fx^%d", e.coef, e.expn);
}//Print
void PrintPolyn(Polynomial P, void (*Print)(PElemType)){
//打印輸出一元多項式P
Link q = NULL;
q = P.head->next; //q指向第一個結點
printf(" f(x)=");
while(q){
Print(q->data);
if(q->next && q->next->data.coef > 0){
printf("+");
}//if
q = q->next;
}//while
printf("\n");
}//PrintPolyn
//-----------------------------一元多項式的運算(+ - *)--------------------------------
void AddPolyn(Polynomial &Pa, Polynomial &Pb){
//多項式加法:Pa=Pa+Pb ,利用兩個多項式的結點構成“和多項式”
Position ha = NULL, hb = NULL, qa = NULL, qb = NULL;
float sum = 0;
PElemType a, b;
ha = GetHead(Pa);
hb = GetHead(Pb);
qa = NextPos(ha);
qb = NextPos(hb);
while(qa && qb){
a = GetCurElem(qa);
b = GetCurElem(qb);
switch(compare(a, b)){
case -1: { //多項式PA中當前結點指數值最小
ha = qa;
qa = NextPos(ha);
break;
}//case
case 0: { //兩者指數值相等
sum = a.coef + b.coef;
if(sum != 0.0){ //修改多項式PA當前的係數值
PElemType e;
e.coef = sum;
e.expn = a.expn;
SetCurElem(qa, e);
ha=qa;
}//if
else{ //刪除多項式PA的當前結點
DelFirst(Pa, ha, qa);
FreeNode(qa);
}//else
DelFirst(Pb, hb, qb);
FreeNode(qb);
qb = NextPos(hb);
qa = NextPos(ha);
break;
}//case
case 1:{ //多項式PB中當前結點的指數值小
DelFirst(Pb, hb, qb);
InsFirst(Pa, ha, qb);
qb = NextPos(hb);
ha = NextPos(ha);
break;
}//case
}//switch
}//while
if(!ListEmpty(Pb)){
Pb.tail = hb;
Append(Pa, qb); //鏈接Pb中剩餘結點
}//if
DestoryPolyn(Pb); //銷燬Pb
} //AddPolyn
void Opposite(Polynomial &Pa){ //係數取反
//多項式Pa係數取反
Position p;
p = Pa.head;
while(p->next){
p = p->next;
p->data.coef *= -1;
}//while
}//Opposite
void SubtractPolyn(Polynomial &Pa, Polynomial &Pb){
//多項式減法:Pa=Pa-Pb,並銷燬一元多項式Pb
Opposite(Pb); //多項式Pb係數取反
AddPolyn(Pa, Pb); //兩多項式相加,操作完之後銷燬Pb
} //SubtractPolyn
void MultiplePolyn(Polynomial &Pa, Polynomial &Pb){
//多項式乘法:Pa=Pa*Pb,並銷燬一元多項式Pb
Polynomial Pc;
Position qa = NULL, qb = NULL;
PElemType a, b, c;
InitList(Pc);
qa = GetHead(Pa);
qa = qa->next;
while(qa){
a = GetCurElem(qa);
qb = GetHead(Pb);
qb = qb->next;
while(qb){
b = GetCurElem(qb);
c.coef = a.coef * b.coef;
c.expn = a.expn + b.expn;
OrderInsertMerge(Pc, c, compare);
qb = qb->next;
}//while
qa = qa->next;
}//while
DestoryPolyn(Pb); //銷燬Pb
ClearList(Pa); //將Pa重置爲空表
Pa.head = Pc.head;
Pa.tail = Pc.tail;
Pa.len = Pc.len;
} //MultiplePolyn
//-------------------------------------------主函數---------------------------------------------------
int main(int argc,char *argv[]){
Polynomial P, Q; //兩個多項式
int m = 0;
printf("\n------------------------------- 一元多項式 -------------------------------------\n");
printf("->請輸入一元多項式1的非零項個數:"); scanf("%d", &m);
createPolyn(P, m);
printf("->請輸入一元多項式2的非零項個數:"); scanf("%d", &m);
createPolyn(Q, m);
printf("\n->執行操作前,P、Q 兩多項式:\n");
printf("P : "); PrintPolyn(P, Print);
printf("Q : "); PrintPolyn(Q, Print);
AddPolyn(P,Q); //多項式加法,P+Q
printf("\n->兩個多項式相加結果P+Q:"); PrintPolyn(P, Print);
printf("\n->請輸入一元多項式3的非零項個數:"); scanf("%d", &m);
createPolyn(Q, m);
printf("\n->執行操作前,P、Q 兩多項式:\n");
printf("P : "); PrintPolyn(P, Print);
printf("Q : "); PrintPolyn(Q, Print);
SubtractPolyn(P,Q); //多項式減法,P-Q
printf("\n->兩個多項式相減結果P-Q:"); PrintPolyn(P, Print);
printf("\n->請輸入一元多項式4的非零項個數:"); scanf("%d", &m);
createPolyn(Q, m);
printf("\n->執行操作前,P、Q 兩多項式:\n");
printf("P : "); PrintPolyn(P, Print);
printf("Q : "); PrintPolyn(Q, Print);
MultiplePolyn(P,Q); //多項式乘法,P*Q
printf("\n->兩個多項式相乘結果P*Q:\n"); PrintPolyn(P, Print);
DestoryPolyn(P); //所有操作完成都會銷燬Q,此時只剩下P沒被銷燬
return 0;
}
程序的運行結果和輸入的數據:
------------------------------- 一元多項式 -------------------------------------
->請輸入一元多項式1的非零項個數:3
請輸入多項式1的係數:1
請輸入多項式1的指數:2
請輸入多項式2的係數:5
請輸入多項式2的指數:4
請輸入多項式3的係數:3
請輸入多項式3的指數:3
->請輸入一元多項式2的非零項個數:3
請輸入多項式1的係數:-3
請輸入多項式1的指數:3
請輸入多項式2的係數:4
請輸入多項式2的指數:2
請輸入多項式3的係數:7
請輸入多項式3的指數:1
->執行操作前,P、Q 兩多項式:
P : f(x)=1.00x^2+3.00x^3+5.00x^4
Q : f(x)=7.00x^1+4.00x^2-3.00x^3
->兩個多項式相加結果P+Q: f(x)=7.00x^1+5.00x^2+5.00x^4
->請輸入一元多項式3的非零項個數:3
請輸入多項式1的係數:4
請輸入多項式1的指數:1
請輸入多項式2的係數:2
請輸入多項式2的指數:3
請輸入多項式3的係數:6
請輸入多項式3的指數:6
->執行操作前,P、Q 兩多項式:
P : f(x)=7.00x^1+5.00x^2+5.00x^4
Q : f(x)=4.00x^1+2.00x^3+6.00x^6
->兩個多項式相減結果P-Q: f(x)=3.00x^1+5.00x^2-2.00x^3+5.00x^4-6.00x^6
->請輸入一元多項式4的非零項個數:2
請輸入多項式1的係數:1
請輸入多項式1的指數:1
請輸入多項式2的係數:2
請輸入多項式2的指數:2
->執行操作前,P、Q 兩多項式:
P : f(x)=3.00x^1+5.00x^2-2.00x^3+5.00x^4-6.00x^6
Q : f(x)=1.00x^1+2.00x^2
->兩個多項式相乘結果P*Q:
f(x)=3.00x^2+11.00x^3+8.00x^4+1.00x^5+10.00x^6-6.00x^7-12.00x^8
--------------------------------
Process exited with return value 0
Press any key to continue . . .
下次的文章將會介紹順序棧的實現,希望大家繼續關注,不見不散!