zoukankan      html  css  js  c++  java
  • 多项式的相加

    多项式的相加

    一、案例分析

      假如说我们现在有下面两个多项式:

      ①A(x)=3x2+4x5+5x3-x1

      ②B(x)=4x3+7x2+3x1

      这两个多项式在计算机中用链表的来存储

    根据多项式相加的运算规则:对两个多项式中所有指数相同的项,对应系数想加,若其和不为零,则作为“和多项式”中的一项插入到“和多项式”链表中去;对于两个多项式中指数不相同的项,则将指数较小的项插入到“和多项式”链表中去。“多项式”链表中的节点无需生成,而应该从两个多项式的链表中摘取。

    二、案例实现

    (一)代码分析

    1.预处理部分

    #include <iostream>
    using namespace std;
    
    #define OK 1
    #define ERROR 0
    #define ElemType int
    
    int flag = 1;    //定义一个标志变量,来区分输出的F(x)

    2.结构体

    链表的每个节点都有三个,系数(data)、指数(index)和一个指针域(next)。

    typedef struct Polyn     //定义一个结构体,包括三个成员变量
    {
        ElemType data;        //系数
        ElemType index;       //指数
        struct Polyn *next;  //结构体指针
    }Polyn,*LinkList;

    3.输出链表

    输出链表是为了便于观察我们创建的链表,以及后面输出同类型和的链表。

      具体实现:①首先声明一个指针指向首元结点

           ②while,在p不为空的情况下按照多项式的形式输出节点,并按照系数的正负,分情况输出

    void Printf_Polyn(LinkList L)   //输出链表
    {
        Polyn *p = L->next;         //定义一个指向首节点的指针
        cout<<"F(x"<<flag<<")=";   //使输出美观
        while(p)                   //while循环遍历链表,逐个输出
        {
            if(p->data > 0)       //判断系数是否为正,若为正数则加上"+",负数的话,只需正常输出即可
            {
                cout<<"+"<<p->data<<"X^"<<p->index;
            }
            else cout<<p->data<<"X^"<<p->index;
            p=p->next;            //指针下移
        }
        cout<<endl;
    }

    4.对链表进行排序

    使用选择排序,对链表每个元素进行排序

      具体实现:①定义一个中间变量,便于后面的数据交换。

           ②排序时,首先取到第一个结点的指数,逐个与后面结点的指数比较,第二次用第二个结点的指数与后面结点指数比较,依次类推。

           ③如果前面的指数比后面的指数大,就交换,这样比下去即可实现排序

    void Sort_Polyn(LinkList &L)     //使用选择法对链表进行排序
    {   int temp_data,temp_index;    //定义一个中间变量,便于后面的数据交换
        Polyn *k,*r,*p = L->next;
        for(;p;p=p->next)            //从链表第一个节点开始,逐个与后面的节点比较
        {
            k = p;                   //k指向第一个节点的,比较完一轮之后,将会指向第二个节点,依次往后推
            for(r=p->next;r;r=r->next)   //从第二节点值开始与k所指节点值进行比较,比较完一轮之后,就是第三节点与k比较,依次类推
            {
                if(k->index > r->index)  //如果k指向的节点的值大,就交换系数和指数
                {
                    temp_index = r->index;
                    temp_data = r->data;
                    r->data = k->data;
                    r->index = k->index;
                    k->data = temp_data;
                    k->index = temp_index;
                }
            }
        }
        Printf_Polyn(L);               //输出链表
        flag++;
    }

    5.创建链表

    采用尾插法创建链表。

    具体实现参考我上篇博客:单链表的基本操作和实现https://www.cnblogs.com/953-zjf/p/LinkList.html

    void Creat_Polyn(LinkList &L)      //尾插法创建链表
    {
        int n;                         //项数n
        if(flag % 2)                   //为了使程序更直观而设立的标志变量
        {
            cout<<"现在输入第一个多项式"<<endl;
        }
        else cout<<"现在输入第二个多项式"<<endl;
        cout<<"请输入你要创建的项数:";
        cin>>n;                      //输入项数
        Polyn *p,*r;                 //一个新建节点的指针和一个尾指针
        L = new Polyn;               //初始化头节点
        L->next = NULL;
        r = L;
        cout<<"请输入系数和指数(系数和指数之间用空格隔开):";
        for(int j = 1;j <= n;j++)    //循环n次,每次新建一个节点
        {
            p = new Polyn;
            cin>>p->data>>p->index;  //输入新节点的系数和指数
            p->next = r->next;       //接尾
            r->next = p;             //接头
            r = p;                   //尾指针后移
        }
    }

    6.链表的合并

    基本的思想就是分别先定义两个指针分别指向两个链表,至于两个链表的和,可以新建一个链表来存放,也可以直接用两个链表的其中一个来存储。我这里用的La存储,那么也需要一个指针来指向它,就是r。做好这些我们就可以来进行比较了,La中每个结点与Lb的每个结点进行比较,会出现三种情况,第一种:La的大于Lb,就将La的结点接到r上,然后指La的指针下移。第二种,La的小于Lb,就将Lb的结点接到r上,然后Lb的指针下移。第三种:La等于Lb,那就将两个结点之和相加,这时候先判断两个之和是否为0,不为0,就将两者之和赋给La的结点,并将该结点接上,然后删除Lb的节点。如果两者之和为0.则将两个节点都删除。

    void Addit_Polyn(LinkList L1,LinkList L2)  //将两个链表相加的函数
    {
        Polyn *p1,*p2,*r,*s;           //定义四个结构体指针
        p1 = L1->next;                 //p1指向第一个链表
        p2 = L2->next;                 //p2指向第二个链表
        r = L1;                        //r指向p1,p1指得链条接下来也将成为和的链表的
        while(p1 != NULL&&p2 != NULL) //当p1、p2不指向空时,循环继续
        {
            if(p1->index < p2->index) //判断——如果p1的指数小于p2的指数,就将p1插到L1所指的链表
            {
                r->next = p1;
                r = p1;
                p1 = p1->next;       //指针p1下移
            }
            else if(p1->index > p2->index)//判断——如果p1的指数大于p2的指数,就将p2插到L1所指的链表
            {
                r->next = p2;
                r = p2;
                p2  = p2->next;     //指针p2下移
            }
            else if(p1->index == p2->index)       //判断——如果p1的指数等于p2的指数
            {
                if(p1->data + p2->data)//就先判断系数之和是否为0,如果不是0
                {
                    p1->data = p1->data+p2->data;   //将p1、p2系数之和赋值给p1
                    r->next = p1;                   //p1接入L1
                    r = p1;                        //r后移
                    p1 = p1->next;                 //p1后移
                    s = p2;                        //记录p2,记录之后,后面可以释放该节点
                    p2 = p2->next;                 //记录之后,p2下移
                    delete s;                      //释放上一节点
                }
                else                               //如果p1、p2系数之和为0
                {
                    s = p1;             //先分别用s记录p1、p2,p1、p2下移,再分别释放s,即删除了前面p1和p2相等的两个节点
                    p1 = p1->next;
                    delete s;
                    s = p2;
                    p2 = p2->next;
                    delete s;
                }
            }
            r->next = NULL;      //结束循环时,先让链表和的链表的尾部指向空
        }
        if(p1 != NULL)           //判断剩余的p1是否为空
        {
            r->next = p1;        //如果剩余的p1不是空,就接到L1的后边
        }
        else if(p2!=NULL)       //判断剩余的p2是否为空
        {
            r->next = p2;       //如果剩余的p1不是空,就接到L1的后边
        }
        Printf_Polyn(L1);       //输出链表
    }

    7.主程序

    首先新建两个链表头指针,然后只需分别调用上面的函数即可

    int main()
    {
        LinkList La,Lb;        //定义两个链表指针
        Creat_Polyn(La);       //创建链表La
        Sort_Polyn(La);         //链表La排序
        Merge_Polyn(La);
        Creat_Polyn(Lb);       //创建链表Lb
        Sort_Polyn(Lb);
        Merge_Polyn(Lb);        //链表Lb排序
        cout<<"合并之后的多项式为:";
        Addit_Polyn(La,Lb);    //将两个链表相加
        return 0;
    }

    8.完整代码

    #include <iostream>
    using namespace std;
    
    #define OK 1
    #define ERROR 0
    #define ElemType int
    
    int flag = 1;             //定义一个标志变量,来区分输出的F(x)
    typedef struct Polyn     //定义一个结构体,包括三个成员变量
    {
        ElemType data;        //系数
        ElemType index;       //指数
        struct Polyn *next;  //结构体指针
    }Polyn,*LinkList;
    
    
    void Printf_Polyn(LinkList L)   //输出链表
    {
        Polyn *p = L->next;         //定义一个指向首节点的指针
        cout<<"F(x"<<flag<<")=";   //使输出美观
        while(p)                   //while循环遍历链表,逐个输出
        {
            if(p->data > 0)       //判断系数是否为正,若为正数则加上"+",负数的话,只需正常输出即可
            {
                cout<<"+"<<p->data<<"X^"<<p->index;
            }
            else cout<<p->data<<"X^"<<p->index;
            p=p->next;            //指针下移
        }
        cout<<endl;
    }
    
    void Sort_Polyn(LinkList &L)     //使用选择法对链表进行排序
    {   int temp_data,temp_index;    //定义一个中间变量,便于后面的数据交换
        Polyn *k,*r,*p = L->next;
        for(;p;p=p->next)            //从链表第一个节点开始,逐个与后面的节点比较
        {
            k = p;                   //k指向第一个节点的,比较完一轮之后,将会指向第二个节点,依次往后推
            for(r=p->next;r;r=r->next)   //从第二节点值开始与k所指节点值进行比较,比较完一轮之后,就是第三节点与k比较,依次类推
            {
                if(k->index > r->index)  //如果k指向的节点的值大,就交换系数和指数
                {
                    temp_index = r->index;
                    temp_data = r->data;
                    r->data = k->data;
                    r->index = k->index;
                    k->data = temp_data;
                    k->index = temp_index;
                }
            }
        }
        Printf_Polyn(L);               //输出链表
        flag++;
    }
    void Creat_Polyn(LinkList &L)      //尾插法创建链表
    {
        int n;                         //项数n
        if(flag % 2)                   //为了使程序更直观而设立的标志变量
        {
            cout<<"现在输入第一个多项式"<<endl;
        }
        else cout<<"现在输入第二个多项式"<<endl;
        cout<<"请输入你要创建的项数:";
        cin>>n;                      //输入项数
        Polyn *p,*r;                 //一个新建节点的指针和一个尾指针
        L = new Polyn;               //初始化头节点
        L->next = NULL;
        r = L;
        cout<<"请输入系数和指数(系数和指数之间用空格隔开):";
        for(int j = 1;j <= n;j++)    //循环n次,每次新建一个节点
        {
            p = new Polyn;
            cin>>p->data>>p->index;  //输入新节点的系数和指数
            p->next = r->next;       //接尾
            r->next = p;             //接头
            r = p;                   //尾指针后移
        }
    }
    
    void Addit_Polyn(LinkList L1,LinkList L2)  //将两个链表相加的函数
    {
        Polyn *p1,*p2,*r,*s;           //定义四个结构体指针
        p1 = L1->next;                 //p1指向第一个链表
        p2 = L2->next;                 //p2指向第二个链表
        r = L1;                        //r指向p1,p1指得链条接下来也将成为和的链表的
        while(p1 != NULL&&p2 != NULL) //当p1、p2不指向空时,循环继续
        {
            if(p1->index < p2->index) //判断——如果p1的指数小于p2的指数,就将p1插到L1所指的链表
            {
                r->next = p1;
                r = p1;
                p1 = p1->next;       //指针p1下移
            }
            else if(p1->index > p2->index)//判断——如果p1的指数大于p2的指数,就将p2插到L1所指的链表
            {
                r->next = p2;
                r = p2;
                p2  = p2->next;     //指针p2下移
            }
            else if(p1->index == p2->index)       //判断——如果p1的指数等于p2的指数
            {
                if(p1->data + p2->data)//就先判断系数之和是否为0,如果不是0
                {
                    p1->data = p1->data+p2->data;   //将p1、p2系数之和赋值给p1
                    r->next = p1;                   //p1接入L1
                    r = p1;                        //r后移
                    p1 = p1->next;                 //p1后移
                    s = p2;                        //记录p2,记录之后,后面可以释放该节点
                    p2 = p2->next;                 //记录之后,p2下移
                    delete s;                      //释放上一节点
                }
                else                               //如果p1、p2系数之和为0
                {
                    s = p1;             //先分别用s记录p1、p2,p1、p2下移,再分别释放s,即删除了前面p1和p2相等的两个节点
                    p1 = p1->next;
                    delete s;
                    s = p2;
                    p2 = p2->next;
                    delete s;
                }
            }
            r->next = NULL;      //结束循环时,先让链表和的链表的尾部指向空
        }
        if(p1 != NULL)           //判断剩余的p1是否为空
        {
            r->next = p1;        //如果剩余的p1不是空,就接到L1的后边
        }
        else if(p2!=NULL)       //判断剩余的p2是否为空
        {
            r->next = p2;       //如果剩余的p1不是空,就接到L1的后边
        }
        Printf_Polyn(L1);       //输出链表
    }
    int main()
    {
        LinkList La,Lb;        //定义两个链表指针
        Creat_Polyn(La);       //创建链表La
        Sort_Polyn(La);         //链表La排序
        Merge_Polyn(La);
        Creat_Polyn(Lb);       //创建链表Lb
        Sort_Polyn(Lb);
        Merge_Polyn(Lb);        //链表Lb排序
        cout<<"合并之后的多项式为:";
        Addit_Polyn(La,Lb);    //将两个链表相加
        return 0;
    }

    三、运行结果

    如有什么不对的地方,欢迎大家指正!

  • 相关阅读:
    [AHOI2006]文本编辑器 Splay tree区间操作
    HDU-3487 Play with Chain Splay tee区间反转,移动
    HDU-4619 Warm up 2 二分匹配
    HDU-4618 Palindrome Sub-Array 暴力枚举
    HDU-4616 Game 树形DP
    HDU-4614 Vases and Flowers 线段树区间更新
    HDU-4612 Warm up 边双连通分量+缩点+最长链
    HDU-4611 Balls Rearrangement 循环节,模拟
    HDU-4605 Magic Ball Game 树状数组+离散+dfs
    HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动
  • 原文地址:https://www.cnblogs.com/953-zjf/p/13860821.html
Copyright © 2011-2022 走看看