设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0
。
输入样例:
4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1
输出样例:
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0
- 结合刚学完的C语言,结构中不能包含本结构类型的变量,但是可以包含本类型的指针,因为指针变量存放的数据是地址,系统为指针变量分配的内存字节数(即存放地址所需的内存字节数)是固定的,不依赖于它所指向的数据类型。
- attach函数不返回值,只修改rear值 ,链表中尾指针后移相当于尾部链接新项
- (每次老想定义指针来指向,但是结构体变量名本身可以做地址用)
- 不能用rear->link=rear->link->link;因为删除节点同时伴随着释放删除的节点的操作
- //注意rear本来是个结构变量但是进入attach函数以后是个指针,放的是rear的首地址
//所以(*rear)才是指针所指的内容
//既然rear是个指针,自然就不能 rear=rear->link;
//rear=new,什么都不是,肯定要报错,因为两个类型都不一样一个是指针一个是结构变量
//要对rear指针解应用
#include <stdio.h>
#include <stdlib.h>//malloc的头文件
//确定使用链表,所以定义链表节点
typedef struct PolyNode *Polynomial;
struct PolyNode{
int coef;
int expon;
Polynomial link;
};
Polynomial Add(Polynomial p1,Polynomial p2) ;
Polynomial Mult(Polynomial p1,Polynomial p2) ;
void Attach(int c,int e,Polynomial *rear) ;
Polynomial ReadPoly();
void PrintPoly(Polynomial p);
int main(){
Polynomial p1,p2,pm,ps;
p1=ReadPoly();
p2=ReadPoly();
pm=Mult(p1,p2);
PrintPoly(pm);
ps=Add(p1,p2);
PrintPoly(ps);
return 0;
}
Polynomial ReadPoly(){
int c,e,n;
Polynomial p,rear,t;
//rear:为了让attach函数中可以明确往哪里链接 ,而且attach函数中rear会被改变的
scanf("%d",&n);//确定有多少非0项
p=(Polynomial)malloc(sizeof(struct PolyNode));p->link=NULL;
rear=p;
while(n--){
scanf("%d %d",&c,&e);
Attach(c,e,&rear);
//链接新节点只意味着尾指针后移(新节点加入尾指针变化)
//因为链首节点p是不变的,而p可以作为结构体的首地址来返回整个链表
}
t=p;p=p->link;free(t);
return p;
}
void Attach(int c,int e,Polynomial *rear){ //本函数不返回值,只修改rear值
Polynomial p;
p =(Polynomial)malloc(sizeof(struct PolyNode));
p->coef=c;
p->expon=e;
p->link=NULL;//先初始化完所有的结构变量
(*rear)->link=p;
*rear=p;//修改rear,始终让rear指向最后一个节点,方便下次链接
}
//创建一个结果多项式,每次用p1的一项*p2的每一项 ,在结果多项式中找到插入位置插入进去
Polynomial Mult(Polynomial p1,Polynomial p2){
Polynomial p,rear,t1,t2,t;
//新结构多项式首节点,尾结点,p1p2首指针,t暂存待删除节点
int c,e;
if(!p1||!p2) return NULL;
//任意一个多项式为空,那么多项式乘法的结果就是空
//返回的空指针传入print函数,按照题目要求输出"0 0\n"
t1=p1;t2=p2;
p=(Polynomial)malloc(sizeof(struct PolyNode));p->link=NULL;
rear=p;
while(t2) //用t2->link!=NULL会内存超限??这我哪想得到啊郁闷
//把第一个多项式的第一项乘以第二个多项式的每一项得到初始多项式,此时多项式按照指数递减,是有序的
{ Attach(t1->coef*t2->coef,t1->expon+t2->expon,&rear);
t2=t2->link;
}
t1=t1->link; //第一项做完运算了,该往后了
while(t1){
t2=p2;rear=p;
//复原t2:t2在上一个循环中被改变了
//因为后面的操作需要在首节点开始查找插入位置,每比较一个就要改变rear的位置,p不能动的p是首节点
while(t2){
//开始每个t1与所有t2相乘
c=t1->coef*t2->coef;
e=t1->expon+t2->expon;
while(rear->link&&rear->link->expon>e){
//找插入位置,保存在rear里面
//用rear->link的原因是:删除操作需要前前一个节点位置
rear=rear->link;}
//插入位置:只要待插入的指数大于rear下一项的指数,指针就后移(因为要得到指数递降的序列)
if(rear->link&&rear->link->expon==e){
if(rear->link->coef+c)//指数相加不为零
rear->link->coef+=c;
else {
//不能用rear->link=rear->link->link;因为删除节点同时伴随着释放删除的节点的操作
t=rear->link;
rear->link=t->link;
free(t);
}
}
else{
//如果指数不相等,则要进行插入操作
t = (Polynomial)malloc(sizeof(struct PolyNode));
t->coef = c; t->expon = e;
//单链表的插入:rear指向是插入位置的前一个节点
t->link=rear->link;
rear->link=t;
}t2=t2->link;
}t1=t1->link;
}
t2=p;p=p->link;free(t2);
//这里的t是任意的,只用于释放p指向的空节点
//因为插入都是rear的link开始的,所以第一个节点就是空出来的
return p;
}
Polynomial Add(Polynomial p1,Polynomial p2){
int sum;
Polynomial t1,t2,p,rear,t;
p = (Polynomial)malloc(sizeof(struct PolyNode)); p->link = NULL;
t1 = p1; t2 = p2;
rear = p;
while(t1&&t2){
if(t1->expon==t2->expon){
sum=t1->coef+t2->coef;
if(sum) Attach(sum,t1->expon,&rear);
t1=t1->link;
t2=t2->link;
}
else if(t1->expon>t2->expon){
Attach(t1->coef,t1->expon,&rear);
t1=t1->link ;
}
else if(t1->expon<t2->expon){
Attach(t2->coef,t2->expon,&rear);
t2=t2->link;
}
}
if(t1){
rear->link=t1;
}
if(t2){
rear->link=t2;
}
t=p;p=p->link;free(t);
return p;
}
void PrintPoly(Polynomial p){
int flag=1;
if(!p) printf("0 0\n");
else {
while(p){
if(flag) flag=0;
else printf(" ");
printf("%d %d",p->coef,p->expon);
p=p->link;
}
printf("\n");//必须放在这里,因为人家0 0输出自己带着\n
}
}