多项式的相加
一、案例分析
假如说我们现在有下面两个多项式:
①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; }
三、运行结果
如有什么不对的地方,欢迎大家指正!