zoukankan      html  css  js  c++  java
  • 多个有序链表的合并[续]---一元多项式的乘法与加法运算

    02-线性结构2 一元多项式的乘法与加法运算(20 分)

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

    输入格式:

    输入分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
    
     
    解题思路:
    1.首先确定多项式的数据模型:
    typedef struct node* Polynomial;
    struct node{
        int coef;
        int exp;
        Polynomial link;
    };

    将多项式看作链表,多项式中的每一个非零项看作链表的结点

    所以指数递降方式输入一个多项式就是一个有序链表

    两个多项式相加就可以看作是有序链表合并

    两个多项式相乘A*B:

    1.可先取A的第一项依次乘以B的所有项

    2.会得到一个指数递降多项式,计为有序链表A1

    3.取A的第二项依次乘以B的所有项,得到有序链表A2

    4.为避免累计多个多项式,立即合并A1,A2得到A12

    5.取A的第三项依次乘以B的所有项,得到有序链表A3, 合并A12,A3 ,依次类推

    总结:多项式相乘可以看成多项式多次相加,所以重点在于怎么写相加函数。相乘不过是单链表合并的升级罢了

    2.由输入构建多项式

    技巧:

    先创建头结点,便于书写循环

    每次循环生成一个结点,并建立和前一个结点的关系(需要头结点)

    最后删除头结点

    封装Attach函数,方便构建多项式,传入多项式的头结点,要以指针方式传入.

    因为每次调用,生成一个新的结点,创建和前面结点关系后,要修改这个头结点,如此链接关系才能延续,只有传指针才能改值

     1 void Attach(int coet, int exp, Polynomial* pLeader){
     2     Polynomial p = (Polynomial)malloc(sizeof *p);
     3     p->coef = coet;
     4     p->exp = exp;
     5     p->link = NULL;
     6     (*pLeader)->link = p;
     7     (*pLeader) = (*pLeader)->link;
     8 }
     9 
    10 Polynomial readPoly(){
    11     int N;
    12     int c, e;
    13     Polynomial pRear = (Polynomial)malloc(sizeof *pRear);//创建头结点
    14     Polynomial p = pRear;
    15     Polynomial t;
    16     scanf("%d", &N);
    17     if (0 == N){
    18         return NULL; //3    输入有零多项式和常数多项式    段错误    2 ms    256KB
    19     }
    20     while (N--){
    21         scanf("%d %d", &c, &e);
    22         /*pRear = (pRear->link = (Polynomial)malloc(sizeof *p));
    23         pRear->coef = c;
    24         pRear->exp = e;
    25         pRear->link = NULL;*/ //便于复用,抽象成函数Attach
    26         Attach(c, e, &pRear);
    27     }
    28     t = p; 
    29     p = p->link; 
    30     free(t);//删除头结点
    31     return p;
    32 }

    3.多项式相加

    合并有序链表,使用循环方式,

    不选择递归,主要基于两点考虑

    1.合并需要考虑许多细节,采用循环易控制

    2.合并不能影响原来链表,就不能复用原结点,用递归没有优势

     1 //循环方式
     2 Polynomial Add(Polynomial p1, Polynomial p2){
     3     Polynomial merge = (Polynomial)malloc(sizeof *merge);//创建头结点
     4     Polynomial mergeHead = merge;
     5     Polynomial t;
     6     if (p1 == NULL){
     7         return p2;
     8     }
     9     if (p2 == NULL){
    10         return p2;
    11     }
    12 
    13     while (p1 && p2){
    14         Polynomial temp = (Polynomial)malloc(sizeof *temp);//每次循环新增结点,避免破坏原多项式
    15         if (p1->exp > p2->exp){
    16             temp->coef = p1->coef;
    17             temp->exp = p1->exp;
    18             merge->link = temp;
    19             p1 = p1->link;
    20         }
    21         else if (p1->exp == p2->exp){
    22             temp->coef = p1->coef + p2->coef;
    23             if (0 == temp->coef){//1    同类项合并时有抵消    答案错误    2 ms    256KB
    24                 p1 = p1->link;
    25                 p2 = p2->link;
    26                 continue;
    27             }
    28             else{
    29                 temp->exp = p1->exp;
    30             }
    31             merge->link = temp;
    32             p1 = p1->link;
    33             p2 = p2->link;
    34         }
    35         else{
    36             temp->coef = p2->coef;
    37             temp->exp = p2->exp;
    38             merge->link = temp;
    39             p2 = p2->link;
    40         }
    41         merge = merge->link;
    42     }
    43     merge->link = p1 ? p1 : p2;// 处理剩下的,相当于有序链表
    44     if (NULL == mergeHead->link){//全部抵消时,生成 0 0 结点
    45         merge->link = zero;//2    系数和指数取上限,结果有零多项式    答案错误    2 ms    240KB
    46     }
    47     t = mergeHead;
    48     mergeHead = mergeHead->link;
    49     free(t);//删除头结点
    50     return mergeHead;
    51 }

    freopen("data.txt", "r", stdin);//输入重定向,方便调试

    可以将scanf的输入定向到文件,调试oj的利器

    完整程序:

    #include<iostream>
    using std::cout;
    using std::endl;
    typedef struct node* Polynomial;
    struct node{
        int coef;
        int exp;
        Polynomial link;
    };
    
    Polynomial zero = (Polynomial)malloc(sizeof *zero);//全局变量,处理零多项式情况
    
    void Attach(int coet, int exp, Polynomial* pLeader){
        Polynomial p = (Polynomial)malloc(sizeof *p);
        p->coef = coet;
        p->exp = exp;
        p->link = NULL;
        (*pLeader)->link = p;
        (*pLeader) = (*pLeader)->link;
    }
    
    Polynomial readPoly(){
        int N;
        int c, e;
        Polynomial pRear = (Polynomial)malloc(sizeof *pRear);//创建头结点
        Polynomial p = pRear;
        Polynomial t;
        scanf("%d", &N);
        if (0 == N){
            return NULL; //3    输入有零多项式和常数多项式    段错误    2 ms    256KB
        }
        while (N--){
            scanf("%d %d", &c, &e);
            /*pRear = (pRear->link = (Polynomial)malloc(sizeof *p));
            pRear->coef = c;
            pRear->exp = e;
            pRear->link = NULL;*/ //便于复用,抽象成函数Attach
            Attach(c, e, &pRear);
        }
        t = p; 
        p = p->link; 
        free(t);//删除头结点
        return p;
    }
    
    void printPoly(Polynomial p){
        while (p != NULL){
            if (p->link == NULL){//0    sample换个数字    答案正确    3 ms    244KB
                cout << p->coef <<" "<< p->exp;
            }
            else{
                cout << p->coef << " " << p->exp << " ";
            }
            p = p->link;
        }
    }
    
    //循环方式
    Polynomial Add(Polynomial p1, Polynomial p2){
        Polynomial merge = (Polynomial)malloc(sizeof *merge);//创建头结点
        Polynomial mergeHead = merge;
        Polynomial t;
        if (p1 == NULL){
            return p2;
        }
        if (p2 == NULL){
            return p2;
        }
    
        while (p1 && p2){
            Polynomial temp = (Polynomial)malloc(sizeof *temp);//每次循环新增结点,避免破坏原多项式
            if (p1->exp > p2->exp){
                temp->coef = p1->coef;
                temp->exp = p1->exp;
                merge->link = temp;
                p1 = p1->link;
            }
            else if (p1->exp == p2->exp){
                temp->coef = p1->coef + p2->coef;
                if (0 == temp->coef){//1    同类项合并时有抵消    答案错误    2 ms    256KB
                    p1 = p1->link;
                    p2 = p2->link;
                    continue;
                }
                else{
                    temp->exp = p1->exp;
                }
                merge->link = temp;
                p1 = p1->link;
                p2 = p2->link;
            }
            else{
                temp->coef = p2->coef;
                temp->exp = p2->exp;
                merge->link = temp;
                p2 = p2->link;
            }
            merge = merge->link;
        }
        merge->link = p1 ? p1 : p2;// 处理剩下的,相当于有序链表
        if (NULL == mergeHead->link){//全部抵消时,生成 0 0 结点
            merge->link = zero;//2    系数和指数取上限,结果有零多项式    答案错误    2 ms    240KB
        }
        t = mergeHead;
        mergeHead = mergeHead->link;
        free(t);//删除头结点
        return mergeHead;
    }
    
    //递归方式,会改变原始结点
    Polynomial Add1(Polynomial p1, Polynomial p2){
        Polynomial mergeHead = NULL;
        if (p1 == NULL){
            return p2;
        }
        if (p2 == NULL){
            return p1;
        }
    
        if (p1->exp > p2->exp){
            mergeHead = p1;
            mergeHead->link = Add1(p1->link, p2);
        }
        else if (p1->exp == p2->exp){
            p1->coef = p1->coef + p2->coef;
            mergeHead = p1;
            mergeHead->link = Add1(p1->link, p2->link);
        }
        else{
            mergeHead = p2;
            mergeHead->link = Add1(p1, p2->link);
        }
        
        return mergeHead;
    }
    
    Polynomial Mult(Polynomial p1, Polynomial p2){
        Polynomial p1Base = p1, p2Base = p2;
        Polynomial mult = (Polynomial)malloc(sizeof *mult);//创建头结点
        Polynomial multHead = mult;
        Polynomial t1;
        
        //p1第一项乘以p2, 产生一个多项式multHead
        if (p1 == NULL){
            return zero;
        }
        while (p2 != NULL)
        {
            int coef = p1->coef * p2->coef;
            int exp = p1->exp + p2->exp;
            Attach(coef, exp, &mult);
            p2 = p2->link;
        }
        t1 = multHead;
        multHead = multHead->link;
        free(t1);
        //产生更多的多项式,由于各中间多项式都是有序的,问题转化为多个有序链表合并
        while ( (p1 = p1->link) != NULL ){
            p2 = p2Base;
            Polynomial temp = (Polynomial)malloc(sizeof *temp);
            Polynomial tempHead = temp;
            Polynomial t2;
            while (p2 != NULL){
                int coef = p1->coef * p2->coef;
                int exp = p1->exp + p2->exp;
                Attach(coef, exp, &temp);
                p2 = p2->link;
            }
            t2 = tempHead;
            tempHead = tempHead->link;
            free(t2);
            
            multHead = Add(multHead, tempHead);
        }
    
        return multHead;
    
    }
    
    int main() {
        //freopen("data.txt", "r", stdin);//输入重定向,方便调试
    
        zero->coef = 0;
        zero->exp = 0;
        zero->link = NULL;
    
        Polynomial P1, P2, PA, PM;
        P1 = readPoly();
        P2 = readPoly();
    
        PM = Mult(P1, P2);
        printPoly(PM);
        cout << endl;
        PA = Add(P1, P2);
        printPoly(PA);
    
        return 0;
    }
    View Code
  • 相关阅读:
    【扯淡篇】SDOI2018丶一轮游丶记
    初来乍到, 多多包涵~
    【学术篇】The Xuanku Inversion Magic学习笔记
    【模板篇】树状数组(六)
    【学术篇】CF932E Team Work && bzoj5093 图的价值
    【模板篇】NTT和三模数NTT
    【学术篇】CF833B TheBakery 分治dp+主席树
    【学术篇】NOI2015 品酒大会 后缀数组+并查集
    【模板篇】数论大杂烩~
    【学术篇】SPOJ GEN Text Generator AC自动机+矩阵快速幂
  • 原文地址:https://www.cnblogs.com/hixin/p/7589135.html
Copyright © 2011-2022 走看看