C语言练习(2)——链表实现多项式加法


前言

兄弟们,每日一题,怡情悦兴
使用链表来实现多项式的加法。
这本该是数据结构中最为简单的试题,菜的抠脚的我敲了半个下午。。。😠
警醒:多练习!多思考! 切勿:走马观花,浅尝辄止!


一、题目描述

成对输入两个多项式的系数和指数,系数与指数间要空格,并且以0 0结束。
例如:1 2 3 4 5 2 3 4 0 0
这意味着输入了:
(为什么两个指数符号会变成这样😟😟😟)
在这里插入图片描述

二、解题思路

构建两个链表存放多项式,重点实现链表冒泡排序函数功能、合并同类项函数、多项式相加函数;
① 两个多项式分别按照指数由小到大排序
② 两个多项式分别合并同类项
③ 根据第一个多项式中的每一项,去第二个多项式中找同类项:
————❶如果有同类项,把系数累加并将该项移到和多项式中
————❷如果没有同类项,直接把该项移到和多项式中
④ 根据第二个多项式中的每一项,去第二个多项式中找同类项:
————❸如果有同类项,就不予理会,因为该项在上一部中已经被第一个多项式中的某一项累加过了
————❹如果没有同类项,就要把这一项移到和多项式中
字迹虽丑但清😉在这里插入图片描述


三、代码展示

实现函数时:一定要注意某些控制循环的变量要 更新或者重新赋值
难点部分要仔细看注释!

1.SL.h

(1)引用函数库

注意引用stdlib.h
有时你不引用,VS检查不出来,就会莫名其妙的报错
代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>

(2)定义链表

定义链表结构体时,分别命名List和Node,对节点和链表做出区分,更加直观。
此处也可以将 typedef int DataType;💣注意要加上分号
便于更改系数类型
代码如下

typedef struct ListNode
{
	int coef;
	int expon;
	struct ListNode* next;
}List,Node;

(3)声明接口函数

主要实现初始化函数、头插函数、打印函数等常见函数
以及特殊函数:链表冒泡排序、合并同类项、多项式相加
代码如下:

//创建带头单链表
void CreateList(List** PtrtoList);
//创建节点
Node* CreateNode(int coef, int expon);
//头插
void ListPushFront(List* PtrtoList);
//链表排序
void ListSort(List* PtrtoList);
//节点合并
List* NodeMerge(List* PtrtoList);
//链表求和
void ListAdd(List* p1, List* p2, List* add);
//链表打印
void ListPrint(List* PtrtoList);

2.SL.c

(1)创建带头单链表

带头节点的链表一般都需要初始化函数,注意该处使用的是💣💣传址调用,要记得&
代码如下:

//创建带头单链表
void CreateList(List** PtrtoList)
{
	*PtrtoList = (List*)malloc(sizeof(List));
	(*PtrtoList)->coef = 0;
	(*PtrtoList)->expon = 0;
	(*PtrtoList)->next = NULL;
}

(2)创建节点

代码如下:

//创建节点
Node* CreateNode(int coef, int expon)
{
	Node* tem = (Node*)malloc(sizeof(Node));
	tem->coef = coef;
	tem->expon = expon;
	return tem;
}

(3)头插

💣💣💣要注意我们要获得键入的偶数个整数,每两个创建一个节点,且输入时只有到结尾0 0后才敲enter键,必须要这样使用scanf函数!
代码如下:

//头插
void ListPushFront(List* PtrtoList)
{
	int coef, expon;
	//注意scanf函数的使用形式
	scanf("%d %d", &coef, &expon);
	while (coef != 0 || expon != 0)
	{
		//输入0 0时停止循环
		Node* tem = CreateNode(coef, expon);
		tem->next = PtrtoList->next;
		PtrtoList->next = tem;
		scanf("%d %d", &coef, &expon);
	}
}

(4)链表排序

💣💣💣实现该功能的前提是要十分熟悉数组的冒泡排序,然后比葫芦画瓢利用三个指针到达数组中i和j的循环控制功能。请仔细看注释!

代码如下:

//链表排序(冒泡)
void ListSort(List* PtrtoList)
{
	if (PtrtoList->next == NULL)
	{
		printf("链表为空\n");
		return;
	}
	//设立尾指针,通过将尾指针逐渐前移
	//实现控制每次冒泡排序的数据减少一个的功能
	Node* tail = NULL;
	Node* cur = NULL;
	Node* next = NULL;
	int flag = 1;
	//当尾指针指向第二项时,便停止
	//最后一趟排序只剩第一项数据,不必再排了
	while (tail!=PtrtoList->next->next)
	{
		cur = PtrtoList->next;
		next = cur->next;
		while (next != tail)
		{
			if (cur->expon > next->expon)
			{
				//交换系数和指数
				int tem1 = next->expon;
				next->expon = cur->expon;
				cur->expon = tem1;
				int tem2 = next->coef;
				next->coef = cur->coef;
				cur->coef = tem2;
				flag = 0;
			}
			cur = cur->next;
			next = cur->next;
		}
		if (flag == 1)
			break;
		//将尾指针前移
		tail = cur;
	}
}

(5)节点合并(合并同类项)

注意我写的这个函数是将链表合并后移到新链表中,最终返回List*类型
主要通过使用两个指针,前指针指向第一项,后指针指向第二项。后指针每循环遍历完一次,前指针后移一位,旗舰判断它们的指数,进行系数的累加。
💣💣💣仔细观察nexttem
💣💣💣 因为链表是排序后的,如果链表中有tem的同类项一定紧跟在其后,所以当nexttem的指数和tem不一样就直接break,并且在将该项移到新链表后,可以将nexttem直接赋给tem,不仅保证tem后移,还确保tem的指数一定增加了
代码如下:

//节点合并(合并多项式中的同类项)
List* NodeMerge(List* PtrtoList)
{
	//创建一个新链表,存放合并后的多项式
	List* NewList;
	CreateList(&NewList);
	//设立两个指针
	//第一个指针指向首元节点(第一项),然后向后遍历
	//第二个指针始终指向第一个指针的后面
	Node* tem = PtrtoList->next;
	Node* nexttem = tem->next;
	while (tem)
	{
		nexttem = tem->next;
		//记录第一项的系数
		int newcoef = tem->coef;
		//第二个指针向后移动
		while (nexttem)
		{
			//从第二个指针指向的位置向后
			//寻找和第一个指针指向的指数相同的项
			//累加它们的系数
			if (tem->expon != nexttem->expon)
			{
				break;
			}
			else
			{
				newcoef += nexttem->coef;
			}
			nexttem = nexttem->next;
		}
		//创建合并后的节点,头插到新链表中
		Node* new = CreateNode(newcoef, tem->expon);
		new->next = NewList->next;
		NewList->next = new;
		//更新tem指针,使得两个指针都向后移动
		tem = nexttem;
	}
	//返回新链表
	return NewList;
}

(6)链表求和

方法很值得记忆,这里再重复一遍,加强记忆
⚠️ 根据第一个多项式中的每一项,去第二个多项式中找同类项:
————❶如果有同类项,把系数累加并将该项移到和多项式中
————❷如果没有同类项,直接把该项移到和多项式中
⚠️: 根据第二个多项式中的每一项,去第二个多项式中找同类项:
————❸如果有同类项,就不予理会,因为该项在上一部中已经被第一个多项式中的某一项累加过了
————❹如果没有同类项,就要把这一项移到和多项式中
仔细看代码
代码如下;

//链表求和
void ListAdd(List* PtrtoList1, List* PtrtoList2, List* add)
{
	//先将两个多项式分别合并同类项
	List* p1 = NodeMerge(PtrtoList1);
	List* p2 = NodeMerge(PtrtoList2);
	Node* tem1 = p1->next, * tem2 = p2->next;
	Node* tem3 = add->next;
	int newcoef = 0;
	//先依照第一个多项式,去第二个多项式中寻找同类项
	//如果有同类项,合并后移入和多项式中
	//如果没有同类项,将第一个多项式中的这一项移入和多项式中
	while (tem1)
	{
		//这里一定要注意重新赋值给tem2
		tem2 = p2->next;
		newcoef = tem1->coef;
		while (tem2)
		{
			//有同类项,合并,累加系数
			if (tem1->expon == tem2->expon)
			{
				newcoef += tem2->coef;
				//两个多项式已经被Merge过,只可能存在一个同类项
				break;
			}
			tem2 = tem2->next;
		}
		//将tem1中的项插入到和多项式中
		Node* new = CreateNode(newcoef, tem1->expon);
		new->next = add->next;
		add->next = new;
		tem1 = tem1->next;
	}
	//注意此tem2移动后变成了NULL,add后面也插入了新节点
	//tem2,tem3应该重新赋值
	tem2 = p2->next;
	tem3 = add->next;
	//依照第二个多项式,在和多项式中寻找同类项
	//有同类项的项不可以移到和多项式中
	//没有同类项的项可以移动
	while (tem2)
	{
		newcoef = tem2->coef;
		//注意tem3发生了改变,要重新赋值
		tem3 = add->next;
		//flag=1以为着没有同类项,即可以移动
		int flag = 1;
		while (tem3)
		{
			if (tem2->expon == tem3->expon)
			{
				flag = 0;
				break;
			}
			tem3 = tem3->next;
		}
		if (flag == 1)
		{
			Node* new = CreateNode(newcoef, tem2->expon);
			//将新找到的没有同类项的项移到和多项式中
			new->next = add->next;
			add->next = new;
		}
		tem2 = tem2->next;
	}
	//对和多项式排序
	ListSort(add);
}

(7)链表打印

常用接口函数,只要注意下这是带头节点的函数即可
只不过稍微有点麻烦,暂时没有优化😁😁
①分为最后一项和其他项(因为最后一项不用加+)
②再分为系数为0、系数为1、其它系数
③最后分成指数为0、指数为1、其它指数

//链表打印
void ListPrint(List* PtrtoList)
{
	printf("多项式之和是: ");
	Node* tem = PtrtoList->next;
	//除最后一项外,每项后面带有+
	while (tem->next)
	{
		//系数为0
		if (tem->coef == 0)
		{
			tem = tem->next;
		}
		//系数为1
		else if (tem->coef == 1)
		{
			//指数为0
			if (tem->expon == 0)
			{
				printf("1+");
				tem = tem->next;
			}
			//指数为1
			else if (tem->expon == 1)
			{
				printf("X+");
				tem = tem->next;
			}
			//指数不是1和0
			else
			{
				printf("X^%d+",tem->expon);
				tem = tem->next;
			}
		}
		//系数不是1和0
		else
		{
			//指数为0
			if (tem->expon == 0)
			{
				printf("%d+", tem->coef);
				tem = tem->next;

			}
			//指数为1
			else if(tem->expon==1)
			{
				printf("%dX+", tem->coef);
				tem = tem->next;
			}
			//指数不是1和0
			else
			{
				printf("%dX^%d+", tem->coef, tem->expon);
				tem = tem->next;
			}
		}
	}
	//最后一项不带+,单独打印
	//系数为0,不打印
	if (tem->coef == 0)
	{
		;
	}
	//系数为1
	else if (tem->coef == 1)
	{
		//指数为0
		if (tem->expon == 0)
		{
			printf("%d", tem->coef);
		}
		//指数为1
		else if (tem->expon == 1)
		{
			printf("X");
		}
		//指数不为1和0
		else
		{
			printf("X^%d",tem->expon);
		}
	}
	//系数不为1和0
	else
	{
		//指数为0
		if (tem->expon == 0)
		{
			printf("%d", tem->coef);
		}
		//指数为1
		else if (tem->expon == 1)
		{
			printf("%dX", tem->coef);
		}
		//指数不为0和1
		else
		{
			printf("%dX^%d", tem->coef, tem->expon);
		}
	}
}

3.test.c

这里稍微实现了一点菜单的提示功能
代码如下:

#include"sl.h"
int main()
{
	printf("请确保按照格式输入!\n");
	List *list1,*list2;
	CreateList(&list1);
	CreateList(&list2);
	//键入系数和指数
	printf("请两两输入系数和指数,系数与指数间有空格,并以0 0结尾!\n");
	printf("例:1 1 2 3 4 5 0 0\n");
	printf("请输入第一个多项式:");
	ListPushFront(list1);
	printf("请输入第二个多项式:");
	ListPushFront(list2);
	ListSort(list1);
	ListSort(list2);
	List* add;
	CreateList(&add);
	ListAdd(list1,list2,add);
	ListPrint(add);
}

四、运行检验

在这里插入图片描述

总结(求赞😘)

😑😑😑敲了半个下午的代码属实繁琐和笨拙,写的时候坚持正面硬钢,不参考大神们的优秀代码。写完后看别人的思路和代码,明白了差距的巨大,但这并不重要!

引用文本
重要的是:自己努力思考后,再去捧读优秀文章,颇有茅塞顿开、醍醐灌顶之感! 在这里希望大家都可以多独立实践,勤于深度思考,必有所获!

此外,最重要的是:拒绝白嫖哦
在这里插入图片描述

  • 18
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
下面是 C 语言中用链表实现多项式加法的代码: ```c #include <stdio.h> #include <stdlib.h> // 定义多项式结点 typedef struct PolyNode { int coef; // 系数 int expon; // 指数 struct PolyNode* next; } PolyNode, *PolyList; // 多项式加法 PolyList PolyAdd(PolyList P1, PolyList P2) { PolyList front, rear, temp; int sum; // 初始化空结点 rear = (PolyList)malloc(sizeof(PolyNode)); front = rear; while (P1 && P2) { if (P1->expon == P2->expon) { sum = P1->coef + P2->coef; if (sum) { temp = (PolyList)malloc(sizeof(PolyNode)); temp->coef = sum; temp->expon = P1->expon; rear->next = temp; rear = temp; } P1 = P1->next; P2 = P2->next; } else if (P1->expon > P2->expon) { temp = (PolyList)malloc(sizeof(PolyNode)); temp->coef = P1->coef; temp->expon = P1->expon; rear->next = temp; rear = temp; P1 = P1->next; } else { temp = (PolyList)malloc(sizeof(PolyNode)); temp->coef = P2->coef; temp->expon = P2->expon; rear->next = temp; rear = temp; P2 = P2->next; } } // 将未处理完的结点添加到结果链表中 for (; P1; P1 = P1->next) { temp = (PolyList)malloc(sizeof(PolyNode)); temp->coef = P1->coef; temp->expon = P1->expon; rear->next = temp; rear = temp; } for (; P2; P2 = P2->next) { temp = (PolyList)malloc(sizeof(PolyNode)); temp->coef = P2->coef; temp->expon = P2->expon; rear->next = temp; rear = temp; } // 结束链表 rear->next = NULL; // 删除空结点 temp = front; front = front->next; free(temp); return front; } // 创建多项式 PolyList CreatePoly() { PolyList P, rear, temp; int coef, expon; // 初始化空结点 rear = (PolyList)malloc(sizeof(PolyNode)); P = rear; // 输入多项式的系数和指数 while (scanf("%d %d", &coef, &expon) == 2) { if (!coef || !expon) { break; } temp = (PolyList)malloc(sizeof(PolyNode)); temp->coef = coef; temp->expon = expon; rear->next = temp; rear = temp; } // 结束链表 rear->next = NULL; // 删除空结点 temp = P; P = P->next; free(temp); return P; } // 打印多项式 void PrintPoly(PolyList P) { if (!P) { printf("0 0\n"); return; } for (; P; P = P->next) { printf("%d %d", P->coef, P->expon); if (P->next) { printf(" "); } } printf("\n"); } int main() { PolyList P1, P2, PP; // 创建多项式 P1 和 P2 printf("请输入多项式 P1:\n"); P1 = CreatePoly(); printf("请输入多项式 P2:\n"); P2 = CreatePoly(); // 求多项式 P1 和 P2 的和 PP = PolyAdd(P1, P2); // 打印结果 printf("P1 + P2 = "); PrintPoly(PP); return 0; } ``` 以上代码中,首先定义了多项式结点 `PolyNode`,然后定义了多项式链表 `PolyList`,其中每个结点包含系数 `coef` 和指数 `expon` 两个成员,以及一个指向下一个结点的指针 `next`。 接着,定义了函数 `PolyAdd` 实现多项式加法,它通过遍历两个多项式链表,将指数相同的项相加,并添加到结果链表中,最后返回结果链表。 函数 `CreatePoly` 用于创建多项式,它通过输入系数和指数,创建多项式链表并返回。 函数 `PrintPoly` 用于打印多项式,它遍历多项式链表并按格式输出。 在 `main` 函数中,先分别创建多项式 `P1` 和 `P2`,然后求它们的和 `PP`,最后输出结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值