一元多项式的乘法与加法运算

问题描述

设计函数分别求两个一元多项式的乘积与和。

输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出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

解决思路

解决这个问题主要有数组实现链表实现两种方法,为了训练使用链表,以及可能会出现超时或者内存不足的情况,本文中是用链表形式来实现多项式的加法,乘法运算

数组实现

在加法数组中:(index-1000)表示指数,里面的内容表示系数
在加法数组中:(index-2000)表示指数,里面的内容表示系数
使用两个大小为2002*sizeof(int)数组来接受数据(因为绝对值不大于1000,最后一项放非零项的个数

定义存放加法结果的数组(大小同样为2002),初始化为0
将两个多项式分别放入加法数组中,对应的指数的系数+=放入系数即可;

定义存放乘法结果的数组(大小为4002)初始化为0
poly1(多项式1,下同)每个项分别乘以poly2,放到乘法数组之中,对应系数+=放入系数即可;

输出:首先先看非零项为0,便输出0 0,如果不是,则便利整个结果数组,只有遇到内容不是0,才输出对应系数和指数

算法分析

简单概括思路,只需要通过下标找到指数即可,然后对应内容加上系数。输出遇到系数为0便不输出

操作较为简单,如果非零项较小,便会有很多空的节点,内存开销太大,并且每次输入系数,输出都需要遍历整个数组,使得效率非常低

链表实现

1.首先使用链表接受数据,每个节点的数据格式如下:
[coust, power next]
[系数,指数,下一个节点地址]
头节点中的系数域用于放置非零项个数,指数域预置一个比较大的数(用处后面将讲解)

2.首先需要知道一点,在本题中多项式乘法的实现本质是加法的实现,因为多项式中乘法可以分解成为加法。乘法结果可以分解为poly1每个项乘以poly2的和,所以下面着重讲解加法的实现

3.我们使用一个空链表来存储加法结果(系数项预置为0,指数项预置为大于4000的值),接下来我们要做的便是分别把两个多项式放入这个链表中

放入这个链表的动作可以分为两步:
step1:通过传入需要放入的项的指数,在目标链表找到放的位置(return的是放的位置的地址)
step2:通过地址找到的节点,将系数放进去

乘法运算便是每个项与另一个项相乘形成的多项式分别放入乘法链表之中

4.输出链表,若头节点系数域为0,输出0 0;否则则遍历整个链表 遇到系数非零才会输出项

Some Detail Of Function(建议配合代码食用

Pnode createList(void):用于存放输入数据,没什么好说的
Pnode copyList(Pnode head):将链表拷贝到一个新链表

Notice:这里需要说明一下copyList在代码中的作用。在加法运算中,我的存放加法结果的addPoly本身不是空的,是已经拷贝了Poly1内容的链表,目的是为在加法运算时的方便,直接将poly2加入其中即可。不需要把poly1加入addPoly,再把poly2也加入

void add(Pnode head1, Pnode head2):head1是加式,head2是被加式。也就是说,把head1加到head2上,最后head2存放的是加法结果(isInsert待会会讲解用处
1.每次temp1指向head1的存放数据的节点,将temp1->power传入findEle函数,寻找head2中的合适地址用于插入或者直接放入(下面会详细讲解
2.使用insert函数将该项放入head2之中,然后temp1指向下一个节点

Pnode findEle(int power, Pnode head):传入指数,在被加式head中寻找出一个合适的地址并返回该地址;为什么会说是合适的地址?因为我们对加入项的操作可能是插入,或者不需要插入。如下图所示:

image.png

image.png

 由上图所示,有相同指数的项,便改变其系数,如果没有则插入一个新的项
 所以该地址的作用便是对指向的节点修改系数,或者在指向的节点后面插入一个新的项
 在这里也就可以解释为什么头节点的power会设置成一个比较大的数字!(我们是从头节点开始寻找的!)
 因为按照findEle函数的查找方式,如果没有设置头节点的power,那么有一个比第一个项更高次幂的项便会插入困难,如果从第一项开始比较,便会有可能让链表断裂,因为temp2的上一个节点我们是没有的!

 值得一提的是,在整个加法插入中,我们只需遍历一次多项式,便可以整个加法运算,因为输入的项的指数是按从高到低的顺序

因为这块是难点重点,所以稍微总结一下:
 我们首先传入power,通过它来寻找一个合适的位置,传入的head便是从head指向的节点开始向后寻找(第一次使用这个函数传入的head都是指向头节点的)
 在寻找的过程中if (temp->power == power || temp->next == 0),便返回temp;if(temp->next->power >= power),便更新temp,否则便表示结果是需要在temp后面插入节点,返回temp;

void insert(int * isInsert, Pnode head1, Pnode head2):将项插入节点后面后者修改该节点
 这里可以解释isInsert的作用,如果表示插入,那么我们便会把isInsert改成1,表示头结点的非零项的数目需要++;如果表示修改,便查看修改后的系数是否等于零,如果为零,便会改成1。表示需要将非零项的个数--;若不等于零便会改成0,不需要修改非零项的个数

Pnode multi(Pnode head1, Pnode head2):核心和加法运算大致相同,只是多了一层二重循环,来执行乘法,看懂了上面仔细阅读即可了解

void printResult(Pnode head):输出结果

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中,因为有几种寻找方式,不同的寻找方式会导致insert操作会有所不同
 而且有些查找方式不能很好的照顾到边界情况,例如在第一个节点前面插入一个节点,最后一个节点后面插入一个节点,或者不同的终止条件会造成可能不能遍历最后一个节点等等,如果不仔细想好合适的查找方式,很容易不能照顾到边界情况
 还要说一点,还是要多考虑极限情况才能比较顺畅的答题,否则很容易陷入打补丁式的编写

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容