C语言实现两个多项式加法与乘法

加法实现:

先说一下,我用了两种方法实现,一种是顺序表实现,一种是链表实现,所以,为了方便,将两种方法分别写成头文件了,主函数是一样的

方法一(顺序表实现)

直接上代码,头文件"List.h"代码:

//头文件"List.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<Windows.h>
#define MAXSIZE 1005
typedef int ElementType;
typedef struct LNode {//定义结构体
	ElementType Data1[MAXSIZE];
	ElementType Data2[MAXSIZE];//因为后面的第二题要用到两个数组,所以我在第一题就一次定义了两个数组
							   //防止后面贴重复代码
	int Last;//数组Data用来存放数据
				  //Last用来标记存放数据的最后一个位置
				  //Last其实就是Data数组存放的最后一个元素的下标
				  //所以Last+1其实就是线性表的长度
}*List;
List makeEmpty() {//创建线性表
	List L = (List)malloc(sizeof(struct LNode));
	L->Last = -1;
	return L;
}
int Find(List L, ElementType x) {//查找   0
	int i = 0;
	while (i <= L->Last && L->Data1[i] != x)i++;
	if (i > L->Last)return -1;
	return i;
}
List Insert(List L, ElementType x, ElementType y, int i) {//插入   1
	if (L->Last == MAXSIZE - 1) {//表空间已满,不能插入
		printf("表满\n");
		return L;
	}
	if (i<1 || i>L->Last + 2) {
		printf("位数不合法\n");
		return L;
	}
	for (int j = L->Last; j >= i - 1; j--)
		L->Data1[j + 1] = L->Data1[j];//数据后移
	L->Data1[i - 1] = x;
	L->Data2[i - 1] = y;
	L->Last++;//插入成功后,线性表长度+1,并且Last仍指向最后一个元素
	return L;
}
int Length(List L) {//计算线性表的长度   2
	return L->Last + 1;
}
bool Delete(List L, int i) {//删除第i个元素   3
	if (i<0 || i>L->Last + 1) {
		printf("位序%d不存在元素\n", i);
		return false;
	}
	for (int j = i; j <= L->Last; j++) {
		L->Data1[j] = L->Data1[j + 1];
		L->Data2[j] = L->Data2[j + 1];
	}//数据前移就相当于删去了位序i的元素
	L->Last--;//删除成功后,线性表的长度-1,并且Last仍指向最后一个元素

}
ElementType FindKth(List L, int i) {//输出第i位元素   4
	if (i<1 || i>L->Last + 1) {
		printf("位序%d不存在元素\n", i);
		return false;
	}
	return L->Data1[i];
}
void print(List L) {//将线性表中的元素全部打印出来 5
	if (L->Last == -1) {
		printf("0\n");
		return;
	}
	if (L->Data1[0] != 0) printf("%d*X^%d", L->Data1[0], L->Data2[0]);
	else printf("0");
	for (int i = 1; i <= L->Last; i++) {
		if (L->Data1[i] == 0)continue;
		if (L->Data1[i] == 1) {
			if (L->Data2[i] == 0) {
				if (L->Data1[i] < 0) printf("%d", L->Data1[i]);
				else printf("+%d", L->Data1[i]);
			}
			else if (L->Data2[i] == 1) {
				if (L->Data1[i] < 0)printf("X");
				else printf("+X");
			}
			else {
				if (L->Data1[i] < 0)printf("X^%d", L->Data2[i]);
				else printf("+*X^%d", L->Data2[i]);
			}
		}
		else {
			if (L->Data2[i] == 0) {
				if (L->Data1[i] < 0) printf("%d", L->Data1[i]);
				else printf("+%d", L->Data1[i]);
			}
			else if (L->Data2[i] == 1) {
				if (L->Data1[i] < 0)printf("%d*X", L->Data1[i]);
				else printf("+%d*X", L->Data1[i]);
			}
			else {
				if (L->Data1[i] < 0)printf("%d*X^%d", L->Data1[i], L->Data2[i]);
				else printf("+%d*X^%d", L->Data1[i], L->Data2[i]);
			}
		}
	}
	printf("\n");
}
List List_sort(List L) {//将线性表中的数按指数大小进行排列
	//并将表中数组Data1[]的值为0的删除
	if (L->Last == -1) return L;
	else {
		for (int i = 0; i <= L->Last; i++)//去重,防止输入错误使线性表中存在两个指数相同的元素
			for (int j = i + 1; j <= L->Last; j++)
				if (L->Data2[i] == L->Data2[j] && L->Data1[i] != 0 && L->Data1[j] != 0) {
					L->Data1[i] += L->Data1[j];
					L->Data1[j] = 0;
				}
		for (int i = 0; i <= L->Last; i++)
			if (L->Data1[i] == 0) Delete(L, i);
		for (int i = 0; i <= L->Last; i++) //选择排序
			for (int j = i + 1; j <= L->Last; j++)
				if (L->Data2[i] < L->Data2[j]) {
					ElementType t = L->Data1[i];
					L->Data1[i] = L->Data1[j];
					L->Data1[j] = t;
					t = L->Data2[i];
					L->Data2[i] = L->Data2[j];
					L->Data2[j] = t;
				}
	}
	return L;
}
List add(List a, List b) {//将两个多项式相加
	List L = makeEmpty();//用数组Data1储存多项式的系数,用数组Data2储存多项式的指数
	if (a->Last == -1 && b->Last == -1) printf("要相加的两个多项式均为空\n");
	else if (a->Last == -1 && b->Last != -1) L = b;
	else if (a->Last != -1 && b->Last == -1) L = a;
	else if (a->Last != -1 && b->Last != -1) {
		L = a;
		//若是用L来遍历b,我们每次循环后都要将已经处理过的b的元素删掉(避免重复添加)
		//这样就会出现重加(b的这个元素与L的这个元素指数不等,但是可能会有L的其它元素与b的这个元素相等)
		//不好判断是否删除b元素等情况
		for (int i = 0; i <= b->Last; i++) {//用b来遍历L,可以在不用删除b表中的元素就可以相加了,就不会出现误删的情况了
			int flag = 0;
			for (int j = 0; j <= L->Last; j++) {
				if (L->Data2[j] == b->Data2[i]) {
					L->Data1[j] += b->Data1[i];
					flag = 1;
				}
			}
			if (flag == 0) L = Insert(L, b->Data1[i], b->Data2[i], L->Last + 2);
			//Delete(b, i);
		}
	}
	return L;
}

方法二(链表实现)

头文件"List.c"代码:

//头文件"List.c"代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<Windows.h>
typedef struct LNode* PtrToLNode;
typedef int ElementType;
struct LNode {
	ElementType Data1, Data2;
	//Data1用来存系数,Data2用来存指数
	PtrToLNode Next;
};
typedef PtrToLNode List;
List makeEmpty() {//创建一个空链表并且将第一个节点空置
	List L = (List)malloc(sizeof(struct LNode));
	L->Next = NULL;
	return L;
}
int Length(List L) {//计算链表的长度
	//因为第一个节点是没有数据的,所以要从第二个节点开始计数
	List p = L->Next;
	int cut = 0;
	while (p != NULL) {
		cut++;
		p = p->Next;
	}
	return cut;
}
void Findkth(List L, int k) {//在链表中查找第k个元素
	List p = L->Next;
	int cnt = 1;
	while (p != NULL && cnt < k) {
		p = p->Next;
		cnt++;
	}
	if (cnt == k) {
		printf("第%d个元素为:", k);
		if (p->Data2 == 0)printf("%d\n", p->Data1);
		else printf("%dX^%d\n", p->Data1, p->Data2);
	}
	else 
		printf("在链表中没有第%d个元素\n", k);
}
List Find(List L, ElementType x) {//在链表中查找元素x的位置
	//因为在多项式中,指数才是唯一的,所以x应该是为指数
	List p = L->Next;
	while (p && p->Data2 != x) p = p->Next;
	if (p)return p;
	else return NULL;
}
List Insert(List L, ElementType x, ElementType y, int i) {//插入函数
	List tmp = (List)malloc(sizeof(struct LNode));
	tmp->Data1 = x; tmp->Data2 = y;
	int cnt = 0;
	List p = L;
	while (p && cnt < i - 1) {
		p = p->Next;
		cnt++;
	}
	if (p == NULL || cnt != i - 1) 
		printf("插入位置的参数错误\n!");
	else {
		tmp->Next = p->Next;
		p->Next = tmp;
	}
	return L;
}
List Delete(List L, int i) {//将第i个元素删除
	List tmp, p = L;
	int cnt = 0;
	while (p && cnt < i - 1) {
		p = p->Next;
		cnt++;
	}
	if (p == NULL || cnt != i - 1 || p->Next == NULL)printf("删除位置参数错误!\n");
	else {
		tmp = p->Next;
		p->Next = tmp->Next;
		free(tmp);
	}
	return L;
}
void print(List L) {//打印相加之后的多项式
	if (L->Next == NULL) {//如果链表中没有数据,直接退出函数
		printf("0\n");
		return;
	}
	List p = L->Next;
	if (p->Data1 != 0) printf("%d*X^%d", p->Data1, p->Data2);
	else printf("0");
	p = L->Next->Next;
	while (p != NULL) {
		if (p->Data1 == 0) {
			p = p->Next;
			continue;
		}
		if (p->Data1 == 1) {
			if (p->Data2 == 0) {
				if (p->Data1 < 0) printf("%d", p->Data1);
				else printf("+%d", p->Data1);
			}
			else if (p->Data2 == 1) {
				if (p->Data1 < 0)printf("X");
				else printf("+X", p->Data1);
			}
			else {
				if (p->Data1 < 0)printf("X^%d", p->Data1, p->Data2);
				else printf("+X^%d", p->Data1, p->Data2);
			}
		}
		else {
			if (p->Data2 == 0) {
				if (p->Data1 < 0) printf("%d", p->Data1);
				else printf("+%d", p->Data1);
			}
			else if(p->Data2==1){
				if (p->Data1 < 0)printf("%d*X", p->Data1);
				else printf("+%d*X", p->Data1);
			}
			else {
				if (p->Data1 < 0)printf("%d*X^%d", p->Data1, p->Data2);
				else printf("+%d*X^%d", p->Data1, p->Data2);
			}
		}
		p = p->Next;
	}
	printf("\n");
}
List List_sort(List L) {
	if (L->Next == NULL)return L;//如何链表中没有有效的元素,直接返回L
	List p, q;
	p = L->Next;
	int i = 0;
	for (p = L->Next; p!= NULL; p = p->Next) //见链表中的元素按指数大小进行排序
		for (q = p->Next; q!= NULL; q = q->Next) //选择排序
			if (p->Data2 < q->Data2) {
				ElementType t = p->Data2;
				p->Data2 = q->Data2;
				q->Data2 = t;
				t = p->Data1;
				p->Data1 = q->Data1;
				q->Data1 = t;
			}
	return L;
}
List add(List a, List b) {
	List p = b->Next;
	while (p != NULL) {
		List q = a->Next;
		int flag = 0;
		while (q != NULL) {
			if (p->Data2 == q->Data2) {//如果两个链表的指数相等,就将两个链表中的对应系数相加
				q->Data1 += p->Data1;
				flag = 1;
			}
			q = q->Next;
		}
		if (flag == 0)Insert(a, p->Data1, p->Data2, Length(a) + 1);
		p = p->Next;
	}
	return a;
}

最后是主函数代码:

#include"List.h"//导入头文件,这个文件是用顺序存储实现的
//#include"List.c"//这个头文件是用链表实现的
//分别用两个头文件运行得到的结果是一样的(亲自调试过)
//在使用其中一个头文件是应将另一个头文件注释掉
int main() {
	List a = makeEmpty();
	List b = makeEmpty();
	int na, nb;
	printf("请分别输入多项式a与多项式b的非0系数的个数:\n");
	scanf("%d %d", &na, &nb);
	printf("请输入多项式a的各项系数与指数:\n");
	ElementType x, y;
	if (na != 0) {//输入应确保每个多项式的指数没有相同的
		//因为在多项式中指数相同的元素应该已经相加好了
		while (na--) {
			scanf("%d %d", &x, &y);
			a = Insert(a, x, y, Length(a) + 1);//将新加入的元素插到表尾
		}
	}
	if (nb != 0) {
		printf("请输入多项式b的各项系数与指数:\n");
		while (nb--) {
			scanf("%d %d", &x, &y);
			b = Insert(b, x, y, Length(b) + 1);//将新加入的元素插到表尾
		}
	}
	List L = add(a, b);//多项式相加
	List_sort(L);//将相加后的线性表去除0系数的元素并进行按指数大小的从大到小的排序
	printf("两个多项式相加后得到的结果为:\n");
	print(L);//直接输出相加完之后的多项式
	return 0;
}

运行结果:(两个文件的运行结果相同)

 乘法实现:

乘法的实现我只写了一种方法,就是用链表实现

嗯,头文件和前面的加法实现代码"List.c"是一样的,就不再贴了

只是在主函数中加了两个自定义函数

主函数代码:

#include "List.c"
List Multiplication(List a, List b) {//将两个多项式相乘的函数
	List c = makeEmpty();//重新创建一个链表来存相乘之后的数据
	List p = a->Next;
	List d = c;
	while (p != NULL) {//两层循环把连个链表遍历
		List q = b->Next;
		while (q != NULL) {
			List s = (List)malloc(sizeof(struct LNode));
			s->Data1 = p->Data1 * q->Data1;
			s->Data2 = p->Data2 + q->Data2;
			//多项式相乘,系数相乘,指数相加
			d->Next = s;
			s->Next = NULL;
			d = s;
			q = q->Next;
		}
		p = p->Next;
	}
	return c;
}
List new_List_sort(List L) {//进行查重,将相同的指数数据相加
	List p = L->Next;
	while (p != NULL) {
		List q = p->Next;
		while (q != NULL) {
			if (p->Data2 == q->Data2) {
				p->Data1 += q->Data1;
				q->Data1 = 0;
			}
			q = q->Next;
		}
		p = p->Next;
	}
	return L;
}
int main() {
	List a = makeEmpty();
	List b = makeEmpty();
	int na, nb;
	printf("请分别输入多项式a与多项式b的非0系数的个数:\n");
	scanf("%d %d", &na, &nb);
	printf("请输入多项式a的各项系数与指数:\n");
	ElementType x, y;
	if (na != 0) {//输入应确保每个多项式的指数没有相同的
		//因为在多项式中指数相同的元素应该已经相加好了
		while (na--) {
			scanf("%d %d", &x, &y);
			a = Insert(a, x, y, Length(a) + 1);//将新加入的元素插到表尾
		}
	}
	if (nb != 0) {
		printf("请输入多项式b的各项系数与指数:\n");
		while (nb--) {
			scanf("%d %d", &x, &y);
			b = Insert(b, x, y, Length(b) + 1);//将新加入的元素插到表尾
		}
	}
	List c = Multiplication(a, b);//多项式相乘
	List_sort(c);//将相乘后的线性表去除0系数的元素并进行按指数大小的从大到小的排序
	new_List_sort(c);//将相乘后的链表进行查找,防止出现有指数相同的两个结点
	printf("两个多项式相乘后得到的结果为:\n");
	print(c);//直接输出相乘完之后的多项式
	return 0;
}

下面是运行结果展示(因为数据太大不好验算,所以就造了一些比较简单的数据):

嗯,就到这里了,比较简单,也没什么好讲解的。 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoyuer2815

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值