数据结构3————链表的应用2[一元多项式]
一.前言
这次博客主要是使用链表进行多项式的运算,包括
- 多项式的建立输出
- 多项式的加法
- 多项式的减法
- 多项式的乘法
- 多项式的求值
- 多项式的求导
二.说明
我是在学校的acm系统上做的题,由于acm上面的一些问题,接受数据时,第一个节点接受的是垃圾数据,所以我多建立了一个节点,当链表建立完成后,将第一个节点删除。
for(i=0;i<iCound+1;i++){//多建立一个节点
。。。。。
}
pHead=pHead->next;//将第一个节点删除
return pHead;
如果是其他系统上,或者自己测试,可改为
for(i=0;i<iCound;i++){
。。。。。
}
//pHead=pHead->next;//将第一个节点删除
return pHead;
三.多项式的建立和输出
1.题意要求
2.加载头文件和设置结构体
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int coef;//系数
int expn;//指数
struct node *next;
}LNode,*LinkList;
3.多项式的建立
- 多项式的建立和普通的链表建立相差无几,只是填充数据域时要从键盘接受
- 链表的建立:申请空间,填充数据,链接到尾部,尾指针移动
4.代码
LinkList CreatePoly(int iCound){
LinkList pHead;
LNode *pNew,*pEnd;
int i;
char a;
pEnd=pHead = (LinkList)malloc(sizeof(LinkList));
pHead->next=NULL;
fflush(stdin);
for(i=0;i<iCound+1;i++){
pNew = (LinkList)malloc(sizeof(LinkList)) ;//申请空间
scanf("%c%d%c%d%c)",&a,&pNew->coef,&a,&pNew->expn,&a);//填充数据
pEnd->next = pNew;//链接到尾部
pEnd = pNew;//尾指针移动
}
pNew->next =NULL;
pHead=pHead->next;
return pHead;
}
5.链表的输出
- 这大概是多项式所以运算里最麻烦的,需要考虑的细节太多,所以最繁琐。
- 需要考虑的情况
- 是否是第一位(前面是否要放+)
- 系数是否为负(前面的符号的正负)
- 指数是否为0(是否出现X)
- 指数是否为1(是否打印指数)
- 系数是否为0(是否打印该节点)
- 是否全部节点都为0(是否最终只打印0)//减法时会出现
- 指数是否为1/-1(是否打印系数)//这种情况学校acm没有要求,我就没有写
6.代码
void PrintPolyn(LinkList pHead){
LNode *pt;
int i;
while(pHead->next->next&&pHead->next->coef==0){
pHead=pHead->next;
}
if(pHead->next->next==NULL&&pHead->next->coef==0){
printf("0");
return;
}
pt=pHead->next;
while(pt){
if(pt==pHead->next){ //是否为第一项
if(pt->expn==0){ //指数是否为0
printf("%d",pt->coef);
}else if(pt->expn==1){//指数是否为1
printf("%dX",pt->coef);
}else{ //正常情况
printf("%dX^%d",pt->coef,pt->expn);
}
}
else{
if(pt->coef==0){//系数是否为0
}else if(pt->expn==0){//指数是否为0
printf("+%d",pt->coef);
}else if(pt->expn==1){//指数是否为1
if(pt->coef<0){//系数是否为负
printf("%dX",pt->coef);
}else{
printf("+%dX",pt->coef);
}
}else if(pt->coef<0){//系数是否为负
printf("%dX^%d",pt->coef,pt->expn);
}else{//正常情况
printf("+%dX^%d",pt->coef,pt->expn);
}
}
pt=pt->next;
}
printf("\n");
}
四.多项式的加法
1.题意要求
2.思路
- 类似于两个非递减的链表合并成一个链表
- 非递减链表的合并可以看我之前的博客
- La,Lb指向两个加数的链表,Lc指向加完之后的表示和的链表,cHead指向和头结点(利用原La头结点的空间)
- 代码思路
- 比较La和Lb,如果哪个小,将哪个连接在Lc后面,Lc和这个指针后移
- 如果两个大小相同,则系数相加后,连接在Lc后面,La和Lb都后移
- 重复1,2知道La或者Lb移动到链表尾部
- 将未遍历完的链表连接在Lc后
3.代码
int add(LinkList aHead, LinkList bHead){
LinkList cHead=aHead;
LNode *La=aHead->next;
LNode *Lb=bHead->next;
LNode *Lc=cHead;
while(La&&Lb){ //3. 重复1,2知道La或者Lb移动到链表尾部
if((La->expn)<(Lb->expn)){ //1. 比较La和Lb,如果哪个小,将哪个连接在Lc后面,Lc和这个指针后移
Lc->next=La;
Lc=La;
La=La->next;
}else if((La->expn)==(Lb->expn)){//2.如果两个大小相同,则系数相加后,连接在Lc后面,La和Lb都后移
La->coef = La->coef + Lb->coef;
Lc->next =La;
Lc=La;
La=La->next;
Lb=Lb->next;
}
else{
Lc->next=Lb;
Lc=Lb;
Lb=Lb->next;
}
}
if(La) //4.将未遍历完的链表连接在Lc后
Lc->next=La;
else
Lc->next=Lb;
}
五.多项式的减法
1.题意要求
2.思路
- 类似于加法
- 代码思路1
- 将代表减数的链表遍历一遍,系数等于原来的相反数
- 调用加法函数
- 代码思路2 //我的方法
- La表示被减数,Lb表示减数,Lc表示差
- 比较La和Lb,如果La小,将哪个连接在Lc后面,Lc和La指针后移
- 如果Lb小,将Lb系数变为原来的相反数,连接在Lc后面,Lc和Lb指针后移
- 如果两个大小相同,则系数相减后,连接在Lc后面,Lc.La和Lb都后移
- 重复2,3,4知道La或者Lb移动到链表尾部
- 将未遍历完的链表连接在Lc后(如果是La,直接连接,如果是Lb,系数全部变反)
3.代码
int minus(LinkList aHead, LinkList bHead){
LinkList cHead=aHead;
LNode *La=aHead->next;
LNode *Lb=bHead->next;
LNode *Lc=cHead;
while(La&&Lb){
if((La->expn)<(Lb->expn)){ //比较La和Lb,如果La小,将哪个连接在Lc后面,Lc和La指针后移
Lc->next=La;
Lc=La;
La=La->next;
}else if((La->expn)==(Lb->expn)){ //如果两个大小相同,则系数相减后,连接在Lc后面,Lc.La和Lb都后移
La->coef = La->coef - Lb->coef;
Lc->next =La;
Lc=La;
La=La->next;
Lb=Lb->next;
}
else{ //如果Lb小,将Lb系数变为原来的相反数,连接在Lc后面,Lc和Lb指针后移
Lb->coef = -Lb->coef;
Lc->next=Lb;
Lc=Lb;
Lb=Lb->next;
}
}
if(La) //将未遍历完的链表连接在Lc后(如果是La,直接连接,如果是Lb,系数全部变反
Lc->next=La;
else{
Lc->next=Lb;
while(Lb){
Lb->coef = -Lb->coef;
Lb=Lb->next;
}
}
}
六.多项式的乘法
1.题意要求
2.思路
- La每一项和Lb的每一项相乘(两重循环,系数相差,指数相加)
- 结果链表进行排序(插入排序)
- 结果链表合并形同指数的系数
3.代码
相乘
LinkList time(LinkList aHead, LinkList bHead){ //相乘
LinkList cHead;
LNode *La=aHead->next;
LNode *Lb=bHead->next;
LNode *cNew,*cEnd;
cEnd=cHead=(LinkList)malloc(sizeof(LinkList));
for(La=aHead->next;La;La=La->next){ // La每一项和Lb的每一项相乘(两重循环,系数相差,指数相加)
for(Lb=bHead->next;Lb;Lb=Lb->next){
cNew=(LinkList)malloc(sizeof(LinkList));
cNew->coef=La->coef*Lb->coef;
cNew->expn=La->expn+Lb->expn;
cEnd->next=cNew;
cEnd=cNew;
}
}
cEnd->next=NULL;
sore(cHead);
f1(cHead);
return cHead;
}
排序
void sore(struct node *pHead) //排序
{
struct node *pt,*pt_h,*pi;
pt=pHead->next;
pt_h=pt->next;
pHead->next=NULL;
while(pt){
for(pi=pHead;pi->next&&pi->next->expn<pt->expn;pi=pi->next);
pt_h=pt->next;
pt->next=pi->next;
pi->next=pt;
pt=pt_h;
}
}
合并
void f1(LinkList pHead){ //合并
LNode *ptt;
LNode *pt=pHead->next;
while(pt->next){
ptt=pt;
pt=pt->next;
if(ptt->expn==pt->expn){
ptt->coef=ptt->coef+pt->coef;
ptt->next=pt->next;
}
}
}
七.多项式的求值
1.题意要求
2.思路
- 可以说是多项式运算中最简单的一个
- 将X带入每一个节点里,累加
- 然后计算每一个节点的具体值,累乘
3.代码
int f1(int n ,int x){// 然后计算每一个节点的具体值,累乘
int sum=1;
int i;
for(i=0;i<x;i++)
sum=sum*n;
return sum;
}
int count(int x,LinkList pHead){
int sum=0;
LNode *pt=pHead->next;
while(pt){
sum+=pt->coef*f1(x,pt->expn);//将X带入每一个节点里,累加
pt=pt->next;
}
return sum;
}
八.多项式的求导
1.题意要求
2.思路
- 遍历链表,系数等于原系数*原指数,指数等于原指数-1
3.代码
int f1(LinkList pHead){
LinkList pt=pHead->next;
while(pt){
if(pt->expn==0){
pt->coef=0;
}else{
pt->coef=pt->expn * pt->coef;
pt->expn=pt->expn-1;
}
pt=pt->next;
}
}