3-2-3 链表 一元多项式的乘法与加法运算 (20 分)

题目来源:3-2-3 链表 一元多项式的乘法与加法运算 (20 分)
这个题目第二次写了,应该没问题了,第一次写最后两个点一直没过,今天才发现当add或者mul为空表(零多项式)应输出“0 0”。行吧,总算是过了。
上(第二次的)(个人感觉比第一次写的好看)代码:

#include<stdio.h>
#include<stdlib.h>
typedef struct dec* LinkList;
struct dec {
	int coef;//系数
	int expon;//指数
	LinkList next;
};
LinkList Read();
void Attach(int c, int e, LinkList* head, LinkList* tail);//尾巴接上
void Insert(int c, int e, LinkList* head, LinkList* tail);//中间接上
void print(LinkList L);
void Renew(LinkList* head);//把系数为0的清除,其实也可以边计算边清除去,但是感觉有个费时间,每次清楚都要从头遍历,不如一次性清除。
LinkList Add(LinkList L1, LinkList L2);//加法
LinkList Mul(LinkList L1, LinkList L2);//乘法
int main()
{
	LinkList L1, L2,add,mul;
	L1 = Read();
	L2 = Read();
	add = Add(L1, L2);
	mul = Mul(L1, L2);
	print(mul);
	printf("\n");
	print(add);
	return 0;
}
void Renew(LinkList* head)//更新,把所有系数为0的清楚干净
{
	while (*head&&(*head)->coef== 0) *head = (*head)->next;
	if (*head == NULL) return;
	LinkList front = *head,tail=front->next;//开始的front的系数肯定不为0;
	while (tail)
	{
		if (tail->coef == 0) {//删除节点
			front->next = tail->next;
			free(tail);
}
		front = front->next;
		tail = front->next;
	}
}
LinkList Mul(LinkList L1, LinkList L2)
{
    if (L1 == NULL || L2 == NULL)return NULL;//***这个没加导致第四个点一直过不去
	LinkList head = NULL, tail = NULL;
	LinkList point2 = L2 ,point1 = L1;
	int c, e;
	while (point2)//先将L1的一个元素和L2上的每一个元素相乘,构成一条链表
	{
		c = (point1 ->coef)* (point2->coef);
		e = (point1->expon) + (point2->expon);
		Attach(c, e, &head, &tail);
		point2 = point2->next;
	}
	point1 = point1->next;//这一步不能漏,第一条链表的第一个节点已与第二条链表每一个节点相乘,所以第一条链表的节点要后移
	while (point1)
	{
		point2 = L2;
		while (point2)//链表一的每一个节点与链表二的每一个节点相乘插入已经构成的链表
		{
			int c = point1->coef * point2->coef;
			int e = point1->expon + point2->expon;
			Insert(c, e, &head, &tail);
			point2 = point2->next;
		}
		point1 = point1->next;
	}
	Renew(&head);
	return head;
}
void Insert(int c, int e, LinkList* head, LinkList* tail)
{
	LinkList point = *head;
	if (e > point->expon) {//头部插入
		//其实是用不到的,因为两条链表(指数降序)的第一个节点相乘一定是最大的
		LinkList temp = (LinkList)malloc(sizeof(struct dec));
		temp->expon = e;
		temp->coef = c;
		temp->next = *head;
		*head = temp;
		return;
	}
	else if (e < (*tail)->expon)//尾部插入
	{
		Attach(c, e, &*head, &*tail);
		return;
	}
	while (point)//不能用head,会改变head的指向的,因为传入Insert函数的是head的二级指针
	{
		if (point->expon == e) {
			point->coef += c;//指数相同,系数相加
			return;
		}
		else if (e<point->expon && e>(point->next)->expon)//中间插入
		{
			LinkList temp = (LinkList)malloc(sizeof(struct dec));
			temp->expon = e;
			temp->coef = c;
			temp->next = point->next;
			point->next = temp;
			return;
		}
		point = point->next;

	}
}
LinkList Add(LinkList L1, LinkList L2)
{
    if (L1 == NULL && L2 == NULL) return NULL;//***这个没加导致第四个点一直过不去
	LinkList head = NULL, tail = NULL;
	int c, e;
	while (L1 && L2)
	{
		if (L1->expon == L2->expon)//指数相同,系数相加
		{
			c = L1->coef + L2->coef;
			e = L1->expon;
			if(c) Attach(c, e, &head, &tail);//系数不为0才保存
			L1 = L1->next,L2=L2->next;
		}
		else if (L1->expon > L2->expon)
		{
			if(L1->coef)Attach(L1->coef,L1->expon,&head, &tail);
			L1 = L1->next;
		}
		else
		{
			if(L2->coef)Attach(L2->coef, L2->expon, &head, &tail);
			L2 = L2->next;
		}
	}
	while (L1)
	{
		if(L1->coef)Attach(L1->coef, L1->expon, &head, &tail);
		L1 = L1->next;
	}
	while (L2)
	{
		if(L2->coef)Attach(L2->coef, L2->expon, &head, &tail);
		L2 = L2->next;
	}
	return head;
}
LinkList Read()
{
	LinkList head=NULL, tail=NULL;
	int n,c,e;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%d %d", &c, &e);
		Attach(c, e, &head, &tail);
	}
	return head;
}
void Attach(int c, int e, LinkList* head, LinkList* tail)
{
	LinkList temp = (LinkList)malloc(sizeof(struct dec));
	temp->next = NULL;
	temp->coef = c;
	temp->expon = e;
	if (*head == NULL)  *head = temp;
	else (*tail)->next = temp;
	*tail = temp;
}
void print(LinkList L)
{
	if (L == NULL)
	{
		printf("0 0");
		return;
	}
	int flag = 0;
	while (L) {
		if (flag != 0) printf(" ");
		flag = 1;
		printf("%d %d", L->coef, L->expon);
		L = L->next;
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值