3.3.Polynomial_add 一元多项式相加

题目描述

编写一元多项式加法运算程序。要求用线性链表存储一元多项式(参照课本)。

输入:输入三个多项式,建立三个多项式链表Pa、Pb、Pc(提示:调用CreatePolyn(polynomial &P,int m)。输入格式要求如下所示:

1

多项式A包含的项数,以指数递增的顺序输入多项式A各项的系数(整数)、指数(整数)

多项式B包含的项数,以指数递增的顺序输入多项式B各项的系数(整数)、指数(整数)

多项式C包含的项数,以指数递增的顺序输入多项式C各项的系数(整数)、指数(整数)

0 ---操作终止,退出。

输出:显示三个输入多项式Pa、Pb、Pc、和多项式Pa+Pb、多项式Pa+Pb+Pc(提示:调用AddPolyn(polynomial &Pa, polynomial Pb), 调用PrintPolyn(polynomial P))。

多项式输出格式:以指数递增的顺序输出: <系数,指数>,<系数,指数>,<系数,指数>。零多项式的输出格式为<0,0>。

解题思路

该题用链表来储存多项式的项,首先要弄清表达形式:

这里使用系数、指数的形式来连续储存,并且构造出题目要求的函数实现的功能。

typedef struct TERM* ptr;
struct TERM {
    int Coefficient;
    int Exponent;
    ptr Next;
};
typedef ptr Polynomial;

void CreatePolyn(Polynomial P, int m);
Polynomial AddPolyn(Polynomial Pa, Polynomial Pb);
void PrintPolyn(Polynomial P);

下一步是构造多项式(CreatePolyn()):

m表示多项式项数,表示多项式头结点为空(第一项为下一项)。本题多项式都是按照指数递增的形式,所以不用调序。

void CreatePolyn(Polynomial P, int m)
{
    ptr cur = P->Next = (ptr)malloc(sizeof(struct TERM));
    for (int n = 0; n < m; n++)
    {
        int coef, comp;
        cin >> coef >> comp;
        cur->Coefficient = coef;
        cur->Exponent = comp;
        if (n == m - 1)
            cur->Next = NULL;
        else
        {
            cur->Next = (ptr)malloc(sizeof(struct TERM));
            cur = cur->Next;
        }
    }
    return;
}

然后输出函数(PrintPolyn()):

这其中主要的问题是0多项式,也就是表示为<0,0>时的特判;由于我在处理中,为方便后续的结点输出,是系数为零即删除。这就需要讨论只有头结点的多项式仍有一个输出<0,0>.这里用了flag来记录是否有项输出。

void PrintPolyn(Polynomial P)
{
    ptr cur = P->Next;
    int flag = 0;
    while (cur != NULL) {
        cout << '<' << cur->Coefficient << ',' << cur->Exponent << '>';
        if (cur->Next != NULL) {
            cout << ',';
        }
        cur = cur->Next;
        flag = 1;
    }
    if (!flag) {
        cout << '<' << '0' << ',' << '0' << '>';
    }
    cout << endl;
    return;
}

题目主要部分是多项式相加。考虑两种方式:

(1)一种是将其中一个加到另一个上,然后输出被加的这个;

(2)将结果生成为一个新的多项式。

第二种方式的遍历顺序和易错点比较少,也不需考虑一些阴间的情况,首先选择第二种。

然而,我首次采用的方式就是第一种,debug时还以为实现是错误的,而且代码也长得相当难看,最后结构比较混乱,还有goto语句。(看得出伤痕累累、受尽折磨…)这种方法实际上需要讨论指数大小的情况,类似于模拟一个人计算的过程,要先模拟对齐(which也是最折磨的)。我是将A作为被加的。大体思路是:

i、首先检测B是否为空,不然不用加了;

ii、检测A为空,这样的话需要把B复制到A,输出A;

iii、在循环中开始相加:如果A的指数小,那么需要在A中增加新的结点并赋值该B结点的值,反之一直寻找A指数更大的结点;

iv、相加时系数为0要删除,但是,删除后需要注意就只有B需要后移一位来进行下一轮;

v、在iii中需要注意的点是可能会遇到还未达到指数相等就结束的情况,这其中只有在A的系数小于B的系数的时候还需要做收尾工作(如果B结束就不加到A上了,没影响):在结束的A的尾部还需要将B的剩余部分复制。

在代码实现时,我将ii中和v中的B到A的复制操作合并了,所以出现了一个goto语句。

void AddPolyn(Polynomial Pa, Polynomial Pb)
{
    ptr ptra = Pa, ptrb = Pb;
    if (ptrb->Next == NULL)
        return;
    if (ptra->Next == NULL)
        goto CopyPbToPa;
    while (1) {
        if (ptrb->Next->Exponent < ptra->Next->Exponent) {
            while (ptrb->Next != NULL && ptrb->Next->Exponent < ptra->Next->Exponent) {
                ptr cur = (ptr)malloc(sizeof(struct TERM));
                cur->Next = ptra->Next;
                ptra->Next = cur;
                ptra = cur;

                cur->Exponent = ptrb->Next->Exponent;
                cur->Coefficient = ptrb->Next->Coefficient;

                ptrb = ptrb->Next;
            }
            if (ptrb->Next == NULL) {
                break;
            }
            continue;
        }

        else if (ptrb->Next->Exponent > ptra->Next->Exponent) {
            while (ptra->Next != NULL && ptra->Next->Exponent < ptrb->Next->Exponent)
                ptra = ptra->Next;
            if (ptra->Next == NULL) {
                break;
            }
            continue;
        }

        ptra->Next->Coefficient += ptrb->Next->Coefficient;
        int flag = 0;
        if (ptra->Next != NULL && ptra->Next->Coefficient == 0) {
            ptr tmp = ptra->Next;
            ptra->Next = ptra->Next->Next;
            free(tmp);
            flag = 1;
        }
        if (flag) {
            ptrb = ptrb->Next;
        }
        else {
            ptra = ptra->Next;
            ptrb = ptrb->Next;
        }

        if (ptra->Next == NULL || NULL == ptrb->Next)
            break;
    }

    CopyPbToPa:
    while (ptrb->Next != NULL) {
        ptr cur = (ptr)malloc(sizeof(struct TERM));
        cur->Next = NULL;
        ptra->Next = cur;
        ptra = cur;

        cur->Exponent = ptrb->Next->Exponent;
        cur->Coefficient = ptrb->Next->Coefficient;

        ptrb->Next = ptrb->Next->Next;
    }
    return;
}

贴源代码

还是应当给出相对好理解和使用的生成新的多项式的一种,这其中就是两列多项式同时移动,相同才相加,不相同就不加选指数小的;同时也有关于尾部结束的处理问题,但简单,也就是把没加完的加到新多项式(newpoly)

#include <iostream>
using namespace std;

typedef struct TERM* ptr;
struct TERM {
    int Coefficient;
    int Exponent;
    ptr Next;
};
typedef ptr Polynomial;

void CreatePolyn(Polynomial P, int m);
Polynomial AddPolyn(Polynomial Pa, Polynomial Pb);
void PrintPolyn(Polynomial P);
int main() {
    int status = 0;
    Polynomial Pa = (ptr)malloc(sizeof(struct TERM)), Pb = (ptr)malloc(sizeof(struct TERM)), Pc = (ptr)malloc(sizeof(struct TERM));
    cin >> status;
    if (status) {
        int m;
        cin >> m;
        CreatePolyn(Pa, m);
        cin >> m;
        CreatePolyn(Pb, m);
        cin >> m;
        CreatePolyn(Pc, m);

        PrintPolyn(Pa);
        PrintPolyn(Pb);
        PrintPolyn(Pc);
        Polynomial ab = AddPolyn(Pa, Pb);
        PrintPolyn(ab);
        Polynomial abc = AddPolyn(ab, Pc);
        PrintPolyn(abc);
    }
    return 0;
}

void CreatePolyn(Polynomial P, int m)
{
    ptr cur = P->Next = (ptr)malloc(sizeof(struct TERM));
    for (int n = 0; n < m; n++)
    {
        int coef, comp;
        cin >> coef >> comp;
        cur->Coefficient = coef;
        cur->Exponent = comp;
        if (n == m - 1)
            cur->Next = NULL;
        else
        {
            cur->Next = (ptr)malloc(sizeof(struct TERM));
            cur = cur->Next;
        }
    }
    return;
}

Polynomial AddPolyn(Polynomial Pa, Polynomial Pb) {
    ptr pa = Pa->Next, pb = Pb->Next, newpoly = (ptr)malloc(sizeof(struct TERM)), pre = newpoly, cur = NULL;

    while (pa != NULL && pb != NULL) {
        cur = (ptr)malloc(sizeof(struct TERM));
        //新和结点

        if (pa->Exponent == pb->Exponent) {
            if (0 == pa->Coefficient + pb->Coefficient) {
                pa = pa->Next;
                pb = pb->Next;
                pre->Next = NULL;
                free(cur);
                continue;
            }
            cur->Coefficient = pa->Coefficient + pb->Coefficient;
            cur->Exponent = pa->Exponent;
            pa = pa->Next;
            pb = pb->Next;
        }//可加时

        else {
            ptr tmp = pa->Exponent < pb->Exponent ? pa : pb;
            cur->Coefficient = tmp->Coefficient;
            cur->Exponent = tmp->Exponent;
            if (tmp == pa) pa = pa->Next;
            else pb = pb->Next;
        }

        //连接链表
        pre->Next = cur;
        cur->Next = NULL;
        pre = cur;
    }
    while (NULL != pa) {
        cur = (ptr)malloc(sizeof(struct TERM));
        cur->Coefficient = pa->Coefficient;
        cur->Exponent = pa->Exponent;
        pa = pa->Next;
        pre->Next = cur;
        cur->Next = NULL;
        pre = cur;
    }
    while (NULL != pb) {
        cur = (ptr)malloc(sizeof(struct TERM));
        cur->Coefficient = pb->Coefficient;
        cur->Exponent = pb->Exponent;
        pb = pb->Next;
        pre->Next = cur;
        cur->Next = NULL;
        pre = cur;
    }

    return newpoly;
}

void PrintPolyn(Polynomial P)
{
    ptr cur = P->Next;
    int flag = 0;
    while (cur != NULL) {
        cout << '<' << cur->Coefficient << ',' << cur->Exponent << '>';
        if (cur->Next != NULL) {
            cout << ',';
        }
        cur = cur->Next;
        flag = 1;
    }
    if (!flag) {
        cout << '<' << '0' << ',' << '0' << '>';
    }
    cout << endl;
    return;
}


——2022.10.10

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值