浙大数据结构:02-线性结构2 一元多项式的乘法与加法运算

02-线性结构2 一元多项式的乘法与加法运算

这道题真是太逆天了,写费劲,调试更费劲。下面我来说明一下思路。

1、主函数

主函数比较简单,调用函数构造两个链表,然后再调用相乘、相加、输出函数。
int main()
{
List l1,l2,ladd,lmulti;
    l1=Read();
    l2=Read();
    lmulti=Mult(l1,l2);
    Print(lmulti);
    ladd=Add(l1,l2);
    Print(ladd);
    return 0;
}

2、结构体定义、Read()函数

我们采用链表来实现:系数,指数,指针
typedef struct node* List;
struct node{
  int pre;   //系数
  int up;    //指数
  List next;  //指针
};
Read函数也较容易,此处采用尾插法
List Read()
{  
        int num;cin>>num;//有多少结点
    List L=new node;L->next=NULL;//初始化头节点
    struct node h;h.next=L;  //保存头节点,用来返回
//L指针用来遍历链表将结点连起来,所以会往后移
    for(int i=1;i<=num;i++)
    {
     List t=new node;  //创建新结点
        int p,u;cin>>p>>u;
        t->pre=p;t->up=u;  //初始化新的系数、指数
     t->next=L->next;
        L->next=t;
        L=L->next;      //往后遍历继续创建
    }
    return h.next;   //返回头节点
}

 3、Add函数、newlink函数

这里头我们实质想实现Add函数,由于中间有的代码重用了,所以我们又写了一个newlink函数来减少代码行数。
先说明一下newlink函数是干嘛的,这里头是把结点p接到L的后面,这个步骤在Add函数里面多次出现。L指向链表的最后一个结点,新结点会被接在尾部
void  newlink(List L,List p)
{ //L后面新接个结点p
     List t=new node;
            t->pre=p->pre;   
            t->up=p->up; 
            t->next=L->next;
            L->next=t;
  //创建新结点,把p复制过来,接到L后面
}
 我们来看一下Add函数的实现:
首先新建头节点和保存头结点的指针用来返回,p的话后面随着遍历来移动。
此处我们把相加的结果放在新的一个链表中,不修改原来的两个链表因为后面要用
然后遍历两个链表,把指数大的放前面,指数相等就相加再放进去
最后如果有没遍历完的,把链表接到后面

List Add(List L1,List L2)
{//此处是新建一个链表来保存两个链表的结果
    struct node h;   //保存头节点,就是为了返回用的
  List p=new node;p->next=NULL;  //后续p会遍历链表,找不到初始状态了,用h来存初始位置
    h.next=p;     
    L1=L1->next;L2=L2->next;
   //L1,L2指向第一个结点
    while(L1&&L2)
    {  //当两者都没遍历完时
        if(L1->up<L2->up)
        {  //把大的结点放前面
           newlink(p,L2);
            p=p->next;
            L2=L2->next;
        }
        else if(L1->up>L2->up)
        {   //把大的结点放前面
            newlink(p,L1);
            p=p->next;
            L1=L1->next;
        }
        else 
        {   //如果两节点相等就合并
            List t=new node;
            t->pre=L1->pre+L2->pre;
            t->up=L1->up;
            t->next=p->next;
            p->next=t;
            p=p->next;
            L1=L1->next,L2=L2->next;
        }
    }
    while(L1)
    {   //L1还剩下没遍历完,接到新链表后面
        newlink(p,L1);
        p=p->next,L1=L1->next;
    }
     while(L2)
    {//L2还剩下没遍历完,接到新链表后面
        newlink(p,L2);
        p=p->next,L2=L2->next;
    }
    return h.next;  //保存的是头节点,返回相加后的新链表
}

4、Mult函数、multi函数

此处也是目的是实现Mult函数,但multi函数这块代码被重用很多次,所以单独写减少冗余。
先讲一下乘法实现思路:
我们选择L2链表,用它的每一个结点与L1相乘,把结果相加(调用Add函数)就行了。
先看一下multi函数:
此处是用small结点与链表L的每一个结点相乘,得到新链表,不修改链表L,我们新开辟空间。
前面几行一样,初始化新的链表,然后进行遍历,将节点相乘存到新链表中
返回新链表的头结点
List   multi(List  L, List small)
{  //用结点small与链表L相乘
struct node h;
  List p=new node;p->next=NULL;
    h.next=p; 
    L=L->next;    //前几行代码与前面一样,初始头节点,h存方便返回,p后面遍历
    while(L)
    {
        List t=new node;
        t->pre=small->pre*L->pre;   //系数相乘
        t->up=small->up+L->up;      //指数相加
        t->next=p->next;
        p->next=t;
        p=p->next;
        L=L->next;
    }
    return h.next;//返回相乘的新链表
}
 再来看Mult函数
遍历L2的每一个结点,用他们与L1所有结点相乘。
此处先乘第一个结点,初始化一下p,然后循环遍历,t存当前结点与L1相乘的结果。
将p,t相加,结果赋给p,p就更新为L2前几个结点的与L1相乘的累加和
最后返回p

List Mult(List L1,List L2)
{//链表L1与链表L2相乘
  List p;L2=L2->next;//L2指向第一个结点
    if(L2)  p=multi(L1,L2); //与L1相乘
      L2=L2->next;
   while(L2)
   {
    List t=multi(L1,L2);  //t来存下一个结点与L1的相乘结果
    p=Add(p,t);         //将两个结果相加
    L2=L2->next;
   }
     //p由于不断更新现在存的是最终结果
    return p;  //将两个链表相乘的结果存到新链表中返回
}

5、Print函数

 print函数先找到第一个系数不为0 的结点,如果遍历完L都没找到,输出0 多项式,否则先输出第一个结点的系数、指数。
注意输出方式,最后输出完不能有多的空格
void Print(List L)
{
    L=L->next;//到第一个结点
     while(L&&L->pre==0)L=L->next;//找到第一个系数不为0的结点
     if(!L) {cout<<"0 0"<<endl;//L遍历完了也没找到,输出0多项式
     return ;}
     cout<<L->pre<<' '<<L->up;
//此处输出是为了最后输出的结果不能多空格,注意不能多输出空格!!!!
        L=L->next;
    while(L)
    {if(L->pre)
        cout<<' '<<L->pre<<' '<<L->up;  //系数不为0就输出该结点
        L=L->next;
    }
    cout<<endl;
}

六、总结

这道题相当费时,花了不少时间希望我的代码能对大家有帮助。
完整代码如下: 
#include<iostream>
using namespace std;
typedef struct node* List;
struct node{
  int pre;
  int up;
  List next;
};

void  newlink(List L,List p)
{ //L后面新接个结点p
     List t=new node;
            t->pre=p->pre;
            t->up=p->up;
            t->next=L->next;
            L->next=t;
}
List Read()
{  
        int num;cin>>num;
    List L=new node;L->next=NULL;
    struct node h;h.next=L;
    for(int i=1;i<=num;i++)
    {
     List t=new node;
        int p,u;cin>>p>>u;
        t->pre=p;t->up=u;
     t->next=L->next;
        L->next=t;
        L=L->next;
    }
    return h.next;   //返回头节点
}
List Add(List L1,List L2)
{
    struct node h;
  List p=new node;p->next=NULL;
    h.next=p;
    L1=L1->next;L2=L2->next;
    while(L1&&L2)
    {
        if(L1->up<L2->up)
        {
           newlink(p,L2);
            p=p->next;
            L2=L2->next;
        }
        else if(L1->up>L2->up)
        {
            newlink(p,L1);
            p=p->next;
            L1=L1->next;
        }
        else 
        {
            List t=new node;
            t->pre=L1->pre+L2->pre;
            t->up=L1->up;
            t->next=p->next;
            p->next=t;
            p=p->next;
            L1=L1->next,L2=L2->next;
        }
    }
    while(L1)
    {
        newlink(p,L1);
        p=p->next,L1=L1->next;
    }
     while(L2)
    {
        newlink(p,L2);
        p=p->next,L2=L2->next;
    }
    return h.next;  //保存的是头节点,返回相加后的新链表
}
List   multi(List  L, List small)
{  //用结点small与链表L相乘
struct node h;
  List p=new node;p->next=NULL;
    h.next=p;
    L=L->next;
    while(L)
    {
        List t=new node;
        t->pre=small->pre*L->pre;
        t->up=small->up+L->up;
        t->next=p->next;
        p->next=t;
        p=p->next;
        L=L->next;
    }
    return h.next;//返回相乘的新链表
}
List Mult(List L1,List L2)
{//链表L1与链表L2相乘

  List p;L2=L2->next;
    if(L2)  p=multi(L1,L2);
      L2=L2->next;
   while(L2)
   {
    List t=multi(L1,L2);
    p=Add(p,t);
    L2=L2->next;
   }
    return p;
}
void Print(List L)
{
    L=L->next;
     while(L&&L->pre==0)L=L->next;
     if(!L) {cout<<"0 0"<<endl;
     return ;}
     cout<<L->pre<<' '<<L->up;
        L=L->next;
    while(L)
    {if(L->pre)
        cout<<' '<<L->pre<<' '<<L->up;
        L=L->next;
    }
    cout<<endl;
}

int main()
{
List l1,l2,ladd,lmulti;
    l1=Read();
    l2=Read();
    lmulti=Mult(l1,l2);
    Print(lmulti);
    ladd=Add(l1,l2);
    Print(ladd);
    return 0;
}

附录:线性表的定义与操作

顺序表:

#include<stdlib.h>
#include<stdio.h>
typedef struct LNode *List;
typedef int ElementType;
typedef int Position;
#define  MAXSIZE   100
#define ERROR -1
struct LNode 
{
    ElementType data[MAXSIZE];
    Position End;
};
List MakeEmpty()
{
    List L;
    L=(List)malloc(sizeof(struct LNode));
    L->End=-1; 
    return L;
}

Position Find(List L,ElementType x)
{
    Position i=0;
    while(i<L->End&&L->data[i]!=x)
    i++;
    if(i>L->End)return ERROR;
    return i;
}

bool Insert(List L ,ElementType x,Position i)
{
    if(L->End+1>=MAXSIZE)return 0;
    if(i<0||i>MAXSIZE-1)return 0;
    for(Position p=L->End;p>=i;p--)
       L->data[p+1]=L->data[p];
       L->End++;
       L->data[i]=x;
       return 1;
}

bool Delete (List L,Position p)
{
    if(p<0||p>L->End)return 0;
    for(Position i=p;i<=L->End;i++)
       L->data[i]=L->data[i+1];
       L->End--;
       return 1;
}

链式表:

#include<stdlib.h>
#include<stdio.h>
typedef struct LNode *List;
typedef int ElementType;
typedef List Position;
#define  MAXSIZE   100
#define ERROR NULL
struct LNode 
{
    ElementType value;
    Position Next;
};
bool init()
{
List L;
L->Next=NULL;
return 1;
}
Position Find( List L,ElementType x)
{
    L=L->Next;
    while(L&&L->value!=x)
    L=L->Next;
   if(L)return L;
   else return ERROR;
}

bool Insert(List L,ElementType x,Position p)
{
    while(L&&L->Next!=p)
    L=L->Next;
    if(L==NULL)return 0;
    List t=(List)malloc(sizeof(struct LNode));
    t->value=x;
    t->Next=L->Next;
    L->Next=t;
    return 1;
}

bool Delete (List L,Position p)
{
    while(L&&L->Next!=p)
    L=L->Next;
    if(L==NULL)return 0;
    L->Next=p->Next;
    free(p);
    return 1;
}

  • 27
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值