一元多项式加法(乘法完善)

#include<bits/stdc++.h>
using namespace std;
typedef struct LNode {
	float coef;//系数
	int expn;//指数
	LNode* next;
}LNode,*Linklist;

void Initlist(Linklist& L)//初始化
{
	L = new LNode;
	L->next = NULL;
}
//冒泡排序单链表
void sortlist(Linklist& L)
{
	LNode *wt, *nt, *lastnt = NULL;
	for (wt = L->next; wt->next != NULL; wt = wt->next)
	{
		for (nt = L->next; nt->next != lastnt; nt = nt->next)
		{
			if (nt->expn > nt->next->expn)//如果当前结点的指数大于下一个将其交换
			{
				float temp;
				int Temp;//交换两个的指数和系数
				temp = nt->coef;
				Temp = nt->expn;
				nt->expn = nt->next->expn;
				nt->coef = nt->next->coef;
				nt->next->coef = temp;
				nt->next->expn = Temp;
			}
		}
	}
}
//多项式合并
Linklist mergelist(Linklist L)
{
	Linklist K;
	Initlist(K);
	LNode* p=L->next->next, * k = L->next, *q=K,*t;
	t = new LNode;
	t->coef = k->coef;
	t->expn = k->expn;
	t->next = q->next;
	q->next = t;
	q = t;
	while (p)
	{
		if (p->expn == q->expn)
		{
			q->coef = q->coef + p->coef;
		}
		else {
			t = new LNode;
			t->coef = p->coef;
			t->expn = p->expn;
			t->next = q->next;
			q->next = t;
			q = t;
		}
		p = p->next;
	}
	q->next = NULL;
	return K;
}
//尾插法建立链表
void createlist(Linklist& L)
{
	Initlist(L);//初始化链表
	LNode* s, * p = L;
	printf("请输入多项式一共有多少项:");
	int n;
	scanf("%d",&n);
	if (n <= 0)
	{
		int k;
		printf("(输入数字不规范)请重新输入多项式有几项:");
		scanf("%d",&k);
		n = k;
	}
	for(int i=0;i<n;i++)
	{
		s = new LNode;//生成一个新节点
		printf("请输入第%d项的系数和指数分别为:",i+1);
		scanf("%f %d",&s->coef,&s->expn);
		if (s->coef == 0)//如果输入的系数为0要重新输入
		{
			printf("请重新输入第%d项的系数和指数分别为:", i + 1);
			scanf("%f %d", &s->coef, &s->expn);
		}
		p->next = s;
		p = s;
	}
	p->next = NULL;//由于我上面已经初始化过所以这步可以省略,如果没有初始化的话要让尾指针指向NULL
	sortlist(L);//将链表排序将指数小的排在前面一般后续进行加法
	L = mergelist(L);
}
//加法
Linklist add_list(Linklist &L, Linklist &M)
{
	LNode* p = L->next, * q = M->next, * r, * s;
	r = L;//让指针r指向L的头节点
	while (p && q)//两个工作指针不管谁先遍历到表尾都要跳出while循环
	{
		if (p->expn < q->expn)//第一种情况如果p的指数小q指针不动让r指向p
		{
			r->next = p;
			p = p->next;
			r = r->next;
		}
		else if (p->expn > q->expn)//同样反过来一样
		{
			r->next = q;
			r = r->next;
			q = q->next;
		}
		else 
		{
			float sum = p->coef + q->coef;
			if (sum != 0.0)//如果两者系数相加不为0
			{
				p->coef = sum;//将系数之和赋给
				r->next = p;
				r = r->next;
				p = p->next;
				s = q;
				q = q->next;
				free(s); // 将M链表上这个无用的结点释放掉节省空间
			}
			else {
				s = p;//如果系数相加等于0的话就要将p和q都释放掉
				p = p->next;
				free(s);
				s = q;
				q = q->next;
				free(s);
			}
		}
	}
	r->next = p ? p : q;//这里用到三元运算符将余下的项加入到链表表尾
	free(M);
	return L; 
}
//加法不引用
Linklist add(Linklist L, Linklist M) {
	Linklist K;
	Initlist(K);
	LNode* p = L->next, * q = M->next, * r = K;
	while (p && q) {
		if (p->expn < q->expn) {
			LNode* t = new LNode;
			*t = *p; // 复制节点数据
			t->next = r->next;
			r->next = t;
			r = t;
			p = p->next;
		}
		else if (p->expn > q->expn) {
			LNode* c = new LNode;
			*c = *q; // 复制节点数据
			c->next = r->next;
			r->next = c;
			r = c;
			q = q->next;
		}
		else {
			float sum = p->coef + q->coef;
			if (sum!=0.0) { 
				LNode* x = new LNode;
				x->coef = sum;
				x->expn = p->expn;
				x->next = r->next;
				r->next = x;
				r = x;
			}
			p = p->next;
			q = q->next;
		}
	}
	r->next = p ? p : q; 
	K = mergelist(K);
	return K;
}
//乘法
Linklist Multilist(Linklist& L, Linklist& M)
{
	LNode* p, * q, * s, * t;
	p = L->next;
	q = M->next;
	Linklist K;
	Initlist(K);
	s = K;
	int flag = 0;//建立一个flag,这里是为了去特殊处理遍历第一个L的结点时,与M每项相乘所生成的一个多项式
	while (p)//外围循环遍历多项式L
	{
		if (flag == 0)
		{
			while (q)//内层遍历多项式M 
			{
				LNode* r;
				r = new LNode;
				float c = p->coef * q->coef;//系数相乘
				int d = p->expn + q->expn;//指数相加
				r->coef = c;
				r->expn=d;
				s->next = r;//跟尾插法建立链表一样,将多项式K建立,相当于部分积
				r->next = NULL;
				s = r;//跟尾插法建立链表一样,将多项式K建立,相当于部分积
				q = q->next;//遍历语句
			}

		}
		else {
			Linklist LO;
			Initlist(LO);
			t = LO;
			while (q)//跟上面一样
			{
				LNode* l;
				l = new LNode;
				l->coef = p->coef * q->coef;
				l->expn = p->expn + q->expn;
				t->next=l;
				l->next = NULL;
				t = l;
				q = q->next;
			}
			K = add_list(K, LO);//这一步是让每次的部分积累加,这也是我们flag村走的意义因为第一次每法跟0相加
		}
		p = p->next;//外围的循环语句
		q = M->next;//当然别忘将q指针重置,要不q都不知道循环到哪了
		flag = 1;//最后我们让flag等于1表明出来第一次后面都正常
	}
	return K;
}


//打印我们所进行的一系列操作
void printf_list(Linklist K)
{
	LNode* s = K->next;
	while (s)
	{
		if (s->coef != 1.0 && s->coef!=-1.0)//判断是否系数为1,则省略系数
		{
			if (s->expn == 0)printf("%.f", s->coef);
			else if (s->expn == 1)printf("%.fx", s->coef);
			else printf("%.fx^%d", s->coef, s->expn);
		}
		else if(s->coef==1.0)
		{
			if (s->expn == 0)printf("%.f", s->coef);
			else if (s->expn == 1)printf("x");
			else printf("x^%d", s->expn);
		}
		else {
			if (s->expn == 0)printf("-");
			else if (s->expn == 1)printf("-x");
			else printf("-x^%d", s->expn);
		}
		if (s->next != NULL && s->coef > 0)
			printf("+");
		s = s->next;
	}
	printf("\n");
}

int main()
{
	Linklist L, M, K, C;
	createlist(L);
	printf("第一个多项式为:\n");
	printf_list(L);
	createlist(M);
	printf("第二个多项式为:\n");
	printf_list(M);
	printf("两多项式相加为:\n");
	C = add(L, M);
	printf_list(C);
	K = Multilist(L, M);
	printf("两个多项式相乘为:\n");
	printf_list(K);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值