PTA 习题3.6 一元多项式的乘法与加法运算

题目

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

输入格式:
输入分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

题目不算难,但是我实力不够,踩了不少坑,包括将得到的乘法多项式按照降序插入结果多项式时,一直因为空指针处理得不好而导致失败;合并同类项忘记判断合并后的系数是否为0。
甚至一开始算加法多项式时,我将list1和list2的节点直接插入到结果多项式中,破坏了链表的结构,导致求乘法多项式一直得不到想要的数据。
刷提前理清思路真的很重要,以后再也不会一上来就直接写代码了。

1、加法多项式

题目给出的输入已经按照降幂顺序排列好,相加时不需要考虑顺序的问题,同时加法也不需要考虑同类项合并,但加法需要考虑系数互为相反数的项相加为0的情况。

运算思路:
分别令pq指向list1list2(即两个多项式)的第一项数据
当p的指数大于q的指数,将节点p复制给新节点newNode,将newNode移动到result的末尾,p往后移动,q不动
p的指数小于q的指数,将节点q复制给新节点newNode,将newNode移动到result的末尾,q往后移动,p不动
p的指数等于q的指数,若pq的系数相加不为0,则复制到结果多项式,为0则舍弃。之后pq都要向后移动
如果pq还有剩余的节点,直接接到结果多项式的末尾
如果给出的输入,所以项全部抵消了,或本身给出的输入就是零多项式,此时结果多项式为空表,输出0 0

在这里插入图片描述

2、乘法多项式

乘法不用考虑相乘系数为0的情况,但需要考虑顺序和同类项合并的问题。

用二重循环得到多项式相乘的所有结果
将每个结果节点newNode插入到结果多项式中合适的位置(按照指数降序排列)

  1. 先找到正确的插入位置,从结果多项式开头按顺序查找,找到第一个小于等于自己系数的项
  2. 如果小于,直接插入
  3. 如果等于,则要合并同类项,要记得判断合并后的系数是否为0,是则删除这个项

在这里插入图片描述
动图来源

代码

#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
    int coefficient; //系数
    int exponent;    //指数
    struct Node *next;
} Node, *LinkList;

void initList(LinkList *head)
{
    if ((*head = (LinkList)malloc(sizeof(Node))) == NULL)
        exit(-1);
    (*head)->next = NULL;
}
void creatList(LinkList head)
{
    LinkList p, tail = head;
    int count;
    scanf("%d", &count);
    while (count-- > 0)
    {
        p = (LinkList)malloc(sizeof(Node));
        scanf("%d%d", &p->coefficient, &p->exponent);
        tail->next = p;
        tail = p;
    }
    tail->next = NULL;
}
void printList(LinkList head)
{
    LinkList p = head->next;
    while (p)
    {
        if (p == head->next)
            printf("%d %d", p->coefficient, p->exponent);
        else
            printf(" %d %d", p->coefficient, p->exponent);
        p = p->next;
    }
}

void addition(LinkList list1, LinkList list2)
{
    LinkList result, p = list1->next, q = list2->next, tail, newNode;
    initList(&result);
    tail = result;
    while (p && q)
    {
        int coefficient1, coefficient2, exponent1, exponent2;
        newNode = (LinkList)malloc(sizeof(Node));

        // 当p的指数大于q的指数,将节点p复制给newNode,将newNode移动到result的末尾,p往后移动,q不动
        if (p->exponent > q->exponent)
        {
            newNode->coefficient = p->coefficient;
            newNode->exponent = p->exponent;
            newNode->next = NULL;
            tail->next = newNode;
            tail = newNode;
            p = p->next;
        }
        else if (p->exponent < q->exponent)
        {
            // 当p的指数小于q的指数,将节点q复制给newNode,将newNode移动到result的末尾,q往后移动,p不动
            newNode->coefficient = q->coefficient;
            newNode->exponent = q->exponent;
            newNode->next = NULL;
            tail->next = newNode;
            tail = newNode;
            q = q->next;
        }
        else
        {
            // 当p和q的指数相等,直接将两个的系数相加。如果相加后的系数为0,则将p,q直接移动到下一位
            if (p->coefficient + q->coefficient == 0)
            {
                p = p->next;
                q = q->next;
                free(newNode);
            }
            else
            {
                newNode->coefficient = p->coefficient + q->coefficient;
                newNode->exponent = p->exponent;
                newNode->next = NULL;
                tail->next = newNode;
                tail = newNode;
                p = p->next;
                q = q->next;
            }
        }
    }
    // 如果p或q还有剩余节点,直接接到result的末尾
    if (!p)
    {
        tail->next = q;
    }
    if (!q)
    {
        tail->next = p;
    }

    if (!result->next)
    {
        free(result);
        printf("0 0");
    }
    else
    {
        printList(result);
    }
}

void multiplication(LinkList list1, LinkList list2)
{
    LinkList result, p = list1->next, q , tail, newNode;
    initList(&result);
    tail = result;
    while (p)
    {
        q = list2->next;
        while (q)
        {
            // 创建新建的newNode
            newNode = (LinkList)malloc(sizeof(Node));
            newNode->coefficient = p->coefficient * q->coefficient;
            newNode->exponent = p->exponent + q->exponent;
            newNode->next = NULL;

            LinkList temp = result;
            // 找到合适的插入位置
            while (temp->next && newNode->exponent < temp->next->exponent)
            {
                temp = temp->next;
            }
            // 插入或者合并同类项
            if (temp->next == NULL || newNode->exponent > temp->next->exponent)
            {
                newNode->next = temp->next;
                temp->next = newNode;
            }
            else if (newNode->exponent == temp->next->exponent)
            {
                temp->next->coefficient += newNode->coefficient;
                // 如果合并同类项后系数为0,得删除这个节点
                if(!temp->next->coefficient){
                    LinkList deleteNode=temp->next;
                    temp->next=deleteNode->next;
                    free(deleteNode);
                }
                free(newNode);
            }
            q = q->next;
        }
        p = p->next;
    }
    if (!result->next)
    {
        free(result);
        printf("0 0");
    }
    else
    {
        printList(result);
    }
}
int main()
{
    LinkList list1, list2;
    initList(&list1);
    initList(&list2);
    creatList(list1);
    creatList(list2);
    multiplication(list1, list2);
    printf("\n");  
    addition(list1, list2);
    return 0;
}

  • 18
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值