1. 程式人生 > >資料結構(14)線性表之C++實現一元多項式相乘

資料結構(14)線性表之C++實現一元多項式相乘

導言

兩個一元多項式相乘的演算法,可以利用兩個一元多項式相加的演算法來實現,因為乘法可以分解為一系列的加法運算。

原始碼實現

#define   OK                    1
#define   ERROR                 0
#define   OVERFLOW             -2
#define   TRUE                  1
#define   FALSE                 0
typedef   int   Status;//為了方便演算法可用性,演算法的Status可以通過這裡可改
#include <iostream> #include <cstdlib> using namespace std; typedef struct{//項的表示,多項式的項作為LinkList的資料元素 float coef;//係數 int expn;//指數 }term, ElemType;//兩個型別:term用於本ADT,ElemType為LinkList的資料物件名 typedef struct LNode{//節點型別 ElemType data;//這裡表示了每一項,其指數和係數 struct LNode *next; }*Link, *Position; typedef struct{//連結串列型別
Link head, tail;//分別指向線性連結串列中的頭結點和最後一個結點 int len;//指示線性連結串列中資料元素的個數 }LinkList;//每一項組成一個列表 typedef LinkList polynomial; Status InitList(LinkList *L) { /* 構造一個空的線性連結串列 */ Link p; p = (Link)malloc(sizeof(LNode)); /* 生成頭結點 */ if (p) { p->next = NULL; (*L).head = (*L).tail =
p; (*L).len = 0; return OK; } else return ERROR;//記憶體分配不夠 } Status ClearList(LinkList *L) { /* 將線性連結串列L重置為空表,並釋放原連結串列的結點空間 */ Link p, q; 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; } free(q); (*L).tail = (*L).head; (*L).len = 0; } return OK; } void FreeNode(Link *p) { /* 釋放p所指結點 */ free(*p); *p = NULL; } Status DestroyPolyn(LinkList *L) { /* 銷燬線性連結串列L,L不再存在 */ ClearList(L); /* 清空連結串列 */ FreeNode(&(*L).head); (*L).tail = NULL; (*L).len = 0; return OK; } Status MakeNode(Link *p, ElemType e) { /* 分配由p指向的值為e的結點,並返回OK;若分配失敗。則返回ERROR */ *p = (Link)malloc(sizeof(LNode)); if (!*p) return ERROR; (*p)->data = e; return OK; } Status InsFirst(LinkList *L, Link h, Link s) /* 形參增加L,因為需修改L */ { /* h指向L的一個結點,把h當做頭結點,將s所指結點插入在第一個結點之前 */ s->next = h->next; h->next = s; if (h == (*L).tail) /* h指向尾結點 */ (*L).tail = h->next; /* 修改尾指標 */ (*L).len++; return OK; } Position GetHead(LinkList L) { /* 返回線性連結串列L中頭結點的位置 */ return L.head; } Status SetCurElem(Link p, ElemType e) { /* 已知p指向線性連結串列中的一個結點,用e更新p所指結點中資料元素的值 */ p->data = e; return OK; } Status LocateElemP(LinkList L, ElemType e, Position *q, int(*compare)(ElemType, ElemType)) { /* 若升序連結串列L中存在與e滿足判定函式compare()取值為0的元素,則q指示L中 */ /* 第一個值為e的結點的位置,並返回TRUE;否則q指示第一個與e滿足判定函式 */ /* compare()取值>0的元素的前驅的位置。並返回FALSE。(用於一元多項式) */ Link p = L.head, pp; do { pp = 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 = pp; return FALSE; } else /* 找到 */ {/* 沒到表尾且p->data.expn=e.expn */ *q = p; return TRUE; } } Status Remove_Polyn(LinkList *L, Link q) { //由於項的指數為0,刪除掉已有的項 Link p, h; h = L->head; while (h->next != q) { h = h->next; } //找到了 if (q == L->tail) {//刪除的如果是表尾,改變表尾 L->tail = h; } h->next = q->next; free(q); L->len--; return OK; } int cmp(term a, term b) // CreatPolyn()的實參 { // 依a的指數值<、=或>b的指數值,分別返回-1、0或+1 if (a.expn == b.expn) return 0; else return (a.expn - b.expn) / abs(a.expn - b.expn); } void CreatPolyn(polynomial &p, int m) {//輸入m項的係數和指數,建立表示一元多項式的有序連結串列P InitList(&p);//初始化多項式連結串列 Link h = GetHead(p);//設定頭結點的資料元素 ElemType e;//頭結點設定 Position q, s; e.coef = 0.0; e.expn = -1; SetCurElem(h, e);//設定頭結點的元素 for (int i = 1; i <= m; ++i)//依次輸入m個非零項 { cout << "第" << i << "項" << "的係數:"; cin >> e.coef; cout << "第" << i << "項" << "的指數:"; cin >> e.expn; if (!LocateElemP(p, e, &q, cmp))//當前連結串列中不存在該指數項 { if (e.coef != 0)//不等於才插入 if (MakeNode(&s, e))InsFirst(&p, q, s);//生成結點並插入連結串列 } else//當前連結串列中存在該指數項,增加其係數 { q->data.coef = q->data.coef + e.coef; //如果合起來等於0,則刪除掉 if (q->data.coef == 0) Remove_Polyn(&p, q);//刪除掉當前節點 } } } Status ListTraverse(LinkList L, void(*visit)(ElemType)) { /* 依次對L的每個資料元素呼叫函式visit()。一旦visit()失敗,則操作失敗 */ Link p = L.head->next; int j; for (j = 1; j <= L.len; j++) { visit(p->data); p = p->next; } cout << "\b "; if (L.len == 0) cout << "0"; return OK; } void visit(ElemType e) { if (e.coef > 0 && e.coef != 1 && e.expn != 0) { if (e.expn > 0) cout << e.coef << "x^" << e.expn << "+"; else cout << e.coef << "x^(" << e.expn << ")+"; } else if (e.coef < 0 && e.expn != 0) { if (e.expn > 0) cout << "(" << e.coef << ")x^" << e.expn << "+"; else cout << "(" << e.coef << ")x^(" << e.expn << ")+"; } else if (e.coef == 1 && e.expn != 0) { if (e.expn > 0) cout << "x^" << e.expn << "+"; else cout << "x^(" << e.expn << ")+"; } else if (e.expn == 0 && e.coef != 0) cout << e.coef << "+"; else cout << "";//考慮使用者輸入可能有係數為0的情況,情況太多,避免萬一 } Position NextPos(Link p) { /* 已知p指向線性連結串列L中的一個結點,返回p所指結點的直接後繼的位置 */ /* 若無後繼,則返回NULL */ return p->next; } ElemType GetCurElem(Link p) { /* 已知p指向線性連結串列中的一個結點,返回p所指結點中資料元素的值 */ return p->data; } 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; /* 修改尾指標 */ (*L).len--; return OK; } else return FALSE; /* 連結串列空 */ } Status ListEmpty(LinkList L) { /* 若線性連結串列L為空表,則返回TRUE,否則返回FALSE */ if (L.len) return FALSE; else return TRUE; } Status 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++; } (*L).tail = s; (*L).len += i; return OK; } Position PriorPos(LinkList L, Link p) { /* 已知p指向線性連結串列L中的一個結點,返回p所指結點的直接前驅的位置 */ /* 若無前驅,則返回NULL */ Link q; q = L.head->next; if (q == p) /* 無前驅 */ return NULL; else { while (q->next != p) /* q不是p的直接前驅 */ q = q->next; return q; } } void OrderInsertMerge(LinkList &L, ElemType e, int(*compare)(term, term)) { // 按有序判定函式compare()的約定,將值為e的結點插入或合併到升序連結串列L的適當位置 Position q, s; if (LocateElemP(L, e, &q, compare)) // L中存在該指數項 { q->data.coef += e.coef; // 改變當前結點係數的值 if (!q->data.coef) // 係數為0 { // 刪除多項式L中當前結點 s = PriorPos(L, q); // s為當前結點的前驅 if (!s) // q無前驅 s = L.head; DelFirst(&L, s, &q); FreeNode(&q); } } else // 生成該指數項並插入連結串列 { MakeNode(&s, e); // 生成結點 InsFirst(&L, q, s); } } void MulPolyn(polynomial &Pa,polynomial &Pb) { //多項式加法:Pa = Pa*Pb,利用兩個多項式的結點構成“和多項式” Position qa = NULL, qb = NULL; polynomial Pc;//臨時多項式連結串列 term a, b,c; InitList(&Pc); qa = GetHead(Pa);//ha和hb分別指向Pa和Pb的頭結點 if (Pa.len != 0 && Pb.len != 0) { 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, cmp); qb = qb->next; } qa = qa->next; } DestroyPolyn(&Pb); // 銷燬Pb ClearList(&Pa); // 將Pa重置為空表 Pa.head = Pc.head; Pa.tail = Pc.tail; Pa.len = Pc.len; } else if (Pa.len == 0 ) { //do nothing,because The polynoimal is 0 } else if (Pb.len == 0) { Pa = Pb;//把Pb賦值給Pa,讓其也為0 } } int main() { cout << "***************************************************************************" << endl; cout << " 《資料結構》<C語言版本>嚴蔚敏 吳偉名 編著 " << endl; cout << " 編寫年月2016年3月 " << endl; cout << " 編寫者:YuYunTan " << endl; cout << " 一元多項式相乘 " << endl; cout << "***************************************************************************" << endl; polynomial A, B; cout << "請輸入第一個多項式的項數為:"; int length; cin >> length; CreatPolyn(A, length); //顯示A出來 cout << "PA(x) = "; ListTraverse(A, visit); cout << endl; //輸入B cout << "請輸入第二個多項式的項數為:"; cin >> length; CreatPolyn(B, length); //輸出B cout << "PB(x) = "; ListTraverse(B, visit); cout << endl; //假設以上輸入成功 //進行相加 MulPolyn(A, B); //這時候A是合併後的結果 cout << "PA(x)*PB(x) = "; ListTraverse(A, visit); cout << endl; system("pause"); return 0; }

結果展示

這裡寫圖片描述
這裡寫圖片描述