前言
实现将两个多项式相加、相减、相乘。具体代码以及讲解在下方。
1.引入库
- stdio.h:提供输入输出操作相关的函数,如printf、scanf等。
- stdlib.h:提供内存管理、类型转换、随机数生成等功能,如malloc、free、atoi等。
- math.h:提供数学运算相关的函数,如sin、cos、sqrt等。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
2结构体定义
数据域包含data和datax,data表示系数,datax表示指数
typedef struct Lnode{
int data; //系数
int datax; //指数
struct Lnode* next;
}LNode,*LinkList;
3.链表初始化
单链表包含头节点,方便后续插入操作
LinkList InitList(LinkList L){//头结点
L=(LinkList)malloc(sizeof(LNode));
if(L==NULL)
exit(EXIT_FAILURE);
L->next=NULL;
return L;
}
4.读入数据
读入数据,要实现对输入的数据自行进行排序,即使在输入时指数没有按照由小到大的数据顺序,也能按照由小到大的顺序输出。
在createList函数中,通过尾插法,将输入的结点添加到已经初始化好的单链表中,并通过LocateElem函数实现对输入的数据进行排序。
LocateElem函数讲解:
L是之前的链表,p是要插入的结点,在while循环中遍历L,分成三种请况
1.如果p的指数比L的第一项大,则继续向后遍历
2.如果p的指数与L的某一项相等,则将系数合并,跳出循环,尾指针r不变,因为最下面的if语句不会被执行。
3.如果p的指数比L的第一项小,则将p插入到L的某一项的前面,尾指针r不变,因为最下面的if语句不会被执行。
最下面的if语句,只有当p的指数比L中的每一项的指数都大时才会执行。
void createList(LinkList L,int l1){
int i;
LinkList p,r=L;//p是要插入的结点,r是尾指针
for(i=0;i<l1;i++){//尾插法
p=(LinkList)malloc(sizeof(LNode));
printf("请输入第%d项的系数和指数(以空格隔开):",i+1);
scanf("%d%d",&p->data,&p->datax);
r=LocateElem(L,p,r);
}
}
LinkList LocateElem(LinkList L,LinkList p,LinkList r){//排序
LinkList p1=L->next,p2=L;//p2为p1的前一项
while(p1){
if(p->datax>p1->datax){
p1=p1->next;
p2=p2->next;
}
else if(p->datax==p1->datax){
p1->data=p1->data+p->data;
break;
}
else{
p2->next=p;
p->next=p1;
break;
}
}
if(!p1){ //p1==NULL
p->next=NULL;
r->next=p;
r=p;
return r;
}
}
5.相加操作
为保证相加后的多相似依旧有序,需对相加的两项进行判断,分为三种情况。
从第一项开始,如果L1的指数小于L2的指数 ,则将L1的第一项添加到L3中,L1指向它的下一项,L2不动。
如果L1的指数等于L2的指数,则将这两项合并后添加到L3中,L1和L2都指向下一项。
如果L1的指数大于L2的指数 ,则将L2的第一项添加到L3中,L2指向它的下一项,L1不动。
直到L1或L2完全遍历完为止,然后将L1或L2中没有遍历完的部分(较长的)添加L3中。
void AdditionList(LinkList L1,LinkList L2,LinkList L3){
LinkList p=L1->next,q=L2->next,s,sr=L3;
while(p&&q){
s=(LinkList)malloc(sizeof(LNode));
if(p->datax<q->datax){//L1的指数比L2小
s->data=p->data;
s->datax=p->datax;
s->next=NULL;
sr->next=s;
sr=s;
p=p->next;
}
else if(p->datax==q->datax){//L1的指数和L2相等
s->data=p->data+q->data;
s->datax=p->datax;
s->next=NULL;
sr->next=s;
sr=s;
p=p->next;
q=q->next;
}
else{//L1的指数比L2大
s->data=q->data;
s->datax=q->datax;
s->next=NULL;
sr->next=s;
sr=s;
q=q->next;
}
}
if(p){
s->next=p;
}
else{
s->next=q;
}
}
6.相减操作
相减操作和相加操作的算法一样,只不过在相减操作中需要先将第二个多项式的系数变成负的,再进行操作。
此时会产生一个问题,就是L2中data域的值全都取负了,在执行时如果先进行了相减操作,会使之后进行的相加相乘操作产生错误。
void SubtractList(LinkList L1,LinkList L2,LinkList L4){
LinkList p=L1->next,q=L2->next,s,sr=L4;
while(q){//找负
q->data=0-(q->data);
q=q->next;
}
q=L2->next;
while(p&&q){
s=(LinkList)malloc(sizeof(LNode));
if(p->datax<q->datax){//L1的指数比L2小
s->data=p->data;
s->datax=p->datax;
s->next=NULL;
sr->next=s;
sr=s;
p=p->next;
}
else if(p->datax==q->datax){//L1的指数和L2相等
s->data=p->data+q->data;
s->datax=p->datax;
s->next=NULL;
sr->next=s;
sr=s;
p=p->next;
q=q->next;
}
else{//L1的指数比L2大
s->data=q->data;
s->datax=q->datax;
s->next=NULL;
sr->next=s;
sr=s;
q=q->next;
}
}
if(p){
s->next=p;
}
else{
s->next=q;
}
}
7.相乘操作
f(x1)=2X^2+3X^3,f(x2)= 3X^2+4X^3
对于上面两个多项式,相乘时,结果多项式会有三项而非四项。因有两项发生了合并。结局办法是将第一个多项式的第一项拿出来,依次和第二个多项式的每一项相乘,此时的操作和读入数据是完全相同的。
void multiplyList(LinkList L1,LinkList L2,LinkList L5){
LinkList p=L1->next,q=L2->next,r=L5,p1;
for(;p;){
for(;q;){
p1=(LinkList)malloc(sizeof(LNode));
p1->data=p->data*q->data;
p1->datax=p->datax+q->datax;
r=LocateElem(L5,p1,r);
q=q->next;
}
p=p->next;
q=L2->next;
}
}
8.打印多项式
void printfList(LinkList L,int j){
LinkList p=L->next;
if(j==3){
printf("和多项式为:P(X)=");
}
else if(j==4){
printf("差多项式为:P(X)=");
}
else if(j==5){
printf("积多项式为:P(X)=");
}
else{
printf("第%d个多项式为:P(X)=",j);
}
while(p){
if(p->data!=0){
printf("%dX^%d",p->data,p->datax);
p=p->next;
if(p!=NULL){//不是最后一项
if(p->data>=0){//系数是整数
printf("+");
}
}
}
else if(p->data==0&&p->next==NULL){//首项为0,且只有一项
printf("0");
p=p->next;
}
else{
p=p->next;
}
}
printf("\n");
}
9.多项式带值计算
void Sum(LinkList L,int x){
int i=0;
LinkList p=L->next;
while(p){
i+=p->data*pow(x,p->datax);
p=p->next;
}
printf("结果为:%d\n",i);
}
10.销毁单链表
void Destory(LinkList* L){
LinkList p;
while(*L){
p=*L;
*L=(*L)->next;
free(p);
}
}
11.菜单
void menu(){
printf( "*******************************************************\n");
printf( "**************** 1.输入1 相加 *******************\n");
printf( "**************** 2.输入2 相减 *******************\n");
printf( "**************** 3.输入3 相乘 *******************\n");
printf( "**************** 4.输入4 退出 *******************\n");
printf( "*******************************************************\n");
}
12.主函数
int main(int argc, char *argv[])
{
char p,c;
int l1,l2,x,y;
LinkList L1,L2,L3,L4,L5;
L1=InitList(L1);//第一个多项式
L2=InitList(L2);//第二个多项式
L3=InitList(L3);//相加后的多项式
L4=InitList(L4);//相减后的多项式
L5=InitList(L5);//相乘后的多项式
printf("请输入第一个多项式的项数:");
scanf("%d",&l1);
createList(L1,l1);
printfList(L1,1);
printf("请输入第二个多项式的项数:");
scanf("%d",&l2);
createList(L2,l2);
printfList(L2,2);
menu();
while ((c = getchar()) != '\n' && c != EOF){
// 清空输入缓冲区中的其他字符
}
printf("请输入要进行的操作序号:");
while(scanf("%d",&y)){
if(y==4){
printf("再见\n");
Destory(&L1);
Destory(&L2);
Destory(&L3);
Destory(&L4);
Destory(&L5);
return 0;
}
switch(y){
case 1:
AdditionList(L1,L2,L3);//相加
printfList(L3,3);
printf("是否带入X求结果?(是:Y,否:N):");
scanf(" %c",&p);
if(p=='Y'||p=='y'){
printf("请输入X的值:");
scanf("%d",&x);
Sum(L3,x);
}
printf("请输入要进行的操作序号:");
break;
case 2:
SubtractList(L1,L2,L4);//相减
printfList(L4,4);
printf("是否带入X求结果?(是:Y,否:N):");
scanf(" %c",&p);
if(p=='Y'||p=='y'){
printf("请输入X的值:");
scanf("%d",&x);
Sum(L4,x);
}
printf("请输入要进行的操作序号:");
break;
case 3:
multiplyList(L1,L2,L5);//相乘
printfList(L5,5);
printf("是否带入X求结果?(是:Y,否:N):");
scanf(" %c",&p);
if(p=='Y'||p=='y'){
printf("请输入X的值:");
scanf("%d",&x);
Sum(L5,x);
}
printf("请输入要进行的操作序号:");
break;
default:
printf("输入有误请重新输入\n");
printf("请输入要进行的操作序号:");
break;
}
}
}