關於多項式的加和、乘積可用連結串列和陣列

Dallas01發表於2020-11-11

關於多項式的加和、乘積

  • Dargon

  • 2020/11/11

  • 所遇到的的重要的問題:

  • 教科書 來自:《資料結構和演算法分析》第三章

對於連結串列操作,自己要去自己實現連結串列的節本功能,例如基本的created、insert、delete。要寫出來,並且執行才知道其中的一些道理,和自己容易出錯的地方

1,運用陣列運算

  • 運用陣列儲存對應指數的項的係數
    例如對於陣列a[10] 可以儲存0 次方~ 9 次方的係數,陣列的下標對應的是指數,陣列的元素的內容對應的是該位的係數。

  • 缺點
    當遇到不連續的情況,就事倍功半了 如計算a = X^1000 +5X^10, b = X^1050 +X^1 +5

2,運用連結串列運算

Creat struct:

typedef struct PNODE {
    int Coefficient;
    int Exponent;
    struct PNODE *Next;
}ListNode;

2.1 建立連結串列 Created_linklist

用兩種方式建立連結串列

  1. 第一種 多申請一個head 浪費一些記憶體空間
ListNode *creat_list(int n) {
    ListNode *root;
    ListNode *pre, *current;
    int c, e, i;
    root =(ListNode *)malloc(sizeof(ListNode));
    assert(root !=NULL);
    pre =root;

    for( i =0; i <n; i++ ) {        
        printf("請輸入第%d項: ", i+1);
        scanf("%d%d", &c, &e);
        current =(ListNode *)malloc(sizeof(ListNode));
        assert( current !=NULL );
        current->Coefficient =c;
        current->Exponent =e;
        current->Next =NULL;

        pre->Next =current;
        pre =current;
    }
    return root;
}
  1. 此方法更合理
ListNode *creat_list_v2(int n) {
    ListNode *root;
    ListNode *newnode, *current;
    int c, e, i;
    root =current =NULL;
    for(i =0; i <n; i++) {
        printf("請輸入第%d項: ", i+1);
        scanf("%d%d", &c, &e);
        newnode =(ListNode *)malloc(sizeof(ListNode));
        assert( newnode != NULL );

        newnode->Coefficient =c;
        newnode->Exponent =e;
        newnode->Next =NULL;

        if(root ==NULL) 
            root =newnode;
        else 
            current->Next =newnode;        
        current =newnode;
    }
    return root;
}

2.2 插入節點 insert ListNode

和正常的插入節點一樣,將指向連結串列(根指標root)的指標作為引數傳入到函式中,排除previous =NULL 的特殊情況

int insert_onenode_v2(ListNode **rootp) {
    ListNode *current;
    ListNode *newnode;
    int c, e;
    printf("分別輸入要插入項的係數指數:");
    scanf("%d%d", &c,&e);
    while( (current =*rootp) !=NULL && current->Exponent >e ) {
        rootp =&(current->Next);
    }
    if(current->Exponent ==e) {
        current->Exponent +=e;
    }
    else {
        newnode =(ListNode *)malloc(sizeof(ListNode));
        assert( newnode !=NULL );

        newnode->Coefficient =c;
        newnode->Exponent =e;

        newnode->Next =current;
        *rootp =newnode;
    }
    return TRUE;
}

2.3 刪除節點 delete ListNode

int delete_onenode(ListNode **rootp) {
    ListNode *current;
    int e;
    printf("分別輸入要刪除項的指數:");
    scanf("%d", &e);
    while( (current =*rootp) !=NULL && current->Exponent !=e ) {
        rootp =&(current->Next);
    }
    if( current ==NULL ) return FALSE;
    else {
        *rootp =current->Next;
        free(current);
    }
    return TRUE;
}

2.4 多項式相加 polynomial add

方法有待於更改,傳入的多項式,預設是次冪是從高到低進行排列的,中間重複程式碼過多!!

void product_node(ListNode **rootp, int COE, int e) {
    ListNode *newnode;
    newnode =(ListNode *)malloc(sizeof(ListNode));
    assert(newnode !=NULL);

    newnode->Coefficient =COE;
    newnode->Exponent =e;
    newnode->Next =NULL;

    (*rootp)->Next =newnode;
    (*rootp) =newnode;
}
ListNode *AddPolynomial_v3( ListNode *roota, ListNode *rootb ) {
    ListNode *pa, *pb, *rootc, *pc, *newnode;
    pa =roota->Next;
    pb =rootb->Next;
    rootc =(ListNode *)malloc(sizeof(ListNode));
    rootc->Coefficient =0;
    rootc->Exponent =0;
    rootc->Next =NULL;
    pc =rootc;
    int COE =0, e;

    while( pa !=NULL && pb !=NULL ) {
        if(pa->Exponent ==pb->Exponent) {
            COE =pa->Coefficient +pb->Coefficient;
            e =pa->Exponent;
            pa =pa->Next;
            pb =pb->Next;
        }
        else if( pa->Exponent >pb->Exponent ) {
            COE =pa->Coefficient;
            e =pa->Exponent;
            pa =pa->Next;
        }
        else {
            COE =pb->Coefficient;
            e =pb->Exponent;
            pb =pb->Next;
        }
        if( COE !=0 ) {
            product_node(&pc, COE, e);           
            COE =0;
        }
    }
    while( pa !=NULL ) {
        COE =pa->Coefficient;
        e =pa->Exponent;
        pa =pa->Next;
        if( COE !=0 ) {
            product_node(&pc, COE, e);
            COE =0;
        }
    }
    while( pb !=NULL ) {
        COE =pb->Coefficient;
        e =pb->Exponent;
        pb =pb->Next;
        if( COE !=0 ) {
            product_node(&pc, COE, e);
            COE =0;
        }
    }
    return rootc;   
}

測試結果顯示

int DataStruct_02_02(void) {
    ListNode *roota, *rootb;
    roota =creat_list_v2(2);
    print_list_v2(roota);
    rootb =creat_list_v2(2);
    print_list_v2(rootb);
    insert_onenode_v2( &rootb);
    print_list_v2(rootb);
    delete_onenode(&rootb);
    print_list_v2(rootb);
    
    print_list_v2(AddPolynomial_v2(roota, rootb));
    free_list(roota);
    free_list(rootb);
    return RUN_TEST_OK;
}

result


請輸入第1項: 1 3
請輸入第2項: 2 1
1*X^3+ 2*X^1  
請輸入第1項: 1 5
請輸入第2項: 1 3
1*X^5+ 1*X^3
分別輸入要插入項的係數指數:1 6
1*X^6+ 1*X^5+ 1*X^3
分別輸入要刪除項的指數:6
1*X^5+ 1*X^3
1*X^5+ 2*X^3+ 2*X^1
1/1 (100.00%) passed

按任意鍵關閉終端。

2.4 多項式相乘 polynomial multiply

解題思路參照:https://blog.csdn.net/weixin_43911865/article/details/100544395
整體的思路就是:
利用最高次冪去做循壞,每一次迴圈將所有相乘為該次冪的項全部找出,將其係數相乘作和,直到找到 0 次冪為止
中間利用一次反轉,對於整個連結串列的反轉,不過此方法還是做了很多次沒有意義的迴圈。

void inverse_list(ListNode *root) {
    ListNode *current =root->Next;
    ListNode *next;
    root->Next =NULL;
    while(current) {
        next =current->Next;
        current->Next =root->Next;
        root->Next =current;
        current =next;
    }
}

ListNode *MultPolynomial_v2( ListNode *roota, ListNode *rootb ) {
    ListNode *rootc, *pa, *pb, *pc, *newnode;
    int exp_max;
    pa =roota;
    pb =rootb;
    
    if(pa->Next !=NULL && pb->Next !=NULL) {
        exp_max =pa->Next->Exponent +pb->Next->Exponent; 
    }
    else {
        return NULL;
    }
    rootc =(ListNode *)malloc(sizeof(ListNode));
    assert(rootc !=NULL);
    rootc->Coefficient =0;
    rootc->Exponent =0;
    rootc->Next =NULL;
    pc =rootc; //As a head of listnode to use

    inverse_list(rootb); //Inverse order of the list
    int COE =0; //係數和
    int k =0; //指數

    for(k =exp_max; k >=0; k--) {
        //Keep pa exponent is largest
        pa =roota->Next;
        while(pa !=NULL && pa->Exponent >k) {
            pa =pa->Next;
        }
        //Search pb in the list
        pb =rootb->Next;
        while(pa !=NULL && pb !=NULL && (pa->Exponent +pb->Exponent) <k) {
            pb =pb->Next;
        }
        // Now (pa +pb)->exp >= k
        while(pa !=NULL && pb !=NULL) {
            if( (pa->Exponent +pb->Exponent) ==k ) {
                COE += (pa->Coefficient *pb->Coefficient);
                pa =pa->Next;
                pb =pb->Next;
            }
            else {
                if( (pa->Exponent +pb->Exponent) <k )
                    pb =pb->Next;
                else 
                    pa =pa->Next;
            }
        }
        //mallco new node insert in c list
        if( COE !=0 ) {
            newnode =(ListNode *)malloc(sizeof(ListNode));
            assert(newnode);

            newnode->Coefficient =COE;
            newnode->Exponent =k;
            newnode->Next =NULL;

            pc->Next =newnode;
            pc =newnode;

            COE =0;
        }
    }
    inverse_list(rootb);
    return rootc;
}

測試結果 result

請輸入第1項: 1 2
請輸入第2項: 1 1
1*X^2+ 1*X^1
請輸入第1項: 1 3
請輸入第2項: 1 1
1*X^3+ 1*X^1
1*X^5+ 1*X^4+ 1*X^3+ 1*X^2
1/1 (100.00%) passed

按任意鍵關閉終端。

2.4 free記憶體

void free_list(ListNode *root) {
    ListNode *first_node;   
    while(root !=NULL) {
        first_node =root;
        root =root->Next;
        free(first_node);
    }
}

3,總結

方法還有很多,目前只是簡單的實現,記錄於此!

相關文章