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

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

導言

上篇文章,我們說明了一元多項式相加採取了什麼形式和抽象定義資料型別定義以及實現一元多項式相加的方法,本節將用具體程式碼來實現一元多項式相加。

一元多項式表現形式

typedef struct{//項的表示,多項式的項作為LinkList的資料元素
float coef;//係數
int expn;//指數
}term,ElemType;//兩個型別:term用於本ADT,ElemType為LinkList的資料物件名
typedef LinkList polynomial

部分演算法描述

Status cmp(PElemType a, PElemType b) {
  if (a.
expn>=b.expn) return 1; else return 0; } void CreatPolyn(PLinkList &P, int m) { // 演算法2.22 // 輸入m項的係數和指數,建立表示一元多項式的有序連結串列P PLink h, q, s; PElemType e; int i; InitList(P); h = GetHead(P); e.coef = 0.0; e.expn = -1; SetCurElem(h, e); // 設定頭結點 for (i=1; i<=m; ++i) { // 依次輸入m個非零項
// scanf ("%f,%d\n",&e.coef, &e.expn); e.coef = (float)(random(1, 90) + random(10)/10.0); if (random(2)) e.coef = -e.coef; e.expn=e.expn+random(1,10); //產生隨機的資料,但是expn值是遞增的 if (!LocateElem(P, e, q, cmp)) { // 當前連結串列中不存在該指數項 if (MakeNode(s,e)) InsFirst(q, s); // 生成結點並插入連結串列 if
(q==P.tail) P.tail=s; } else i--; // 如果沒有產生插入,則將i值減1 } } // CreatPolyn Status PrintfPoly(PLinkList P) { int i=0; PLink q=P.head->next; while (q) { if (fabs(q->data.coef) > 0.005) { if (i>0) { if (q->data.coef>0.005) printf(" + "); else printf(" - "); printf("%.2f", fabs(q->data.coef)); } else printf("%.2f", q->data.coef); if (q->data.expn>=1) printf("x"); if (q->data.expn>1) printf("^%d", q->data.expn); } q=q->next; if (++i % 6 == 0) printf("\n "); } printf("\n"); return OK; int Compare(PElemType a, PElemType b) { if (a.expn<b.expn) return -1; if (a.expn>b.expn) return 1; return 0; } void AddPolyn(PLinkList &Pa, PLinkList &Pb) { // 演算法2.23 // 多項式加法:Pa = Pa+Pb,利用兩個多項式的結點構成"和多項式"。 PLink ha,hb,qa,qb; PElemType a, b, temp; float sum; ha = GetHead(Pa); // ha和hb分別指向Pa和Pb的頭結點 hb = GetHead(Pb); qa = NextPos(Pa,ha); // qa和qb分別指向La和Lb中當前結點 qb = NextPos(Pb,hb); while (qa && qb) { // Pa和Pb均非空 a = GetCurElem (qa); // a和b為兩表中當前比較元素 b = GetCurElem (qb); switch (Compare(a,b)) { case -1: // 多項式PA中當前結點的指數值小 ha = qa; qa = NextPos (Pa, qa); break; case 0: // 兩者的指數值相等 sum = a.coef + b.coef ; if (sum != 0.0) { // 修改多項式PA中當前結點的係數值 temp.coef=sum; temp.expn=a.expn; SetCurElem(qa, temp) ; ha = qa; } else { // 刪除多項式PA中當前結點 DelFirst(ha, qa); FreeNode(qa); } DelFirst(hb, qb); FreeNode(qb); qb = NextPos(Pb, hb); qa = NextPos(Pa, ha); break; case 1: // 多項式PB中當前結點的指數值小 DelFirst(hb, qb); InsFirst(ha, qb); qb = NextPos(Pb, hb); ha = NextPos(Pa, ha); break; } // switch } // while if (!Empty(Pb)) Append(Pa, qb); // 連結Pb中剩餘結點 FreeNode(hb); // 釋放Pb的頭結點 } // AddPolyn

具體實現程式碼

程式碼實現第一種

可能略有不完善之處

第二種程式碼的實現(僅連結串列儲存形式實現)

#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 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; /* 連結串列空 */
}

void FreeNode(Link *p)
{ /* 釋放p所指結點 */
    free(*p);
    *p = NULL;
}
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;
}
void AddPolyn(polynomial &Pa, polynomial &Pb)
{//多項式加法:Pa = Pa+Pb,利用兩個多項式的結點構成“和多項式”
    Position ha, hb, qa=NULL, qb=NULL;
    term a, b;
    ha = GetHead(Pa); hb = GetHead(Pb);//ha和hb分別指向Pa和Pb的頭結點
    if (Pa.len != 0 && Pb.len != 0)
    {
        qa = NextPos(ha); qb = NextPos(hb);//qa和qb分別指向Pa和Pb中的當前結點
        //此時qa和qb都是指向多項式第一項
        while (qa && qb)
        {//qa和qb非空
            a = GetCurElem(qa);
            b = GetCurElem(qb); // a和b為兩表中當前比較元素
            float sum;
            switch (cmp(a, b))//比較兩者的指數值
            {
            case -1://多項式中PA中的結點的指數小
                ha = qa;
                qa = NextPos(ha);
                break;
            case 0://兩者指數值相等
                sum = a.coef + b.coef;
                if (sum != 0)
                {
                    //修改pa指向的該結點的係數值
                    qa->data.coef = sum;
                    //下一個
                    ha = qa;
                }
                else
                {
                    //刪除結點
                    DelFirst(&Pa, ha, &qa);
                    FreeNode(&qa);
                }
                DelFirst(&Pb, hb, &qb);//也刪除掉qb的結點
                //都往後移動一位
                qb = NextPos(hb);
                qa = NextPos(ha);
                break;
            case 1://多項式PB中的當前結點指數值小
                DelFirst(&Pb, hb, &qb);//把當前結點從PB中刪除,並用qb指向當前結點用以插入
                InsFirst(&Pa, ha, qb);//插入在ha前
                qb = NextPos(hb);
                qa = NextPos(ha);
                break;
            }//switch
        }//while
        if (!ListEmpty(Pb))Append(&Pa, qb);//連線Pb中剩餘結點
        FreeNode(&hb);//釋放Pb的頭結點
    }//A,B不為空
    if (Pa.len == 0)
    {
        Pa = Pb;//相加結果就是B
    }
    if (Pb.len == 0)
    {
        //相加結果就是A
    }   
    //其中一個已經空了

}//AddPolyn


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;
    //假設以上輸入成功
    //進行相加
    AddPolyn(A, B);
    //這時候A是合併後的結果
    cout << "PA(x)+PB(x) = ";
    ListTraverse(A, visit);
    cout << endl;
    system("pause");
    return 0;
}

執行結果:
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述