xxl10000

编程、学习

在C语言中用链表实现两个多项式加减乘

目标:输入两个多项式,计算它们的+-*的运算结果,并按幂次从小到大输出到屏幕

输入方法:从文件输入多项式原始数据           

多项式文件的格式如下 n  a1  m1  a2  m2  a3  m3  . .. ai  mi....  an  mn           其中 n 为项数,ai为系数,mi为指数, 它们都是整数。 上述数据所表达的多项式为:           a1*x^m1 + a2*x^m2 + a3*x^m3 + ...... + an * x^mn           (符号^表示幂次)  

 两个多项式用两行表示。

 

输出方式:屏幕输出:参与运算的 2 个多项式以及它们的运算结果

实现过程中要求:

(1) 采用链表结构表示多项式

(2) 运算结果中不能保留系数为零的项

(3) 设计友善的显示方式,使得用户能够清晰直观的看到运算结果。

(4) 自行设计测试数据,验证代码运行的正确性

 

方法:

一:

首先结构模块化设计,先设计链表读入文件数据(read_data),再建立按幂次项排序函数(reorder,之后加函数归约于连接两个链表后的总链表的排序函数,而减函数归约同加函数(减即加的逆运算),然后对乘法,类比(a1+a2+……+an(b1+b2+……+bm)=a1(b1+b2+……bm)+……an(b1+b2+……bm),链表同理,可归约为分解成n次加函数,最后输出人性化(x^0=1,1x^a=x^a等)输出结果,free链表

注:十分重要的一点是你需要建立一个复制链表数据的函数,原因如下:

1. 因为需要在进行三种运算,在进行减、乘之前你不能破坏掉链表的数据。

2. 在进行乘法运算时,你需要记录每次加法运算结果的链表,且不能破坏原链表。

二:链表排序函数分析

对链表进行排序,本质上是使得指针交换,指向的内容不变或指针不变,指向的内容交换,因为含有n块部分链表可看做有nn-1、……、1级指针,如

Int *p1,*p2,*p3,a[2]={1,2};

Int temp;

p1=&a;

p=&a[1]; printf(“%d”,*p1);printf(“%d”,*p2);

要么变指针,p3=p2;p2=p1;p1=p3;

要么变内容, temp=a[0];a[0]=a[1];a[1]=temp;

二者选其一,在链表中对于一个一般无序的链表,

如果变指针,牵涉到3个结构变量,

如果变内容,牵涉到2个结构变量,且变内容程序更直观,可读性强;

故本程序使用变内容的方式。

注:引用“神似”p->next ,注意探测p!=0

 

#include<stdio.h>

#include<stdlib.h>

struct term{

int a;

int index;

struct term *next;

};

struct term *read_data(FILE *fp,int n); // 读取文件数据

struct term *reorder(struct term *list);  // 按指数排序

struct term *list_copy(struct term *list);  // 复制链表

struct term *add(struct term *list1,struct term *list2);  // 加

struct term *subtruct(struct term *list1,struct term *list2);  // 减

struct term *multiply(struct term *list1,struct term *list2);  // 乘

void print(struct term *head);  // 遍历

int main(void)

{

FILE *fp;

struct term *list1=0,*list2=0,*add_list=0,*subtruct_list=0,*multiply_list=0,*p1=0;

    int i,n1,n2;

if((fp=fopen("e:\\test data.txt","r"))==0){

printf("File open error!\n");

exit (0);

}

printf("Make sure that the number of polynomial formula contains accurate!\n");

fscanf(fp,"%d",&n1);  

list1=read_data(fp,n1);       

fscanf(fp,"%d",&n2);

list2=read_data(fp,n2);

print(list1);

print(list2);

list1=reorder(list1);   // 给第一个多项式按指数从小到大排序  

list2=reorder(list2);   // 给第二个多项式按指数从小到大排序

add_list=add(list1,list2);

printf("Add carculate:\n");

    print(add_list);

subtruct_list=subtruct(list1,list2);

printf("Subtruct carculate:\n");

print(subtruct_list);

multiply_list=multiply(list1,list2);

printf("Multiply carculate:\n");

print(multiply_list);

if(fclose(fp)) {

printf("File close error\n");

exit(0);

}

for(;add_list;add_list=p1)

{

p1=add_list->next;

free(add_list);

}

for(;subtruct_list;subtruct_list=p1) // free不再使用的链表

{

p1=subtruct_list->next;

free(subtruct_list);

}

for(;multiply_list;multiply_list=p1)

{

p1=multiply_list->next;

free(multiply_list);

}

return 0;

}

struct term *read_data(FILE *fp,int n)

{

struct term *head=0,*tail=0,*p=0;

int i;

for(i=1;i<=n;i++){

p=(struct term*)malloc(sizeof(struct term));

fscanf(fp,"%d%d",&p->a,&p->index);

p->next=0;

if(head==0) head=p;

else tail->next=p;

tail=p;

}

return head;

}

struct term *reorder(struct term *list)

{

    struct term *p1=0,*p2=0;

    int temp,change;

    p1=p2=list;

    if(p1==0||p1->next==0) return p1;

    for(;p1&&p1->next;p1=p1->next)

{

for(p2=list;p2&&p2->next;p2=p2->next)

{

if(p2->index > p2->next->index) // 大于,取内容(系数、指数)交换

{

   temp=p2->a;

   p2->a=p2->next->a;

   p2->next->a=temp;

   change=p2->index;

   p2->index=p2->next->index;

   p2->next->index=change;

}

if(p2->index==p2->next->index)

{

   p2->a=p2->a+p2->next->a;

   p2->next=p2->next->next;

}

}

    }

    

    return list;

}

struct term *list_copy(struct term *list)

{

struct term *head=0,*tail=0,*p=0;

while(list)

{

p=(struct term*)malloc(sizeof(struct term));

p->a=list->a;

p->index=list->index;

p->next=0;

if(head==0) head=p;

else tail->next=p;

tail=p;

list=list->next;

}

return head;

}

struct term *add(struct term *list1,struct term *list2)

{

struct term *p1=0,*p2=0;

p1=list1;

if(p1==0) return list2;

 while(p1->next)   

{

p1=p1->next;

}

p1->next=list2;

p2=list_copy(list1);

p2=reorder(p2);

p1->next=0;   // 还原list1、list2

return p2;

}

struct term *subtruct(struct term *list1,struct term *list2)

{

struct term *p1=0,*p2=0;

p1=list2;

if(list2==0) return list1;

while(p1->next)

{

p1->a=-p1->a;

p1=p1->next;

}

p1->a=-p1->a;

p1->next=list1;

p2=list_copy(list2);

p2=reorder(p2);

p1->next=0;  // 还原list1、list2

return p2;

}

struct term *multiply(struct term *list1,struct term *list2)

{

struct term *p1=0,*p2=0,*p3=0,*p4=0,*p5=0,*p6=0;

int i=1;

if(list1==0||list2==0) return 0;

for(p1=list1;p1;p1=p1->next,i++)

{   if(i==1) p5=p3=list_copy(list2);

    else p6=p4=list_copy(list2);    // 用p5和p6 记录链表头结点的地址

for(p2=list2;p2;p2=p2->next)

{

if(i==1)

{

p3->a=(-1)*p1->a*p2->a; //list2中的系数在 减函数 已经变相反数,乘 -1 还原

p3->index=p1->index+p2->index;

p3=p3->next;

}

else

{

p4->a=(-1)*p1->a*p2->a;

p4->index=p1->index+p2->index;

p4=p4->next;

}

    }

    if(i>1)

    {

    	p5=p3=add(p5,p6);

    	for(p4=p6;p4;p4=p6) // free不再使用的链表

    	{

    	p6=p4->next;

    	free(p4);

    	}

    }

}

    return p5;

}

void print(struct term *head)

{

    struct term *p=0;

    int i=1;

p=head;

if(head==0) {printf("Insert error!\n");

}

else{while(p->a==0&&p->next){

p=p->next;}

if(p==0||p->a==0) printf("0");

else {

  while(p){

   if(p->a){

   if(i!=1&&p->a>0) {printf("+");}

   i++;

   if(p->index==0) printf("%d",p->a);

   if(p->index==1) {

   if(p->a==1) printf("x");

   if(p->a==-1)printf("-x");

   if(p->a!=1&&p->a!=-1) printf("%dx",p->a);}

   if(p->index!=0&&p->index!=1){

if(p->a==1) printf("x^%d",p->index);

if(p->a==-1)printf("-x^%d",p->index);

if(p->a!=1&&p->a!=-1) printf("%dx^%d",p->a,p->index);}

   }

   p=p->next;

  }

    }

    

    }

printf("\n");



}

 


 

阅读更多
版权声明: https://blog.csdn.net/xxl10000/article/details/79945055
个人分类: 2018.4
下一篇整数划分问题
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭