【线性表】------稀疏多项式加法运算 的 链式实现(带头结点)

1.稀疏多项式回顾

1.稀疏多项式的定义

多项式中指数由低到高排列 ,每一项的系数非零的多项式
比如:
在这里插入图片描述

2.顺序存储与链式存储的优劣辨析:

在这里插入图片描述
我们可以使用顺序表来存储整个多项式,同样可以使用链表来存储整个多项式

  • 但是由于顺序表存在以下劣势,故本篇使用链表来存储
    在这里插入图片描述

2.稀疏多项式加法运算 的 链式实现

1.稀疏多项式结点的结构定义:

typedef struct Node
{
	double coef;//系数
	int expen;//指数
	struct Node* next;//指针域
}Node,* Polynomial;
//Polynomial:多项的

与一般的链表结点相同,只不过稀疏多项式结点数据域分为指数和系数两部分

2.通过用户输入建立稀疏多项式算法(系数按照非递减有序排列)

注意:由于要创建新链表,故传入二级指针

void CreatePolynomial(Polynomial *L,int n)
1.算法步骤:

(1)创建只有一个头结点的空链表(注意初始化)
(2)定义三个临时指针:
//s:用来建立新结点
//pre:用来指向待插入结点的前一个结点:第一个 (指数大于 待插入结点的 结点)的前一个结点
//q:用来指向待插入结点的后一个结点:第一个 指数大于 待插入结点的 结点
(3)循环并按照非递减有序排列插入结点(核心)
<1>建立并初始化新结点的系数与指数
<2>每次初始化 pre指向头结点(寻找待插入前驱);q指向当前首元结点(寻找待插入后继)
<3>遍历链表,寻找插入位置(q指向待插入位置的后一个结点)(pre指向待插入位置的前一个结点)
<4>将新结点插入到链表中正确位置中,即pre和q之间

//1.系数按照非递减有序排列 建立多项式
//核心:对于待插入结点 及其前一结点 和 后一结点的相关操作
void CreatePolynomial(Polynomial *L,int n)
{
	//[1]创建只有一个头结点的空链表
	(*L) = (Polynomial)malloc(sizeof(Node));
	
	if (!(*L))
	{
		return -1;//程序非正常返回
	}

	(*L)->next = NULL;

	//[2]定义三个临时指针:
	//s:用来建立新结点
	//pre:用来指向待插入结点的前一个结点:第一个 (指数大于 待插入结点的 结点)的前一个结点
	//q:用来指向待插入结点的后一个结点:第一个 指数大于 待插入结点的 结点
	Node* s,* pre,* q;
	
	//[3]循环并按照非递减有序排列插入结点
	for(int i=0;i<n;i++)
	{
		//<1>建立并初始化新结点的系数与指数
		s = (Node*)malloc(sizeof(Node));
		
		if (!s)
		{
			return -1; //程序非正常返回
		}

		printf("输入第%d项的系数和指数:\n",i+1);
		scanf_s("%lf %d", &s->coef, &s->expen);

		//<2>每次初始化 pre指向头结点(寻找待插入前驱);q指向当前首元结点(寻找待插入后继)
		pre = (*L);
		q = (*L)->next;
		

		//<3>遍历链表,寻找插入位置(q指向待插入位置的后一个结点)(pre指向待插入位置的前一个结点)
		while (q && q->expen < s->expen)//寻找 第一个 指数 大于 待插入的结点指数 的结点
		{
			pre = q;
			q = q->next;
		}

		//<4>将新结点插入到链表中正确位置中,即pre和q之间
		s->next = q;
		pre->next = s;
		
	}
}

3.多项式的相加算法(实际上为 有序表的合并操作 的实际应用)

void addpolynomial(Polynomial * La, Polynomial * Lb, Polynomial * Lc)

1.算法步骤:

0)保证传入两个非空的多项式
(1)初始化pa,pb分别指向La,Lb的首元结点,pc指向新链表的头结点
//pa用来遍历La中的所有结点
//pb用来遍历Lb中的所有结点
//pc用来遍历 新链表中 最新的有效结点(着重注意)
(2)遍历多项式 La 和 Lb,进行相加操作(核心)
<1>若两项指数相等------>进行系数相加操作
<1.1>若系数相加结果为0,跳过并删除当前pa和pb所指向的结点(注意不需要更新pc的指向;因为pc指向的是新链表中 最新的有效结点)
//<1.1.1>临时生成两个指针,用来删除待销毁结点
//<1.1.2>跳过pa所指结点,并更新pa,pb指向下一个结点
//<1.1.3>删除待销毁结点
<1.2>若系数相加结果不为0,修改pa所指结点系数值,同时删除pb所指结点(注意需要更新pc的指向;因为pc指向的是新链表中 最新的有效结点)
//<1.2.1>临时生成1个指针,用来删除待销毁结点
//<1.2.2>修改pa所指结点系数值,作为新的系数
//<1.2.3>修改新链表并保证完整性;同时修改pc的指向,指向最新的有效结点;更新pa,pb指向下一个结点
//<1.2.4>删除待销毁结点
<2>若pa指向的结点指数值 小于 pb指向的结点指数值,则将pa指向的结点添加到新链表中(类比升序链表的合并)
<3>若pa指向的结点指数值 大于等于 pb指向的结点指数值,则将pb指向的结点添加到新链表中(类比升序链表的合并)
(3)将非空多项式的剩余结点添加到新链表中最后一个有效结点之后(注意释放Lb的头结点)

//2.多项式的相加算法(实际上为 有序表的合并操作 的实际应用)
void addpolynomial(Polynomial * La, Polynomial * Lb, Polynomial * Lc)
{
	//[0]传入两个非空的多项式
	if ( (!(*La) || !(*La)->next) || (!(*Lb) || !(*Lb)->next))
	{
		printf("输入多项式不能为空!\n");
		return;
	}

	//[1]初始化pa,pb分别指向La,Lb的首元结点,pc指向新链表的头结点
	//pa用来遍历La中的所有结点
	//pb用来遍历Lb中的所有结点
	//pc用来遍历 新链表中 最新的有效结点
	Node* pa, * pb, * pc;
	pa = (*La)->next;
	pb = (*Lb)->next;
	(*Lc) = (*La);//用La的头结点作为新链表Lc的头结点(当然也可以使用Lb的头结点)
	pc = (*Lc);//实际上pc指向的是La的头结点

	//[2]遍历多项式 La 和 Lb,进行相加操作
	while (pa && pb)
	{
		//<1>若两项指数相等------>进行系数相加操作	
		if (pa->expen == pb->expen)	
		{
			double sum = pa->coef + pb->coef;
			//<1.1>若系数相加结果为0,跳过并删除当前pa和pb所指向的结点(注意不需要更新pc的指向;因为pc指向的是新链表中 最新的有效结点)
			if(sum==0)
			{
				//<1.1.1>临时生成两个指针,用来删除待销毁结点
				Node* temp_pa = pa;
				Node* temp_pb = pb;

				//<1.1.2>跳过pa所指结点,并更新pa,pb指向下一个结点
				pc->next = pa->next;
				pa = pa->next;  
				pb = pb->next;

				//<1.1.3>删除待销毁结点
				free(temp_pa);
				free(temp_pb);
			}
			//<1.2>若系数相加结果不为0,修改pa所指结点系数值,同时删除pb所指结点(注意需要更新pc的指向;因为pc指向的是新链表中 最新的有效结点)
			else
			{
				//<1.2.1>临时生成1个指针,用来删除待销毁结点
				Node* temp_pb = pb;

				//<1.2.2>修改pa所指结点系数值,作为新的系数
				pa->coef = sum;

				//<1.2.3>修改新链表并保证完整性;同时修改pc的指向,指向最新的有效结点;更新pa,pb指向下一个结点
				pc->next = pa;
				pc = pa;
				pa = pa->next;
				pb = pb->next;

				//<1.2.4>删除待销毁结点
				free(temp_pb);
			}
		}
		//<2>若pa指向的结点指数值  小于  pb指向的结点指数值,则将pa指向的结点添加到新链表中(类比升序链表的合并)
		else if (pa->expen < pb->expen)
		{
			pc->next = pa;
			pc = pa;
			pa = pa->next;
		}
		//<3>若pa指向的结点指数值  大于等于  pb指向的结点指数值,则将pb指向的结点添加到新链表中(类比升序链表的合并)
		else
		{
			pc->next = pb;
			pc = pb;
			pb = pb->next;
		}
	}


	//[3]将非空多项式的剩余结点添加到新链表中最后一个有效结点之后
	pc->next = pa ? pa : pb;
	
	
	free(*Lb);//释放Lb的头结点
}
2.实例图解:

在这里插入图片描述

3.整体实现:

//稀疏多项式的相加算法------链式存储结构的实现
#include<stdio.h>
#include<stdlib.h>

typedef struct Node
{
	double coef;//系数
	int expen;//指数
	struct Node* next;//指针域
}Node,* Polynomial;
//Polynomial:多项的


//1.系数按照非递减有序排列 建立多项式
//核心:对于待插入结点 及其前一结点 和 后一结点的相关操作
void CreatePolynomial(Polynomial *L,int n)
{
	//[1]创建只有一个头结点的空链表
	(*L) = (Polynomial)malloc(sizeof(Node));
	
	if (!(*L))
	{
		return -1;//程序非正常返回
	}

	(*L)->next = NULL;

	//[2]定义三个临时指针:
	//s:用来建立新结点
	//pre:用来指向待插入结点的前一个结点:第一个 (指数大于 待插入结点的 结点)的前一个结点
	//q:用来指向待插入结点的后一个结点:第一个 指数大于 待插入结点的 结点
	Node* s,* pre,* q;
	
	//[3]循环并按照非递减有序排列插入结点
	for(int i=0;i<n;i++)
	{
		//<1>建立并初始化新结点的系数与指数
		s = (Node*)malloc(sizeof(Node));
		
		if (!s)
		{
			return -1; //程序非正常返回
		}

		printf("输入第%d项的系数和指数:\n",i+1);
		scanf_s("%lf %d", &s->coef, &s->expen);

		//<2>每次初始化 pre指向头结点(寻找待插入前驱);q指向当前首元结点(寻找待插入后继)
		pre = (*L);
		q = (*L)->next;
		

		//<3>遍历链表,寻找插入位置(q指向待插入位置的后一个结点)(pre指向待插入位置的前一个结点)
		while (q && q->expen < s->expen)//寻找 第一个 指数 大于 待插入的结点指数 的结点
		{
			pre = q;
			q = q->next;
		}

		//<4>将新结点插入到链表中正确位置中,即pre和q之间
		s->next = q;
		pre->next = s;
		
	}
}


//2.多项式的相加算法(实际上为 有序表的合并操作 的实际应用)
void addpolynomial(Polynomial * La, Polynomial * Lb, Polynomial * Lc)
{
	//[0]传入两个非空的多项式
	if ( (!(*La) || !(*La)->next) || (!(*Lb) || !(*Lb)->next))
	{
		printf("输入多项式不能为空!\n");
		return;
	}

	//[1]初始化pa,pb分别指向La,Lb的首元结点,pc指向新链表的头结点
	//pa用来遍历La中的所有结点
	//pb用来遍历Lb中的所有结点
	//pc用来遍历 新链表中 最新的有效结点
	Node* pa, * pb, * pc;
	pa = (*La)->next;
	pb = (*Lb)->next;
	(*Lc) = (*La);//用La的头结点作为新链表Lc的头结点(当然也可以使用Lb的头结点)
	pc = (*Lc);//实际上pc指向的是La的头结点

	//[2]遍历多项式 La 和 Lb,进行相加操作
	while (pa && pb)
	{
		//<1>若两项指数相等------>进行系数相加操作	
		if (pa->expen == pb->expen)	
		{
			double sum = pa->coef + pb->coef;
			//<1.1>若系数相加结果为0,跳过并删除当前pa和pb所指向的结点(注意不需要更新pc的指向;因为pc指向的是新链表中 最新的有效结点)
			if(sum==0)
			{
				//<1.1.1>临时生成两个指针,用来删除待销毁结点
				Node* temp_pa = pa;
				Node* temp_pb = pb;

				//<1.1.2>跳过pa所指结点,并更新pa,pb指向下一个结点
				pc->next = pa->next;
				pa = pa->next;  
				pb = pb->next;

				//<1.1.3>删除待销毁结点
				free(temp_pa);
				free(temp_pb);
			}
			//<1.2>若系数相加结果不为0,修改pa所指结点系数值,同时删除pb所指结点(注意需要更新pc的指向;因为pc指向的是新链表中 最新的有效结点)
			else
			{
				//<1.2.1>临时生成1个指针,用来删除待销毁结点
				Node* temp_pb = pb;

				//<1.2.2>修改pa所指结点系数值,作为新的系数
				pa->coef = sum;

				//<1.2.3>修改新链表并保证完整性;同时修改pc的指向,指向最新的有效结点;更新pa,pb指向下一个结点
				pc->next = pa;
				pc = pa;
				pa = pa->next;
				pb = pb->next;

				//<1.2.4>删除待销毁结点
				free(temp_pb);
			}
		}
		//<2>若pa指向的结点指数值  小于  pb指向的结点指数值,则将pa指向的结点添加到新链表中(类比升序链表的合并)
		else if (pa->expen < pb->expen)
		{
			pc->next = pa;
			pc = pa;
			pa = pa->next;
		}
		//<3>若pa指向的结点指数值  大于等于  pb指向的结点指数值,则将pb指向的结点添加到新链表中(类比升序链表的合并)
		else
		{
			pc->next = pb;
			pc = pb;
			pb = pb->next;
		}
	}


	//[3]将非空多项式的剩余结点添加到新链表中最后一个有效结点之后
	pc->next = pa ? pa : pb;
	
	
	free(*Lb);//释放Lb的头结点
}


//3.输出多项式
void printPolynomial(Polynomial L)
{
	if (!L)
	{
		return -1;
	}

	Node* p = L->next;
	
	while (p)
	{
		printf("(%lf*x)%d+ ", p->coef, p->expen);
		p = p->next;
	}
	
	printf("end\n");
}





int main()
{
	Polynomial L1, L2, L3;
	CreatePolynomial(&L1, 3);
	printPolynomial(L1);
	
	CreatePolynomial(&L2, 4);
	printPolynomial(L2);

	addpolynomial(&L1, &L2, &L3);

	printPolynomial(L3);

	return 0;

}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值