一元多項式的乘法與加法運算

問題描述

設(shè)計函數(shù)分別求兩個一元多項式的乘積與和。

輸入格式:
輸入分2行,每行分別先給出多項式非零項的個數(shù),再以指數(shù)遞降方式輸入一個多項式非零項系數(shù)和指數(shù)(絕對值均為不超過1000的整數(shù))。數(shù)字間以空格分隔。

輸出格式:
輸出分2行,分別以指數(shù)遞降方式輸出乘積多項式以及和多項式非零項的系數(shù)和指數(shù)。數(shù)字間以空格分隔,但結(jié)尾不能有多余空格。零多項式應(yīng)輸出0 0。

輸入樣例:
4 3 4 -5 2  6 1  -2 0
3 5 20  -7 4  3 1
輸出樣例:
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

解決思路

解決這個問題主要有數(shù)組實現(xiàn)鏈表實現(xiàn)兩種方法,為了訓(xùn)練使用鏈表,以及可能會出現(xiàn)超時或者內(nèi)存不足的情況,本文中是用鏈表形式來實現(xiàn)多項式的加法,乘法運算

數(shù)組實現(xiàn)

在加法數(shù)組中:(index-1000)表示指數(shù),里面的內(nèi)容表示系數(shù)
在加法數(shù)組中:(index-2000)表示指數(shù),里面的內(nèi)容表示系數(shù)
使用兩個大小為2002*sizeof(int)數(shù)組來接受數(shù)據(jù)(因為絕對值不大于1000,最后一項放非零項的個數(shù)

定義存放加法結(jié)果的數(shù)組(大小同樣為2002),初始化為0
將兩個多項式分別放入加法數(shù)組中,對應(yīng)的指數(shù)的系數(shù)+=放入系數(shù)即可;

定義存放乘法結(jié)果的數(shù)組(大小為4002)初始化為0
poly1(多項式1,下同)每個項分別乘以poly2,放到乘法數(shù)組之中,對應(yīng)系數(shù)+=放入系數(shù)即可;

輸出:首先先看非零項為0,便輸出0 0,如果不是,則便利整個結(jié)果數(shù)組,只有遇到內(nèi)容不是0,才輸出對應(yīng)系數(shù)和指數(shù)

算法分析

簡單概括思路,只需要通過下標(biāo)找到指數(shù)即可,然后對應(yīng)內(nèi)容加上系數(shù)。輸出遇到系數(shù)為0便不輸出

操作較為簡單,如果非零項較小,便會有很多空的節(jié)點,內(nèi)存開銷太大,并且每次輸入系數(shù),輸出都需要遍歷整個數(shù)組,使得效率非常低

鏈表實現(xiàn)

1.首先使用鏈表接受數(shù)據(jù),每個節(jié)點的數(shù)據(jù)格式如下:
[coust, power next]
[系數(shù),指數(shù),下一個節(jié)點地址]
頭節(jié)點中的系數(shù)域用于放置非零項個數(shù),指數(shù)域預(yù)置一個比較大的數(shù)(用處后面將講解)

2.首先需要知道一點,在本題中多項式乘法的實現(xiàn)本質(zhì)是加法的實現(xiàn),因為多項式中乘法可以分解成為加法。乘法結(jié)果可以分解為poly1每個項乘以poly2的和,所以下面著重講解加法的實現(xiàn)

3.我們使用一個空鏈表來存儲加法結(jié)果(系數(shù)項預(yù)置為0,指數(shù)項預(yù)置為大于4000的值),接下來我們要做的便是分別把兩個多項式放入這個鏈表中

放入這個鏈表的動作可以分為兩步:
step1:通過傳入需要放入的項的指數(shù),在目標(biāo)鏈表找到放的位置(return的是放的位置的地址)
step2:通過地址找到的節(jié)點,將系數(shù)放進去

乘法運算便是每個項與另一個項相乘形成的多項式分別放入乘法鏈表之中

4.輸出鏈表,若頭節(jié)點系數(shù)域為0,輸出0 0;否則則遍歷整個鏈表 遇到系數(shù)非零才會輸出項

Some Detail Of Function(建議配合代碼食用

Pnode createList(void):用于存放輸入數(shù)據(jù),沒什么好說的
Pnode copyList(Pnode head):將鏈表拷貝到一個新鏈表

Notice:這里需要說明一下copyList在代碼中的作用。在加法運算中,我的存放加法結(jié)果的addPoly本身不是空的,是已經(jīng)拷貝了Poly1內(nèi)容的鏈表,目的是為在加法運算時的方便,直接將poly2加入其中即可。不需要把poly1加入addPoly,再把poly2也加入

void add(Pnode head1, Pnode head2):head1是加式,head2是被加式。也就是說,把head1加到head2上,最后head2存放的是加法結(jié)果(isInsert待會會講解用處
1.每次temp1指向head1的存放數(shù)據(jù)的節(jié)點,將temp1->power傳入findEle函數(shù),尋找head2中的合適地址用于插入或者直接放入(下面會詳細講解
2.使用insert函數(shù)將該項放入head2之中,然后temp1指向下一個節(jié)點

Pnode findEle(int power, Pnode head):傳入指數(shù),在被加式head中尋找出一個合適的地址并返回該地址;為什么會說是合適的地址?因為我們對加入項的操作可能是插入,或者不需要插入。如下圖所示:

image.png

image.png

?由上圖所示,有相同指數(shù)的項,便改變其系數(shù),如果沒有則插入一個新的項
?所以該地址的作用便是對指向的節(jié)點修改系數(shù),或者在指向的節(jié)點后面插入一個新的項
?在這里也就可以解釋為什么頭節(jié)點的power會設(shè)置成一個比較大的數(shù)字?。ㄎ覀兪菑念^節(jié)點開始尋找的?。?/strong>
?因為按照findEle函數(shù)的查找方式,如果沒有設(shè)置頭節(jié)點的power,那么有一個比第一個項更高次冪的項便會插入困難,如果從第一項開始比較,便會有可能讓鏈表斷裂,因為temp2的上一個節(jié)點我們是沒有的!

?值得一提的是,在整個加法插入中,我們只需遍歷一次多項式,便可以整個加法運算,因為輸入的項的指數(shù)是按從高到低的順序

因為這塊是難點重點,所以稍微總結(jié)一下:
?我們首先傳入power,通過它來尋找一個合適的位置,傳入的head便是從head指向的節(jié)點開始向后尋找(第一次使用這個函數(shù)傳入的head都是指向頭節(jié)點的)
?在尋找的過程中if (temp->power == power || temp->next == 0),便返回temp;if(temp->next->power >= power),便更新temp,否則便表示結(jié)果是需要在temp后面插入節(jié)點,返回temp;

void insert(int * isInsert, Pnode head1, Pnode head2):將項插入節(jié)點后面后者修改該節(jié)點
?這里可以解釋isInsert的作用,如果表示插入,那么我們便會把isInsert改成1,表示頭結(jié)點的非零項的數(shù)目需要++;如果表示修改,便查看修改后的系數(shù)是否等于零,如果為零,便會改成1。表示需要將非零項的個數(shù)--;若不等于零便會改成0,不需要修改非零項的個數(shù)

Pnode multi(Pnode head1, Pnode head2):核心和加法運算大致相同,只是多了一層二重循環(huán),來執(zhí)行乘法,看懂了上面仔細閱讀即可了解

void printResult(Pnode head):輸出結(jié)果

Code

#include<stdio.h>
#include<malloc.h>
typedef struct node {
    int coust;
    int power;
    struct node* next;
}Node, *Pnode;
Pnode createList(void);
Pnode copyList(Pnode head);
void add(Pnode head1, Pnode head2);
Pnode multi(Pnode head1, Pnode head2);
void printResult(Pnode head);
Pnode findEle(int power, Pnode head);
void insert(int * isInsert, Pnode head1, Pnode head2);
int main(void) {
    Pnode poly1 = createList();
    Pnode poly2 = createList();
    Pnode addPoly = copyList(poly1);

    Pnode multiPoly = multi(poly1, poly2);
    add(poly2, addPoly);
    printResult(multiPoly);
    printResult(addPoly);
    return 0;
}
Pnode createList(void) {
    Pnode temp = 0;
    Pnode head = temp = (Pnode)malloc(sizeof(Node));
    head->power = 9999;
    int length;
    scanf("%d",&length);
    head->coust = length;
    for (int i = 0; i < length; i++) {
        temp->next = (Pnode)malloc(sizeof(Node));
        temp =  temp->next;
        scanf("%d %d",&temp->coust, &temp->power);
        temp->next = 0;
    }
    return head;
}
Pnode copyList(Pnode head) {
    Pnode tempOfHead = head;
    Pnode tempOfHead1 = 0;
    Pnode head1 = tempOfHead1 = (Pnode)malloc(sizeof(Node));
    head1->power = head->power;
    int length = head1->coust = head->coust;
    for (int i = 0; i < length; i++) {
        tempOfHead1->next = (Pnode)malloc(sizeof(Node));
        tempOfHead1 = tempOfHead1->next;
        tempOfHead = tempOfHead->next;
        tempOfHead1->coust = tempOfHead->coust;
        tempOfHead1->power = tempOfHead->power;
        tempOfHead1->next = 0;
    }
    return head1;
}
void add(Pnode head1, Pnode head2) {
    Pnode temp1 = head1->next;
    Pnode temp2 = head2;
    Pnode temp = 0;
    int isInsert = 0;
    for (;temp1 != 0;) {
        temp2 = findEle(temp1->power, temp2);
        insert(&isInsert, temp1, temp2);
        if (isInsert == 1) {
            head2->coust++;
        }
        else if (isInsert == -1) {
            head2->coust--;
        }
        temp1 = temp1->next;
    }
}
Pnode multi(Pnode head1, Pnode head2) {
    Pnode temp1 = head1;
    Pnode temp2 = head2;
    Pnode multi = (Pnode)malloc(sizeof(Node));
    Pnode temp3 = 0;
    Pnode temp = 0;
    multi->coust = 0;
    multi->next = 0;
    multi->power = 9999;
    if (head1->coust == 0 || head2->coust == 0) {
        return multi;
    }
    else {
        temp1 = head1->next;
        //temp2 = head2->next;
        int isInsert = 0;
        for (; temp1 != 0; temp1 = temp1->next) {
            temp2 = head2->next;
            temp3 = multi;
            for (; temp2 != 0; temp2 = temp2->next) {
                temp = (Pnode)malloc(sizeof(Node));
                temp->power = temp1->power + temp2->power;
                temp->coust = temp1->coust * temp2->coust;
                temp->next = 0;
                temp3 = findEle(temp->power, temp3);
                insert(&isInsert, temp, temp3);
                if (isInsert == 1)
                    multi->coust++;
                else if (isInsert == -1)
                    multi->coust--;
                free(temp);
            }
        }
    }
    return multi;
}
void printResult(Pnode head) {
    if (head->coust == 0) {
        printf("%d %d", 0, 0);
    }else
    {
        Pnode  temp = head->next;
        printf("%d %d", temp->coust, temp->power);
        temp = temp->next;
        for (;temp != 0; temp = temp->next) {
            if (temp->coust == 0) {
                continue;
            }else {
                printf(" %d %d", temp->coust, temp->power);
            }
        }
    }
    printf("\n");
}
Pnode findEle(int power, Pnode head) {
    Pnode temp = head;
    for (; temp!= 0;) {
        if (temp->power == power || temp->next == 0) {
            return temp;
        }
        else {
            if(temp->next->power >= power)
                temp = temp->next;
            else
                return temp;
        }
    }
    return temp;
}
void insert(int * isInsert, Pnode head1, Pnode head2) {
    if (head2->power == head1->power) {
        head2->coust += head1->coust;
        if (head2->coust == 0) {
            *isInsert = -1;
            //if(head2->next != 0)
                //head2->next = head2->next->next;
            
            return;
        }
        *isInsert = 0;
    }else {
            Pnode temp = (Pnode)malloc(sizeof(Node));
            temp->coust = head1->coust;
            temp->power = head1->power;
            temp->next = head2->next;
            head2->next = temp;
            *isInsert = 1;      
    }
}

Summary

?總體感覺還是有些難度的,主要難點在于findEle中,因為有幾種尋找方式,不同的尋找方式會導(dǎo)致insert操作會有所不同
?而且有些查找方式不能很好的照顧到邊界情況,例如在第一個節(jié)點前面插入一個節(jié)點,最后一個節(jié)點后面插入一個節(jié)點,或者不同的終止條件會造成可能不能遍歷最后一個節(jié)點等等,如果不仔細想好合適的查找方式,很容易不能照顧到邊界情況
?還要說一點,還是要多考慮極限情況才能比較順暢的答題,否則很容易陷入打補丁式的編寫

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容