数据结构3————链表的应用2[一元多项式]

数据结构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头结点的空间)
  • 代码思路
    1. 比较La和Lb,如果哪个小,将哪个连接在Lc后面,Lc和这个指针后移
    2. 如果两个大小相同,则系数相加后,连接在Lc后面,La和Lb都后移
    3. 重复1,2知道La或者Lb移动到链表尾部
    4. 将未遍历完的链表连接在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 //我的方法
    1. La表示被减数,Lb表示减数,Lc表示差
    2. 比较La和Lb,如果La小,将哪个连接在Lc后面,Lc和La指针后移
    3. 如果Lb小,将Lb系数变为原来的相反数,连接在Lc后面,Lc和Lb指针后移
    4. 如果两个大小相同,则系数相减后,连接在Lc后面,Lc.La和Lb都后移
    5. 重复2,3,4知道La或者Lb移动到链表尾部
    6. 将未遍历完的链表连接在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;
	}
}

九. 源码

百度云源码 包括a-c的约瑟夫环实验题
git源码 文件夹test1中

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值