详解-线性结构-一元多项式的乘法与加法运算

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

解题方法:线性表
题目要求很简单,求两个一元多项式的乘积与和,用数学表达式直观的描述就是存在两个多项式:
a 1 x b 1 + a 2 x b 2 + . . . + a i x b i (1) a_1x^{b_1}+a_2x^{b_2}+...+a_ix^{b_i} \tag{1} a1xb1+a2xb2+...+aixbi(1) c 1 x d 1 + c 2 x d 2 + . . . + c j x d j (2) c_1x^{d_1}+c_2x^{d_2}+...+c_jx^{d_j} \tag{2} c1xd1+c2xd2+...+cjxdj(2) ( a 1 x b 1 + . . . + a i x b i ) + ( c 1 x d 1 + . . . + c j x d j ) (3) (a_1x^{b_1}+...+a_ix^{b_i})+(c_1x^{d_1}+...+c_jx^{d_j}) \tag{3} (a1xb1+...+aixbi)+(c1xd1+...+cjxdj)(3) ( a 1 x b 1 + . . . + a i x b i ) ∗ ( c 1 x d 1 + . . . + c j x d j ) (4) (a_1x^{b_1}+...+a_ix^{b_i})*(c_1x^{d_1}+...+c_jx^{d_j}) \tag{4} (a1xb1+...+aixbi)(c1xd1+...+cjxdj)(4)

先分析 ( 3 ) (3) (3)式,相较于 ( 4 ) (4) (4)式而言更简单,做法是遍历两式子的各项,因为输入的已经是按指数递降的方式输入,因此考虑使用链表实现,维护一个链表如下

struct LNode{
    int val; //项值
    int index; //指数值
    List next; //下一个节点指针
};

先比较 b 1 b_1 b1 d 1 d_1 d1的大小,将大的指数对应的系数进行赋值,若两个指数相等,则将 a 1 + c 1 a_1+c_1 a1+c1进行赋值,此处应注意系数相抵消的情况,若 b 1 b_1 b1大,接下来比较 b 2 b_2 b2 d 1 d_1 d1的大小,若 d 1 d_1 d1大,接下来比较 b 1 b_1 b1 d 2 d_2 d2的大小,依次类推。

接下来分析 ( 4 ) (4) (4)式,乘法最基本的思路是将多项式展开,即
( 4 ) = a 1 x b 1 ∗ ( c 1 x d 1 + . . . + c j x d j ) + . . . + a i x b i ∗ ( c 1 x d 1 + . . . + c j x d j ) (5) (4) = a_1x^{b_1}*(c_1x^{d_1}+...+c_jx^{d_j})+...+a_ix^{b_i}*(c_1x^{d_1}+...+c_jx^{d_j}) \tag{5} (4)=a1xb1(c1xd1+...+cjxdj)+...+aixbi(c1xd1+...+cjxdj)(5)因此考虑两层循环遍历,外层循环遍历 ( 1 ) (1) 1式,内层循环遍历 ( 2 ) (2) 2式,实现 ( 5 ) (5) 5式的相乘,维护一个链表用作累加,每次结束内层循环将得到的链表累加,当两层循环结束后即得到 ( 5 ) (5) 5式的结果。

实现的思路到此为止,可能有些地方解释的不是很清楚,如果没理解不用担心,直接看程序也可以,程序中关键部分都已经注释了。

完整的程序如下:

#include <stdio.h>
#include <stdlib.h>

typedef struct LNode *List;
struct LNode{
    int val; //项值
    int index; //指数值
    List next; //下一个节点指针
};

void Print(List L); //打印链表
List creatList(int n); //创建链表
List polySum(List L1, List L2); //多项式加法
List polyMul(List L1, List L2); //多项式乘法

int main(){
    int n1, n2; //两行输入链表的长度
    List L1, L2; //捕获的两行输入
    List res1, res2; //多项式乘法的链表和加法的链表
    scanf("%d", &n1);
    L1 = creatList(n1);
    scanf("%d", &n2);
    L2 = creatList(n2);
    res1 = polyMul(L1, L2);
    res2 = polySum(L1, L2);
    Print(res1);
    Print(res2);

    return 0;
}

List creatList(int n){
    List L = (List)malloc(sizeof(struct LNode));
    List L_temp = L;
    int val, index;
    while(n--){
        List temp = (List)malloc(sizeof(struct LNode)); //创建一个临时链表
        scanf("%d %d", &val, &index);
        temp->val = val;
        temp->index = index;
        L_temp->next = temp;
        L_temp = L_temp->next;
    }
    L_temp->next = NULL;
    return L;
}

void Print(List L)
{
   List p=L->next;
   if(p)
   {
       List r;
       r = L;
       while(r->next)
       {
           r = r->next;
           if(r->next)
               printf("%d %d ",r->val, r->index);
           else
               printf("%d %d",r->val, r->index);
       }
   }
   else
   {
    printf("0 0"); //题目要求0多项式式子输出0 0
   }
   printf("\n");
}

List polySum(List L1, List L2){
    List res = creatList(0); //目标链表的表头
    int temp_val;
    List res_temp = res; //目标链表的临时链表,用于链接
    List l1 = L1->next;
    List l2 = L2->next;

    while(l1 && l2){
        List temp = (List)malloc(sizeof(struct LNode));
        if(l1->index > l2->index){ //链表l1的指数大
            temp->val = l1->val;
            temp->index = l1->index;
            l1 = l1->next;
            res_temp->next = temp;
            res_temp = res_temp->next;
        }
        else if(l1->index < l2->index){ //链表l2的指数大
            temp->val = l2->val;
            temp->index = l2->index;
            l2 = l2->next;
            res_temp->next = temp;
            res_temp = res_temp->next;
        }
        else{ //两个链表指数相等
            temp_val = l1->val + l2->val;
            if(temp_val != 0){ //判断项数是否为0,为0则跳过
            temp->val = temp_val;
            temp->index = l1->index;
            res_temp->next = temp;
            res_temp = res_temp->next;
            }
            l1 = l1->next;
            l2 = l2->next;
        }

    }
    res_temp->next = l1 ? l1 : l2; //将l1和l2中较长者的剩余部分链接上去

    return res;
}

List polyMul(List L1, List L2){
    List res = creatList(0);
    List l1 = L1->next;
    List l2 = L2->next;
    if(l1==NULL || l2==NULL) //如果存在0多项式则结果为0
        return res;

    while(l1){ //乘法展开,两层遍历
        List temp1 = (List)malloc(sizeof(struct LNode));
        List temp1_temp = temp1;
        l2 = L2->next; //每次遍历完一遍L2,要从表头继续遍历
        while(l2){
            List temp2 = (List)malloc(sizeof(struct LNode));
            temp2->index = l1->index + l2->index;
            temp2->val = l1->val * l2->val;
            temp1_temp->next = temp2;
            temp1_temp = temp1_temp->next;
            l2 = l2->next;
        }
        temp1_temp->next = NULL;
        res = polySum(temp1, res);
        l1 = l1->next;
    }
    return res;
}

如果有哪里理解错的地方欢迎大家留言交流,如需转载请表明出处。

手工码字码代码,如果有帮助到你的话留个赞吧,谢谢。

以上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值