YAZONG 我的开源

(数据结构)第二讲-线性结构(2.4应用实例:多项式)

  , ,
0 评论0 浏览

多项式求解思路

image.png

image.png

image.png

image.png

这里的每一项对应单向链表的一个结点,这个结点包含三个变量:系数、指数、指针(指向下一项),按照指数递降的顺序串在一起。

如果是加法运算,那么找到指数相等的,系数相加。

如果是乘法运算,那么每一项相乘,系数相乘,指数相加。

image.png

image.png

多项式的关键信息:非零项的系数和指数,这种线性队列有两种在计算机上面存储实现方式:第一种是数组,另一种是链表,链表克服了数组需要事先确定数组大小的特点。

image.png

/*
多项式的链表数据结构表示
*/
struct PolyNode{
	//系数
	int coefficient;
	//指数
	int exponent;
	//指向下一个结点的指针
	struct PolyNode *link;
};
typedef struct PolyNode *Polynomial;
Polynomial P1,P2;

多项式程序框架搭建

步骤:

读入多项式1、

读入多项式2、

乘法运算并输出、

加法运算并输出。

#include<stdio.h>
/*
多项式的程序框架搭建
*/
int main(void){
	/*
	链表
	*/
	Polynomial P1, P2, PP, PS;
	/*
	读入多项式
	*/
	P1 = ReadPoly();
	P2 = ReadPoly();
	/*
	多项式相乘
	PP为指针
	*/
	PP = Mult(P1,P2);
	/*
	多项式输出
	*/
	PrintPoly(PP);
	/*
	多项式相加
	PS为指针
	*/
	PS = Add(P1,P2);
	/*
	多项式输出
	*/
	PrintPoly(PS);

	return 0;
}

读入多项式

/*
如何读入多项式
*/
Polynomical ReadOnly(){
	......
	scanf("%d",&N);
	......
	while(N--){
		scanf("%d %d", &c, &e);
		Attach(c,e,&Rear);
	}
	......
	return P;
}

image.png

此串数字,第一项4代表一共多少项,接下来是一对对的系数指数,所指向的这个链表。

那么这里的关键问题是,读的时候从左到右,从高指数向低指数读取,然后插入到上述的链表中。

在链表中,按照指数递降排序,在插入数据时候,要插入到链表的最后方,那么如果要读入一个新的结点能插入到最后一项的后面,需要一个pRear指针指向当前结果多项式的最后一项,通过函数Attach来完成,最后pRear要指到新的结点。

关于pRear的初值是多少?两种处理方法:

第一种:pRear初值为NULL,在Attach函数中根据pRear是否为NULL做不同处理。

image.png

第二种:pRear指向一个空结点,到最后,必须把这个空结点删除。

image.png

/*
如何读入多项式
*/
Polynomical ReadOnly(){
	Polynomical P, Rear, t;
	int c,e,N;
	scanf("%d",&N);
	/*
	链表头空结点
	*/
	P = (Polynomical)malloc(sizeof(struct PolyNode));
	P->link = NULL;
	Rear = P;
	while(N--){
		scanf("%d %d", &c, &e);
		/*
		将当前项插入多项式尾部
		*/
		Attach(c,e,&Rear);
	}
	t = P;
	//P指向下一个结点
	P = P->link;
	/*
	删除临时生成的头结点
	*/
	free(t);
	return P;
}

image.png

/*
如何读入多项式
c系数
e指数
Polynomial *pRear	最后一个结点的指针位置(*pRear指针的指针.C语言是函数常数值传递.)
*/
void Attach(int c, int e,Polynomial *pRear){
	/*
	由于在本函数中需要改变当前结果表达式尾项指针的值,
	所以函数传递进来的是结点指针的地址,*pRear指向尾项。
	*/
	Polynomial P;
	/*
	申请新结点
	*/
	P = (Polynomial)malloc(sizeof(struct PolyNode));
	/*
	对新结点赋值
	*/
	P->coefficient = c;
	P->exponent = e;
	P->link = NULL;

	/*
	最后两个语句:
	将(新申请的结点)P指向的新结点插入到当前结果表达式尾项rear的后面。
	要注意*pRear是指针。
	*/
	(*pRear)->link = P;
	/*
	修改pRear的值
	最后一个结点的指针位置就是新结点P的位置
	*/
	*pRear = P;
}

两多项式相加

image.png

image.png

/*
多项式的加法运算
*/
struct PolyNode{
	//系数
	int coefficient;
	//指数
	int exponent;
	//指向下一个结点的指针
	struct PolyNode *link;
};
typedef struct PolyNode *Polynomial;
Polynomial P1,P2;

image.png

这里的每一项对应单向链表的一个结点,这个结点包含三个变量:系数、指数、指针(指向下一项),按照指数递降的顺序串在一起,找到指数相等的,系数相加。

image.png

image.png

P1和P2中某两项的指数相同,则二者做加减,指数不同,那么P1或P2直接存入结果多项式,P1或P2指向下一项,如果P2空了,那么就把P1后面的所有项都接到结果多项式的后面。

/*
多项式的加法运算实现
对于多项式来讲,要知道多项式的头结点与尾结点的位置。
*/
Polynomial PolyAdd(Polynomial P1, Polynomial P2){

	Polynomial front, rear, temp;
	int sum;
	/*
	为方便表头插入,先产生一个临时空结点作为结果多项式链表头
	*/
	rear = (Polynomial)malloc(sizeof(struct PolyNode));
	/*
	由front记录结果多项式链表头结点
	*/
	front = rear;
	/*
	当两个多项式都有非零项待处理时(二者都不为空)
	*/
	while(P1 && P2){
		/*
		比较两个指数的大小
		*/
		switch(Compare(P1->exponent,P2->exponent)){
			/*
			P1中的数据项指数较大
			*/
			case 1:
				Attach(P1->coefficient,P1->exponent,&rear);
				P1 = P1->link;
				break;
			/*
			P2中的数据项指数较大
			*/
			case -1:
				Attach(P2->coefficient,P2->exponent,&rear);
				P2 = P2->link;
				break;
			/*
			P1和P2中的数据项指数较大相等
			*/
			case 0:
				//系数相加
				sum = P1->coefficient + P2->coefficient;
				//不等于0就把结果加到多项式中去
				if(sum){
					Attach(sum, P1->exponent, &rear);
				}
				P1 = P1->link;
				P2 = P2->link;
				break;
		}
	}
	/*
	将未处理完的另一个多项式的所有结点依次复制到结果多项式中去
	这俩FOR循环做完,就意味着两个相加基本完成了。
	有一个是空的,就要把另外一个后面剩余的项全部接到多项式的后面。
	*/
	/*
	第一个for循环:处理P1不空,如果P1不空,那么P2肯定空了。
	P1不空,就是把P1后面的每一项全部attach,同时P1往后挪。
	*/
	for(;P1;P1 = P1->link){
		Attach(P1->coefficient, P1->exponent, &rear);
	}
	/*
	第二个for循环:处理P2不空,如果P2不空,那么P1肯定空了。
	P2不空,就是把P2后面的每一项全部attach,同时P2往后挪。
	*/
	for(;P2;P2 = p2->link){
		Attach(P2->coefficient, P2->exponent, &rear);
	}
	/*
	做函数返回之前的扫尾工作
	rear指向结果多项式的最后一项,现在加完了,那么最后一项就没了,那么释放掉NULL空结点。
	*/
	rear->link = NULL;
	temp = front;
	/*
	将front指向结果多项式第一个非零项。
	front往后挪,front原来是指向这个临时结点的表头结点,
	这个表头结点的下一项就是真正的多项式的第一项。
	*/
	front = front->link;
	/*
	释放临时空表头结点
	*/
	free(temp);
	/*
	return的是这个结果多项式/单向链表的第一个结点
	*/
	return front;
}

两多项式相乘

image.png

/*
多项式相乘模板
*/
Polynomial Mult(Polynomial P1,Polynomial P2){
	......
	t1 = P1;
	t2 = P2;
	......
	/*
	先用P1的第一项乘以P2,得到P2。
	*/
	while(t2){
		......
	}
	t1 = t1->link;
	while(t1){
		t2 = P2;
		Rear = P;
		while(t2){
			e = t1->expon + t2->expon;
			c = t1->coef * t2->coef;
			......
			t2 = t2->link;
		}
		t1 = t1->link;
	}
	......

}

image.png

/*
多项式相乘案例
*/
Polynomial Mult(Polynomial P1,Polynomial P2){

	Polynomial P,t1,t2,t;
	int c,e;

	if(!P1 || !P2){
		return NULL;
	}
	t1 = P1;
	t2 = P2;
	P = (Polynomial)malloc(sizeof(struct PolyNode));
	P->link = NULL;
	Rear = P;

	while(t2){
		/*
		先用P1的第一项乘以P2,得到P.
		*/
		Attach(t1->coefficient * t2->coefficient, t1->exponent + t2.exponent, &Rear);
		t2 = t2->link;
	}
	t1 = t1->link;
	/*
	如何插入某结点
	*/
	while(t1){
		t2 = P2;
		Rear = P;
		while(t2){
			e = t1->exponent + t2->exponent;
			c = t1->coefficient * t2->coefficient;
			while(Rear->link && Rear->link->exponent > e){
				Rear = Rear->link;
			}
			/*
			指向要插入的结点的后面
			*/
			if(Rear->link && Rear->link->exponent == e){
				if(Rear->link->coefficient + c){
					Rear->link->coefficient += c;
				}else{
					t = Rear->link;
					Rear->link = t->link;
					free(t);
				}
			}else{
				t = (Polynomial)malloc(sizeof(struct PolyNode));
				t->coefficient = c;
				t->exponent = e;
				t->link = Rear->link;
				Rear->link = t;
				Rear = Rear->link;
			}
		}
		t1 = t1->link;
	}
	/*
	释放临时结点并重新指针指向
	*/
	t2 = P;
	P = P->link;
	free(t2);

	return P;

}

多项式输出

/*
多项式输出模板
*/
void PrintPoly(Polynomial P){
	/*
	输出多项式
	*/
	......
	while(P){
		......
		P = P->link;
	}
	......
}
/*
多项式输出案例
无论相加还是相乘,都有一个指针指向这个多项式的第一个结点。
这实际上是一个链表的遍历问题。
输出案例:
5 20空格-4 4空格-5 2空格9 1空格-2 0
系数指数空格
如何控制这么一个过程?
那么可以倒过来理解,可以把其理解成每一项都是空格系数指数,第一项没有空格除外(flag=1标识)。
*/
void PrintPoly(Polynomial P){
	/*
	输出多项式
	*/
	int flag = 0;//辅助调整输出格式使用
	if(!P){
		print("0 0\n");
		return;
	}
	while(P){
		if(!flag){
			flag = 1;
		}else{
			print(" ");
		}
		printf("%d %d",P->coefficient,P->exponent);
		P = P->link;
	}
	print("\n");
}

小总结

image.png


标题:(数据结构)第二讲-线性结构(2.4应用实例:多项式)
作者:yazong
地址:https://blog.llyweb.com/articles/2023/08/15/1692031833181.html