多项式相加求和(C语言链表版)

C语言链表学的差不多了吗?

学的差不多那我们来试试如何用链表做一个多项式相加的程序。


1.  我们知道多项式是由系数(coef)和指数(expon)构成的,那么我们在用链表建立的时候,就得考虑我们的链表结点需要同时包括三部分的内容,一部分是项的系数,一部分是项的指数,最后不要忘记我们链表结点的指针域。这三部分缺一不可。

struct PolyNode
{
	int coef;
	int expon;
	struct PolyNode* Link;
};//结构体构建多项式项的架构

2.  基础工作做完后,我们可以试图建立每一个多项式所对应的链表结构,这就和我们构建链表是一样的,较之前无非就是多了一个数据而已。

struct PolyNode* Init_Polynomial1()  //初始化第一个多项式
{
	struct PolyNode* header = malloc(sizeof(struct PolyNode)); //建立头节点
	struct PolyNode* pRear = header;                       //建立尾结点,令尾结点指向头节点
	header->coef = 0;                                          //头节点赋初值
	header->expon = 0;
	header->Link = NULL;
	int coef = 0;                 //设置两个变量,用来存放输入的系数(coef)和指数(expon)
	int expon = 0;
	while (1)                    //循环输入
	{
		scanf_s("%d", &coef);     
		if (coef == 0)           //设置一个终止输入的标志,这里我选的是0
		{ 
			break;               //当输入为0的时候,跳出循环,结束结点建立
		}
		scanf_s("%d", &expon);    
		struct PolyNode* NewNode = malloc(sizeof(struct PolyNode));  //建立一个新的结点
		NewNode->coef = coef;    //将输入的系数和指数存放在新的结点中
		NewNode->expon = expon;
		NewNode->Link = NULL;         //下面将新的结点插入链表中
		pRear->Link = NewNode;    //尾结点指向新节点
		pRear = NewNode;          //更新尾部结点
	}
	return header;                //返回头节点
}

 好了,我们第一个多项式的各项都保存完毕,形成了一个链表,下面我们进行第二个多项式链表的构建,和第一个一样,这里就不再过多解释了,直接Copy上面的代码。

struct PolyNode* Init_Polynomial2()  //初始化第二个多项式
{
	struct PolyNode* header = malloc(sizeof(struct PolyNode));
	struct PolyNode* pRear = header;
	header->coef = 0;
	header->expon = 0;
	header->Link = NULL;
	int coef = 0;
	int expon = 0;
	while (1)
	{
		scanf_s("%d", &coef);
		if (coef == 0)
		{
			break;
		}
		scanf_s("%d", &expon);
		struct PolyNode* NewNode = malloc(sizeof(struct PolyNode));
		NewNode->coef = coef;
		NewNode->expon = expon;
		NewNode->Link = NULL;
		pRear->Link = NewNode;
		pRear = NewNode;
	}
	return header;
}

 3.  完成前两步以后,我们进入多项式相加。关于多项式相加,大家都很熟悉,就是指数相同的项的系数相加减。如果指数不相同,那么我们直接把系数和指数抄到结果中去,这些对于我们来说看似很简单,小学的内容而已,但是对于计算机,它并不能和我们一样。这时候我们就得想办法,让计算机明白这个计算的过程步骤。

struct PolyNode* Add_Polynomial(struct PolyNode* P1, struct PolyNode* P2)
{
	int sum = 0, e = 0;  //设置两个变量
	struct PolyNode* Front = malloc(sizeof(struct PolyNode));  //建立结果多项式的头节点
	struct PolyNode* Rear = Front;      //建立结果多项式的尾结点令其等于头节点
	Front->coef = 0;                     //头节点赋初值
	Front->expon = 0;
	Front->Link = NULL;
	while (P1 && P2)                    //对于传入的P1和P2若其中任一个不为NULL则进入循环
	{
		struct PolyNode* NewNode = malloc(sizeof(struct PolyNode)); 
                                        //建立存放结果多项式的各项的新节点
		e = Compare_Expon(P1->expon, P2->expon);    //比较P1和P2的指数
		switch (e)           
		{
		case 1:
			NewNode->coef = P1->coef;             
            //如果P1的系数大于P2的系数,那么直接将P1摘录到结果多项式中,然后将P1向后移动
			NewNode->expon = P1->expon;
			NewNode->Link = NULL;
			Rear->Link = NewNode;
			Rear = NewNode;                        //将新节点插入结果多项式的结点中去
			P1 = P1->Link;
			break;
		case 0:
			sum = P1->coef + P2->coef;
            //如果P1和P2的指数相同,这时候我们需要将两个系数相加。
			NewNode->coef = sum;                       //前面定义的sum就派上用场了
			NewNode->expon = P1->expon;        
			NewNode->Link = NULL; 
			Rear->Link = NewNode;                     //将新节点插入结果多项式
			Rear = NewNode; 
			P1 = P1->Link;
			P2 = P2->Link;
			break;
		case -1:                                        
			NewNode->coef = P2->coef;                    //如果P1的指数小于P2
            //将P2此时所指向的结点直接摘录到结果多项式,然后将P2向后移动
			NewNode->expon = P2->expon;
			NewNode->Link = NULL;
			Rear->Link = NewNode;                 //将新节点插入结果多项式
			Rear = NewNode;
			P2 = P2->Link;
			break;
		}
		
	}
}

   代码看起来似乎很复杂,其实本质就是一个问题,判断P1和P2中的各项的指数是否相等,不相等又分为两种情况。这样一来,我们就可以对每一个多项式实现遍历相加。

 (注:代码演示中的“摘录”看似就是现实中的复制粘贴,但是对于链表来说,复制粘贴的摘录过程就是建立新的结点然后将新的结点插入到链表中的过程)

  4.  代码中还用了自定义的Compare_Expon函数,这里,把具体代码展示出来。

int Compare_Expon(int a, int b)
{
	if (a > b)
		return 1;
	if (a == b)
		return 0;
	if (a < b)
		return -1;
}

  这段很简单,就不再多说了,提一句,Compare_Expon是为了比较两个多项式中对应各项的指数的大小关系。


  好,做到这里,是不是就是结束了呢?

  没错,还没有结束,我们在做两个多项式相加的时候,似乎还少了很多情况,少了什么情况呢?我用代码演示一下,看大家能不能明白。

if (P1 != NULL)
	{
		struct PolyNode* NewNode1 = malloc(sizeof(struct PolyNode));
		NewNode1 = P1;
		Rear->Link = NewNode1;
		Rear = NewNode1;
		P1 = P1->Link;
	}

 5.前面提到的while(P1&&P2)如果P2为空那么就会跳过循环,但是此时我们的P1要是还有项数,那岂不是漏了第一个多项式的后面好几项?

  对,没错,因此,我们就需要在while后面判断一下,是不是P1或者P2真的没再有别的项了,只有当P1和P2同时都为NULL的时候,我们才能说多项式的各项都遍历完毕,然后得到最终结果多项式的链表。

  6.  同样的,给出下面这段代码判断P2是否都加完了

if (P2 != NULL)
	{
		struct PolyNode* NewNode2 = malloc(sizeof(struct PolyNode));
		NewNode2 = P2;
		Rear->Link = NewNode2;
		Rear = NewNode2;
		P2 = P2->Link;
	}

  如果顺利进行到这里,那么我们已经成功的建立了两个多项式相加的基本流程。这时候,我们不要忘记返回结果多项式的头节点(Front)。

7.  我们写出遍历多项式的函数Foreach_Polynomial

void Foreach_Polynomial(struct PolyNode* header)
{
	struct PolyNode* pCurrent = malloc(sizeof(struct PolyNode));
	pCurrent = header->Link;                             //建立一个临时结点
	while (pCurrent != NULL)
	{
		printf("%d %d ", pCurrent->coef, pCurrent->expon);  //输出pCurrent当前的系数和指数
		pCurrent = pCurrent->Link;                        //pCurrent后移
	}
}

8.完成后,我们建立主函数进行测试输出。

int main()
{
	printf("请输入第一个多项式的各项:"); 
	struct PolyNode* header1 = Init_Polynomial1();  //用header1接收第一个多项式返回的头节点
	printf("请输入第二个多项式的各项:");
	struct PolyNode* header2 = Init_Polynomial2();  //用header2接受第二个多项式返回的头节点
	printf("第一个多项式的各项为:");
	Foreach_Polynomial(header1);                    //遍历输出第一个多项式的各项
	printf("\n第二个多项式的各项为:");
	Foreach_Polynomial(header2);                    //遍历输出第二个多项式的各项
	struct PolyNode* a = header1->Link;             
	struct PolyNode* b = header2->Link;
	struct PolyNode* Front = Add_Polynomial(a, b);
	printf("\n两个多项式相加的结果为:");
	Foreach_Polynomial(Front);                     //遍历输出结果多项式的各项
	return 0;
}

对于主函数里做几点解释:

1.  因为我们对于每一个多项式都设置了头节点,并且头节点赋的初值为0,因此我们在做多项式相加的时候如果直接传入两个多项式的头节点,然后遍历输出结果多项式的各项,那么两个多项式的头节点也会默认被相加,这样就会出现结果多项式中头节点(Front)的后一项系数为0,指数也为0,因为不是我们手动输入的,因此也没有任何意义,所以我们在向Add_Polynomial函数传入参数时,只需要传入两个多项式头节点的后一项,即我们在头节点后面创建的新的结点那些项数。

2.在输入的时候一定要按照指数递降分别输入各项的系数和指数。


上面这些做完后,我们运行试一下。

输入1 6 2 5 3 4 4 3 5 2 6 1 0

        1 6 2 5 3 4 4 3 5 2 6 1 0

然后就实现了两个多项式的相加。

 我们再试试项的指数不同的情况:

 这样就实现了两个多项式相加,多个多项式相加其实理论上相近,用于拓展练习大家可以再试试多个多项式相加的C语言代码编写。


  提醒(易出错的地方):

在建立新的结点时,一定不要忘记新节点,头节点,尾结点的Link,让其等于空(NULL),然后再进行插入操作!否则就会出现下面这种情况。

   最后我把完整的代码放在下面(仅供参考),中间过程有部分冗余,但过程相对易于理解。

#include<stdio.h>
#include<stdlib.h>
struct PolyNode
{
	int coef;
	int expon;
	struct PolyNode* Link;
};//结构体构建多项式项的架构
struct PolyNode* Init_Polynomial1()  //初始化第一个多项式
{
	struct PolyNode* header = (struct PolyNode*)malloc(sizeof(struct PolyNode));
	struct PolyNode* pRear = header;
	header->coef = 0;
	header->expon = 0;
	header->Link = NULL;
	int coef = 0;
	int expon = 0;
	while (1)
	{
		scanf_s("%d", &coef);
		if (coef == 0)
		{
			break;
		}
		scanf_s("%d", &expon);
		struct PolyNode* NewNode = (struct PolyNode*)malloc(sizeof(struct PolyNode));
		NewNode->coef = coef;
		NewNode->expon = expon;
		NewNode->Link = NULL;
		pRear->Link = NewNode;
		pRear = NewNode;
	}
	return header;
}
struct PolyNode* Init_Polynomial2()  //初始化第二个多项式
{
	struct PolyNode* header =(struct PolyNode*) malloc(sizeof(struct PolyNode));
	struct PolyNode* pRear = header;
	header->coef = 0;
	header->expon = 0;
	header->Link = NULL;
	int coef = 0;
	int expon = 0;
	while (1)
	{
		scanf_s("%d", &coef);
		if (coef == 0)
		{
			break;
		}
		scanf_s("%d", &expon);
		struct PolyNode* NewNode =(struct PolyNode*) malloc(sizeof(struct PolyNode));
		NewNode->coef = coef;
		NewNode->expon = expon;
		NewNode->Link = NULL;
		pRear->Link = NewNode;
		pRear = NewNode;
	}
	return header;
}
void Foreach_Polynomial(struct PolyNode* header)
{
	struct PolyNode* pCurrent =(struct PolyNode*) malloc(sizeof(struct PolyNode));
	pCurrent = header->Link;
	while (pCurrent != NULL)
	{
		printf("%d %d ", pCurrent->coef, pCurrent->expon);
		pCurrent = pCurrent->Link;
	}
}
int Compare_Expon(int a, int b)
{
	if (a > b)
		return 1;
	if (a == b)
		return 0;
	if (a < b)
		return -1;

}
struct PolyNode* Add_Polynomial(struct PolyNode* P1, struct PolyNode* P2)
{
	int sum = 0, e = 0;
	struct PolyNode* Front =(struct PolyNode*) malloc(sizeof(struct PolyNode));
	struct PolyNode* Rear = Front;
	Front->coef = 0;
	Front->expon = 0;
	Front->Link = NULL;
	while (P1 && P2)
	{
		struct PolyNode* NewNode =(struct PolyNode*) malloc(sizeof(struct PolyNode));
		e = Compare_Expon(P1->expon, P2->expon);
		switch (e)
		{
		case 1:
			NewNode->coef = P1->coef;
			NewNode->expon = P1->expon;
			NewNode->Link = NULL;
			Rear->Link = NewNode;
			Rear = NewNode;
			P1 = P1->Link;
			break;
		case 0:
			sum = P1->coef + P2->coef;
			NewNode->coef = sum;
			NewNode->expon = P1->expon;
			NewNode->Link = NULL;
			Rear->Link = NewNode;
			Rear = NewNode;
			P1 = P1->Link;
			P2 = P2->Link;
			break;
		case -1:
			NewNode->coef = P2->coef;
			NewNode->expon = P2->expon;
			NewNode->Link = NULL;
			Rear->Link = NewNode;
			Rear = NewNode;
			P2 = P2->Link;
			break;
		}
		
	}
	if (P1 != NULL)
	{
		struct PolyNode* NewNode1 =(struct PolyNode*) malloc(sizeof(struct PolyNode));
		NewNode1 = P1;
		Rear->Link = NewNode1;
		Rear = NewNode1;
		P1 = P1->Link;

	}
	if (P2 != NULL)
	{
		struct PolyNode* NewNode2 = (struct PolyNode*)malloc(sizeof(struct PolyNode));
		NewNode2 = P2;
		Rear->Link = NewNode2;
		Rear = NewNode2;
		P2 = P2->Link;

	}
	return Front;
}
int main()
{
	printf("请输入第一个多项式的各项:");
	struct PolyNode* header1 = Init_Polynomial1();
	printf("请输入第二个多项式的各项:");
	struct PolyNode* header2 = Init_Polynomial2();
	printf("第一个多项式的各项为:");
	Foreach_Polynomial(header1);
	printf("\n第二个多项式的各项为:");
	Foreach_Polynomial(header2);
	struct PolyNode* a = header1->Link;
	struct PolyNode* b = header2->Link;
	struct PolyNode* Front = Add_Polynomial(a,b);
	printf("\n两个多项式相加的结果为:");
	Foreach_Polynomial(Front);
	return 0;
}


 另外,有的小伙伴们会遇到这个报错问题   :

  error: invalid conversion from 'void*' to 'PolyNode*'

  这是因为malloc默认返回的类型是void*,所以最完美的操作应该是对malloc加上强制转换,所以如果小伙伴们编译报错的提示这个问题的话,记得在创建空间时改成如下:

(ps:将void*类型转换为PolyNode*)

struct PolyNode* header = (struct PolyNode*)malloc(sizeof(struct PolyNode));

改正的代码也已经同步更新啦~

才疏学浅,难免有错误和不当之处,欢迎交流批评指正~

   那么爱学习的你都来看我文章啦,不给辛辛苦苦写文章的我点个赞mua❤❤❤~

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值