加法实现:
先说一下,我用了两种方法实现,一种是顺序表实现,一种是链表实现,所以,为了方便,将两种方法分别写成头文件了,主函数是一样的
方法一(顺序表实现)
直接上代码,头文件"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;
}
下面是运行结果展示(因为数据太大不好验算,所以就造了一些比较简单的数据):
嗯,就到这里了,比较简单,也没什么好讲解的。