链表实现加法与乘法
构建一个链表
typedef struct LinkNode{
int coef;//系数
int expn;//幂指数
LinkNode *next;
}LinkNode,*LinkList;
为了使得直接可以更好的查看输出结果,顺便写一个show函数用来展示结果
void show(LinkList L){//输出多项式链表结点;
if(L==NULL||L->next==NULL){
printf("0 0\n");
return;
}
LinkNode *r=L->next;
while(r->next){
printf("%d %d ",r->coef,r->expn);
r=r->next;
}
printf("%d %d\n",r->coef,r->expn);
}
现在我们来考虑多项式的加法怎么实现:
首先我们假定输入的多项式都是按幂次升序排列输入的,然后将多项式中的一个单项式拿出来,然后将其系数和幂次作为两个数据传入链表当中。因为word作图不方便我就直接手画了(字丑勿喷):
然后我们对两个链表进行比较,比较幂次部分是否相同,如果不同,把幂次小的的先插入新链表,如果幂次相同,则对系数部分进行加减法,这时候要判断一下结果是否为零,如果结果为零,直接丢弃这个结点,然后依次遍历下去直到两个链表都遍历结束。(这里的插入结点到新链表部分我就不写了哦!)
LinkList Listadd(LinkList L1,LinkList L2){
LinkNode *front=(LinkNode *)malloc(sizeof(LinkNode));
LinkNode *rear=front;
front->next=NULL;
int co,ex;//系数与幂指数;
LinkNode *r1=L1->next,*r2=L2->next;
if(r1==NULL&&r2==NULL) return NULL;
while(r1&&r2){//当两个链表不为空的时候;
if(r1->expn==r2->expn){
co=r1->coef+r2->coef;
if(co!=0){
ex=r1->expn;
attach(co,ex,rear);
}
r1=r1->next;
r2=r2->next;
}
else if(r1->expn<r2->expn){
attach(r1->coef,r1->expn,rear);
r1=r1->next;
}
else{
attach(r2->coef,r2->expn,rear);
r2=r2->next;
}
}
while(r1){
attach(r1->coef,r1->expn,rear);
r1=r1->next;
}
while(r2){
attach(r2->coef,r2->expn,rear);
r2=r2->next;
}
rear->next=NULL;
return front;
}
这样我们加法就结束了。
乘法 (难点哦!)
按照我们正常的思维习惯肯定是循环遍历两个链表,然后对于两个链表中的结点都进行一次乘法运算,然后使用其中一个链表长度大小值的个数个新链表存储。用途表示就是这样:
但是有没有感觉我们浪费了太多内存来存储呢?所以我们可以使用直接在上一次存储的新链表中继续操作,就是找一个适合的结点插入新得到的结果咯
所以我们有:
LinkList ListMultiply(LinkList L1,LinkList L2){
LinkNode *front=(LinkNode *)malloc(sizeof(LinkNode));
LinkNode *rear=front;
front->next=NULL;
int co,ex;//系数与幂指数;
LinkNode *r1=L1->next,*r2=L2->next;
if(r1==NULL||r2==NULL) return NULL;
//先用L1第一个结点与L2乘一次;
while(r2){
co=r2->coef*r1->coef;
ex=r2->expn+r1->expn;
attach(co,ex,rear);
r2=r2->next;
}
r1=r1->next;
while(r1){//L1第一个结点后面的结点与L2中每一个结点进行乘积。所得结点插入到front初始链表中;
r2=L2->next;//重置r2;
rear=front;//重置rear,以便于寻找新节点attach的位置;
while(r2){//遍历L2;
co=r2->coef*r1->coef;
ex=r2->expn+r1->expn;//乘积操作;
while(rear->next&&ex>rear->next->expn){//找到链尾或者当前幂指数小于 等于链表中rear->next结点的幂指数
rear=rear->next;
}
if(rear->next&&ex==rear->next->expn){//此时已经找到位置;
//分情况讨论:1.找到一个合适的位置:(1)幂指数相同
if(co+rear->coef==0){//找到了一个位置:
LinkNode *p=rear->next;
rear->next=p->next;
free(p);
}
else{
rear->next->coef+=co;
}
}
else{ //2.(1)找到链尾。(2)幂指数不同
//即要新建结点;
LinkNode *p=(LinkNode*)malloc(sizeof(LinkNode));
p->coef=co;
p->expn=ex;
p->next=rear->next;//两种情况区别在这
rear->next=p;
rear=rear->next;
}
r2=r2->next;//遍历
}
r1=r1->next;//r1的结点乘完;
}
return front;
}
然后测试函数就自己写咯!个人认为最好的测试函数是可视化结果的那种。