資料結構(14)線性表之C++實現一元多項式相乘
阿新 • • 發佈:2019-02-12
導言
兩個一元多項式相乘的演算法,可以利用兩個一元多項式相加的演算法來實現,因為乘法可以分解為一系列的加法運算。
原始碼實現
#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;
}
結果展示