1. 程式人生 > 實用技巧 >順序表與連結串列實現多項式的加減乘與冪微分

順序表與連結串列實現多項式的加減乘與冪微分

1.連結串列實現

分為三個檔案進行編寫,分別為自定義標頭檔案,實現的cpp檔案與main主程式檔案.

整個過程中在實現乘的函式MutiplePoly和展示的Display函式上遇到較大困難.

1)MutiplePoly:由於一開始便預設資料是按低階到高階的,在設計乘演算法時強迫自己儘量不使用雙迴圈來計算.關鍵在於找到相乘後同階的所有項並相加,,故將兩個連結串列各迴圈一遍存入兩個陣列中方便訪問.在將兩個多項式各個係數相乘的結果規律排列成矩陣後,發現相乘後的階數規律排列.

如兩個陣列大小分別為4,3.則下標分別為0,1,2,3與0,1,2,相乘後係數相加得到如下矩陣:

0 1 2 3
1 2 3 4
2 3 4 5

矩陣中相同數字代表的項階數相同,則按斜線劃分成6層,大迴圈從0層開始遍歷到頂層.則計算可分為兩部分,一部分層數0~2,a[i]+b[j],i+j=當前層數,當j<0時跳出小迴圈.另一部分3~5,當i>3時跳出小迴圈.通過小迴圈將相同階數的係數全部相加.

2)Display:展示多項式的實現過程主要在於細節的繁多,如首項若為正項則不加符號,若為0則不顯示,非首項若為0則不顯示,為正項要新增正號等等.也因為這樣最後的實現體跳轉較多,程式碼顯得繁瑣.

順序表實現雖然用的是vector,但基本也符合順序表的定義,實現過程與連結串列相差無幾.故不多贅述.

最後附上完整連結串列實現程式碼:

標頭檔案:

#ifndef __POLY_H__
#define __POLY_H__
#include <iostream>
#include <vector>
using namespace std;

// 儲存係數的結構體,採用雙鏈表結構
typedef struct data
{
    int coefficient;
    struct data *next;
    struct data *pre;
} Data;
typedef Data *PtrToNode;

// 儲存連結串列首末位置的結構體
typedef struct upper
{
    PtrToNode head;
    PtrToNode end;
    
int items; } list; //宣告連結串列 typedef list *List; void InitList(List &); //初始化連結串列 void Add(List &); //新增資料 void AddNode(List &); //新增節點 void GetInfo(List &); //輸入資料 void Calculate(List &); //運用霍納法則進行計算 void AddPoly(List &, List &, List &); //將兩個多項式相加 void SubtractPoly(List &, List &, List &); //將兩個多項式相減 void MutiplePoly(List &, List &, List &); //將兩個多項式相乘 // void DividePoly(List &, List &, List &); void Differential(List &); void Clear(List &); //清空列表 void Reset(List &, List &); //重新輸入兩個多項式 void menu1(); //展示選單1 void menu2(); //展示選單2 void Display(List &); //展示多項式 void ListToArray(List &, List &, vector<int> &, vector<int> &); //將連結串列資料轉化為陣列儲存 void DeleteHead(List &); //刪除首節點 #endif

實現檔案:

#include "poly.h"

//給多項式新增資訊
void Add(List &l)
{
    int num;
    cout << "Enter the number of terms:" << endl;
    cin >> num;
    cout << "Enter the coefficients in ascending power:" << endl; //提醒使用者以冪次的升序輸入係數
    for (int i = 0; i < num; i++)
    {
        AddNode(l);
        GetInfo(l);
    }
}

// 初始化連結串列
void InitList(List &l)
{
    l = (List) new list;
    l->head = NULL;
    l->end = NULL;
    l->items = 0;
}

//多項式相加
void AddPoly(List &l1, List &l2, List &l3)
{
    PtrToNode cur1 = l1->head;
    PtrToNode cur2 = l2->head;
    while (cur1 != NULL || cur2 != NULL)
    {
        AddNode(l3);
        if (cur1 != NULL && cur2 != NULL)
        {
            l3->end->coefficient = cur1->coefficient + cur2->coefficient;
            cur1 = cur1->next;
            cur2 = cur2->next;
        }
        else if (cur1 == NULL) //處理多項式項數不同的情況
        {
            l3->end->coefficient = cur2->coefficient;
            cur2 = cur2->next;
        }
        else
        {
            l3->end->coefficient = cur1->coefficient;
            cur1 = cur1->next;
        }
    }
    Display(l3);
}

// 多項式相減
void SubtractPoly(List &l1, List &l2, List &l3)
{
    PtrToNode cur1 = l1->head;
    PtrToNode cur2 = l2->head;
    while (cur1 != NULL || cur2 != NULL)
    {
        AddNode(l3);
        if (cur1 != NULL && cur2 != NULL)
        {
            l3->end->coefficient = cur1->coefficient - cur2->coefficient;
            cur1 = cur1->next;
            cur2 = cur2->next;
        }
        else if (cur1 == NULL)
        {
            l3->end->coefficient = -cur2->coefficient;
            cur2 = cur2->next;
        }
        else
        {
            l3->end->coefficient = cur1->coefficient;
            cur1 = cur1->next;
        }
    }
    Display(l3);
}
void MutiplePoly(List &l1, List &l2, List &l3)
{
    vector<int> a1;
    vector<int> a2;
    ListToArray(l1, l2, a1, a2);

    //根據冪次相加後形成的規律矩陣查詢每個冪次對應的項並相加,最後賦值
    int top = (l1->items + l2->items - 2);
    int floor = 0; //冪次為0開始
    int border = a2.size() - 1;
    int sum = 0; //儲存每個冪次對應的係數
    while (floor <= top)
    {
        AddNode(l3);
        if (floor <= border)
            for (int i = 0, j = floor - i; j >= 0; i++, j--)
            {
                sum += a1[i] * a2[j];
                l3->end->coefficient = sum;
            }
        else
            for (int j = border, i = floor - j; i < a1.size() && j >= 0; i++, j--)
            {
                sum += a1[i] * a2[j];
                l3->end->coefficient = sum;
            }
        sum = 0;
        floor++;
    }
    Display(l3);
}

// 求一階導
void Differential(List &l)
{
    DeleteHead(l);

    int time = 1;
    PtrToNode cur = l->head;
    while (cur != NULL)
    {
        cur->coefficient *= time;
        cur = cur->next;
        time++;
    }
    Display(l);
}

void Calculate(List &l)
{
    //獲得x值
    int x;
    cout << "Enter the value of x:" << endl;
    cin >> x;

    PtrToNode cur = l->end; //按照霍納法則從後往前遍歷
    int poly = 0;
    while (cur != NULL)
    {
        poly = x * poly + cur->coefficient; //將多項式進行拆分成相乘形式
        cur = cur->pre;
    }
    cout << "The result is " << poly << endl;
}

//兩個選單
void menu1()
{
    cout << "Choose one to execute:" << endl;
    cout << "a)Add\nb)Subtract\nc)Mutiply" << endl;
}
void menu2()
{
    cout << "Choose one to execute:" << endl;
    cout << "a)Calculate\nb)Retype the two polynomials\nc)Differential\nq)quit" << endl;
}

//獲得係數
void GetInfo(List &l)
{
    cin >> l->end->coefficient;
}

void AddNode(List &l)
{
    PtrToNode newNode = (PtrToNode) new Data;
    newNode->next = NULL;
    newNode->pre = l->end;
    if (l->head == NULL)
    {
        l->head = newNode;
        l->end = newNode;
    }
    else
    {
        l->end->next = newNode;
        l->end = newNode;
    }
    l->items++;
}

//清除結果
void Clear(List &l)
{
    PtrToNode cur = l->head;
    PtrToNode temp;
    while (cur != NULL)
    {
        temp = cur->next;
        free(cur);
        cur = temp;
    }
    l->head = NULL;
    l->end = NULL;
    l->items = 0;
}

//重設l1,l2
void Reset(List &l1, List &l2)
{
    Clear(l1);
    Clear(l2);
    Add(l1);
    Add(l2);
}

//將多項式以字串形式展示
void Display(List &l)
{
    string polynomial;
    PtrToNode cur = l->head;
    if (l->items == 0)
        polynomial.append("0");
    else //遍歷以確定係數是否全為0
    {
        int cnt = 0;
        while (cur != NULL)
        {
            if (cur->coefficient == 0)
                cnt++;
            cur = cur->next;
        }
        if (cnt == l->items)
        {
            polynomial.append("0");
            cout << polynomial << endl;
            return;
        }
    }

    //通過不斷將係數與符號append到string中從而展示

    int time = 0; //記錄冪的次數
    cur = l->head;
    while (cur != NULL)
    {
        if (cur == l->head)
        {
            if (cur->coefficient != 0)
                polynomial.append(to_string(cur->coefficient));
            cur = cur->next;
            time++;
            continue;
        }
        else
        {
            if (cur->coefficient > 0)
                polynomial.append("+");
            else if (cur->coefficient < 0)
                polynomial.append("-");
            else //係數為零則跳過不顯示
            {
                cur = cur->next;
                time++;
                continue;
            }
            polynomial.append(to_string(abs(cur->coefficient)));
            polynomial.append("x^");
            polynomial.append(to_string(time));
            time++;
            cur = cur->next;
        }
    }
    cout << polynomial << endl;
}

// 將連結串列儲存到陣列當中方便訪問
void ListToArray(List &l1, List &l2, vector<int> &a1, vector<int> &a2)
{
    PtrToNode p1 = l1->head;
    PtrToNode p2 = l2->head;

    //通過if,else語句讓a1.a2分別固定儲存長多項式於短多項式
    if (l1->items > l2->items)
    {
        while (p1 != NULL)
        {
            a1.push_back(p1->coefficient);
            p1 = p1->next;
        }

        while (p2 != NULL)
        {
            a2.push_back(p2->coefficient);
            p2 = p2->next;
        }
    }
    else
    {
        while (p1 != NULL)
        {
            a2.push_back(p1->coefficient);
            p1 = p1->next;
        }

        while (p2 != NULL)
        {
            a1.push_back(p2->coefficient);
            p2 = p2->next;
        }
    }
}

// 刪除第一個節點
void DeleteHead(List &l)
{
    PtrToNode temp = l->head;
    if (l->items > 1) //項數大於1的情況
        l->head->next->pre = NULL;
    l->head = l->head->next;
    delete temp;
    l->items--;
}

主程式檔案:

#include "poly.h"
int main(void)
{
    List l1;//第一個多項式
    List l2;//第二個多項式
    List l3;//操作之後的多項式
    char option;

    //初始化三個連結串列
    InitList(l1);
    InitList(l2);
    InitList(l3);

    //輸入多項式
    Add(l1);
    Add(l2);
    do
    {
        menu1();
        cin >> option;
        switch (option)
        {
        case 'a':
            AddPoly(l1, l2, l3);
            break;
        case 'b':
            SubtractPoly(l1, l2, l3);
            break;
        case 'c':
            MutiplePoly(l1, l2, l3);
            break;
        case 'd':
            // DividePoly(l1, l2, l3);
            break;
        default:
            cout << "Invalid input" << endl;
            continue;
        }

        menu2();
        cin >> option;
        switch (option)
        {
        case 'a':
            Calculate(l3);
            break;
        case 'b':
            Reset(l1, l2);
            break;
        case 'c':
            Differential(l3);
            break;
        case 'q':
            break;
        default:
            cout << "Invalid input" << endl;
            break;
        }

        Clear(l3);
    } while (option != 'q');
}