单链表模拟一元多项式加减乘运算

第一个多项式有n项,第二个多项式有m项。以下均为最坏的情况。

操作

时间复杂度(T(n))

空间复杂度(S(n))

判断是否为空

O(1)

O(1)

得到长度

O(n)

O(1)

求和

O(n+m)

O(1)

求差

O(n+m)

O(1)

求积

O(n*m)

双重循环

O(n*m)

最坏的情况就是相乘后每一项的指数都不一样,这样就有n*m项(这种情况概率很低)

/*   数据结构分析与学习专栏
*  Copyright (c) 2015, 山东大学计算机科学与技术专业学生
*  All rights reserved.
*   作    者:   高祥
*   完成日期:  2015 年 3 月 28 日
*   版 本 号:006
 
*任务描述:单链表的应用,模拟一元多项式的运算。
*   1:建立一元多项式 ;
*   2:打印一元多项式 ;
*   3:输出一元多项式的项数 ;
*   4:判断一元多项式是否为空 ;
*   5:一元多项式求和 ;
*   6:一元多项式求差;
*   7:一元多项式求积 ;
*   8:销毁一元多项式;
 
*主要函数:
* 1.InitPoly(Polynome &P);//初始化头结点
* 2.FindPoly(Polynome P,Polynome&before,Polynome &after,int expo);
//建立一元多项式的辅助函数
//参数说明:
//P是已经存在的一元多项式的头结点指针;before是满足指数小于将要插入结点指数的第一个结点指针
//after是满足指数大于等于将要插入结点指数的第一个结点指针;expo是将要插入的结点指数
//注意:before与after指针必须引用传值,达到修改CreatPoly()函数中指针的目的,且after=before->next
* 3.CreatPoly(Polynome P,int polysize);//建立一元多项式
* 4.Output(Polynome P);//输出一元多项式
* 5.int PolyLength(Polynome P);//求一元多项式的项数
* 6.Status IsEmptyPoly(Polynome P);//判断一元多项式是否为空
* 7.AddPoly(Polynome P1,Polynome&P2);//一元多项式相加,将结果赋给多项式P1
* 8.SubtractPoly(Polynome P1,Polynome&P2);//一元多项式相减,将结果赋给P1
* 9.MultiplyPoly(Polynome &P1,Polynome&P2);//一元多项式相乘,将结果赋给P1
* 10.DestroyPoly(Polynome &P);//销毁多项式
 
*主要优点:
1.  创建多项式:用户输入任意组由用户决定的数据(无序状态),创建的多项式是合并同类项后并且结点的指数大小依次递增(通过辅助函数FindPoly来实现该排序的功能),不多含任何一项,在合并的过程中,某些项合并后消失,那么程序接着会释放无用节点的内存达到内存最少、项数最精简的效果。
例如输入9组数据:-5 0 5 0 0 1 1 2 1 2 -2 2 -7 1 7 3 21 4
输出为:P(x)=(-7)x+(7)x^(3)+(21)x^(4)
2.  输出多项式:符合人们书写的习惯。做到了:非第一项的系数为正前面加‘+’;系数为1省略输出;常数为1不能省略输出;指数为0不输出x;指数为1不输出指数;每输出10项换行。每个数字用括号括起来是因为:当系数很大时,系统会输出如‘1.009e+098’之类的数字,为了便于识别‘+’、‘-’符号,因此每个数字均加了括号。
3. 求多项式的和差:做到了:内存最优,运算后消失的项和指数相同冗余的项均释放了内存;运算后结果依然是按照指数的升序排序。
4. 求多项式的积:同样做到了内存最优。但是没想到怎样优化时间空间复杂度,采取最笨的一项乘一项的方式,两项相乘完以后,指数、系数均可能改变,为了依然按照指数升序排列,再次使用辅助函数FindPoly来实现该排序的功能,就好像是手动输入运算后的系数和指数一样,达到排序的效果。运算结束,销毁原来的两条多项式,将结果移交给第一个头结点。
*注意:以上函数中的形参的&均是必要的,都不能去掉
*/
 
#include<iostream>
#include<cstdlib>
using namespace std;
 
#define OK 1
#define FALSE 0
#define ERROR 0
 
const int INF=2000000000;
 
typedef int Status;
 
typedef struct
{
   double coef;
   int expo;
} ElemType;
 
typedef struct LNode
{
   ElemType data;
   struct LNode *next;
} LNode,*LinkList;
 
typedef LinkList Polynome;
 
void InitPoly(Polynome &P);//初始化头结点
 
void FindPoly(Polynome P,Polynome&before,Polynome &after,int expo);//建立一元多项式的辅助函数
//参数说明:
//P是已经存在的一元多项式的头结点指针;before是满足指数小于将要插入结点指数的第一个结点指针
//after是满足指数大于等于将要插入结点指数的第一个结点指针;expo是将要插入的结点指数
//注意:before与after指针必须引用传值,达到修改CreatPoly()函数中指针的目的,且after=before->next
 
void CreatPoly(Polynome P,int polysize);//建立一元多项式
 
void Output(Polynome P);//输出一元多项式
 
int PolyLength(Polynome P);//求一元多项式的项数
 
Status IsEmptyPoly(Polynome P);//判断一元多项式是否为空
 
void AddPoly(Polynome P1,Polynome&P2);//一元多项式相加,将结果赋给多项式P1
 
void SubtractPoly(Polynome P1,Polynome&P2);//一元多项式相减,将结果赋给P1
 
void MultiplyPoly(Polynome &P1,Polynome&P2);//一元多项式相乘,将结果赋给P1
 
void DestroyPoly(Polynome &P);//销毁多项式
 
void Interaction();
 
int main()
{
   Polynome P1=NULL,P2=NULL;//初始化为空指针最安全
   Interaction();
 
   int operate;
   while(cin>>operate)
    {
       switch(operate)
       {
       case 0:
           goto END;
 
       case 1:
           InitPoly(P1);
           cout<<"请输入要创建的一元多项式的项数:";
           int polysize;
           cin>>polysize;
           CreatPoly(P1,polysize);
           break;
 
        case 2:
           Output(P1);
           break;
 
       case 3:
           cout<<"该一元多项式的项数为:"<<PolyLength(P1)<<endl;
           break;
 
       case 4:
           if(!IsEmptyPoly(P1))
           {
                cout<<"该一元多项式不为空。\n";
           }
           else
           {
                cout<<"该一元多项式为空。\n";
           }
           break;
 
       case 5:
           InitPoly(P2);
           cout<<"请输入要创建的一元多项式的项数:";
           cin>>polysize;
           CreatPoly(P2,polysize);
 
           AddPoly(P1,P2);
           break;
 
       case 6:
           InitPoly(P2);
           cout<<"请输入要创建的一元多项式的项数:";
           cin>>polysize;
           CreatPoly(P2,polysize);
 
           SubtractPoly(P1,P2);
           break;
 
       case 7:
           InitPoly(P2);
           cout<<"请输入要创建的一元多项式的项数:";
           cin>>polysize;
           CreatPoly(P2,polysize);
 
           MultiplyPoly(P1,P2);
           break;
 
       case 8:
           DestroyPoly(P1);
           cout<<"销毁一元多项式成功。进行其他操作请先创建一元多项式。\n";
           break;
 
       default:
           cout<<"请输入正确的操作数!\n";
           break;
       }
    }
 
END:
   DestroyPoly(P1);
   DestroyPoly(P2);
 
   return 0;
}
 
void InitPoly(Polynome &P)//初始化头结点
{
   P=(Polynome)malloc(sizeof(LNode));
   P->next=NULL;
   P->data.coef=0.0;//头结点的系数为0,后续所有结点的系数均不为0,
   P->data.expo=-INF;//头结点的指数为负无穷,便于实现按照指数升序排列
   cout<<"头结点初始化成功。\n";
}
 
void FindPoly(Polynome P,Polynome&before,Polynome &after,int expo)//建立一元多项式的辅助函数
//参数说明:
//P是已经存在的一元多项式的头结点指针;before是满足指数小于将要插入结点指数的第一个结点指针
//after是满足指数大于等于将要插入结点指数的第一个结点指针;expo是将要插入的结点指数
//注意:before与after指针必须引用传值,达到修改CreatPoly()函数中指针的目的,且after=before->next
{
   //分类讨论:
   if(!IsEmptyPoly(P))//一元多项式已经存在项
    {
       before=P;
       after=P->next;
 
       while(1)
       {
           if(before->data.expo<expo&&(after==NULL||(after&&after->data.expo>=expo)))
                //after指针为空(说明要插在当前一元多项式的最后面)或者不为空且满足大小条件
           {
                return;
           }
 
           if(after)//after指针不为空,向后更新指针
           {
                before=after;
                after=after->next;
           }
       }
    }
   //一元多项式为空:
   before=P;
   after=NULL;
}
 
void CreatPoly(Polynome P,int polysize)
{
   cout<<"请输入"<<polysize<<"组数据,每组数据第一个数字是系数(任意非零实数),第二个数字是指数(任意整数),数字之间用空格间隔:\n";
   for(int i=1; i<=polysize; i++)
    {
       double coef;
       int expo;
       cin>>coef>>expo;
 
       if(coef)//系数为0的项不用建立
       {
           Polynome before,after;
           FindPoly(P,before,after,expo);//找到合适位置
 
           if(after&&after->data.expo==expo)
           //若将要插入的项的指数已经存在,那么无需开辟新内存,只需要修改存在项的系数
           {
               after->data.coef=after->data.coef+coef;
 
                if(after->data.coef==0)//修改后若系数为0,即该项消失,那么释放存在项的内存
                {
                   before->next=after->next;//删除该结点,改变指针链接
                    free(after);
                }
           }
           else//若将要插入的项的指数不存在,那么需开辟新内存,创建新结点
           {
                Polynomeq=(Polynome)malloc(sizeof(LNode));
                q->data.coef=coef;
                q->data.expo=expo;
                before->next=q;//更新指针
                q->next=after;
           }
       }
    }
 
   cout<<"您创建的多项式为(合并同类项后):\n";
   Output(P);
}
 
void Output(Polynome P)//输出一元多项式
{
   if(!IsEmptyPoly(P))
    {
       cout<<"P(x)=";
       Polynome q=P->next;
       int kase=0;//控制一行输出的项数和开头‘+’号的输出
 
       while(q)
       {
           if(kase!=0)//不为第一项,前面填上‘+’号
           {
                cout<<"+";
           }
 
           if(q->data.coef>0)//系数大于0
           {
                if(q->data.coef!=1||(q->data.coef==1&&q->data.expo==0))//不为1的正系数或者为1的常数才输出系数
                {
                   cout<<"("<<q->data.coef<<")";
                }
           }
           else//系数小于0直接输出系数
           {
               cout<<"("<<q->data.coef<<")";
           }
 
           if(q->data.expo)//指数不为0才输出x
           {
                cout<<"x";
                if(q->data.expo!=1)//指数为1不输出
                {
                   cout<<"^("<<q->data.expo<<")";
                }
           }
           kase++;//输出项+1
 
           q=q->next;//更新指针
 
           if(kase%10==0)//每行输出10项
           {
                cout<<endl;
           }
       }
       cout<<endl;
       return;
    }
   cout<<"多项式为空,无法输出。请先创建多项式。\n";
}
 
int PolyLength(Polynome P)//求一元多项式的项数
{
   int num=0;
   if(!IsEmptyPoly(P))
    {
       P=P->next;
       while(P)
       {
           num++;
            P=P->next;
       }
    }
   return num;
}
 
Status IsEmptyPoly(Polynome P)//判断一元多项式是否为空
{
   if(P&&P->next)
    {
       return FALSE;
    }
   return OK;
}
 
void AddPoly(Polynome P1,Polynome&P2)//一元多项式相加,将结果赋给多项式P1
{
   if(!IsEmptyPoly(P1)&&!IsEmptyPoly(P2))//两个多项式均不为空
    {
       Polynome p1,p2,q,r;
       p1=P1->next,p2=P2->next;//两个用来遍历的指针
       q=P1;//相加后的多项式的头结点
 
       while(p1&&p2)
       {
           if(p1->data.expo<p2->data.expo)//连接到P1链本身的节点
           {
                r=p1->next;
                //预存将要访问的节点指针,因为q是P1上的指针,省去该语句后,
                //语句:q->next=p1;q=p1可能会修改p1原来的指向,导致错误
                q->next=p1;
                q=p1;//更新指针
                p1=r;
           }
           else if(p1->data.expo==p2->data.expo)//系数相加后连接到P1链本身的节点
           {
                r=p1->next;
               p1->data.coef=p1->data.coef+p2->data.coef;
                if(p1->data.coef==0)//合并项后消失,释放内存
                {
                    free(p1);
                }
                else
                {
                    q->next=p1;
                    q=p1;
                }
 
                p1=r;//更新指针
                r=p2->next;
                free(p2);//该结点相加后的多项式中用不到,所以释放其内存
                p2=r;
           }
           else//连接到P2链的节点
           {
                r=p2->next;
                q->next=p2;
                q=p2;//更新指针
                p2=r;
           }
       }
       q->next= p1==NULL?p2:p1;//链接到有剩余项的链的剩余的第一个指针即可完成运算
 
       cout<<"相加后的一元多项式为:\n";
       Output(P1);
//DestroyPoly(P2);语句不能加,因为P2链的许多结点链接到了新链中,只需要释放P2链中与P1链指数相同的节点和P2的头结点
       free(P2);
       P2=NULL;
       return;
    }
   cout<<"一元多项式为空,无法操作。\n";
}
 
void SubtractPoly(Polynome P1,Polynome&P2)//一元多项式相减,将结果赋给P1
{
   if(!IsEmptyPoly(P1)&&!IsEmptyPoly(P2))//两个多项式均不为空
    {
       Polynome p1,p2,q,r;
       p1=P1->next,p2=P2->next;//两个用来遍历的指针
       q=P1;//相加后的多项式的头结点
 
       while(p1&&p2)
       {
           if(p1->data.expo<p2->data.expo)//连接到P1链本身的节点
           {
                r=p1->next;
                //预存将要访问的节点指针,因为q是P1上的指针,省去该语句后,
                //语句:q->next=p1;q=p1可能会修改p1原来的指向,导致错误
                q->next=p1;
                q=p1;//更新指针
                p1=r;
           }
           else if(p1->data.expo==p2->data.expo)//系数相加后连接到P1链本身的节点
           {
                r=p1->next;
               p1->data.coef=p1->data.coef-p2->data.coef;
                if(p1->data.coef==0)//合并项后消失,释放内存
                {
                    free(p1);
                }
                else
                {
                    q->next=p1;
                    q=p1;
                }
 
                p1=r;//更新指针
                r=p2->next;
                free(p2);//该结点相加后的多项式中用不到,所以释放其内存
                p2=r;
           }
           else//连接到P2链的节点
           {
               p2->data.coef=-p2->data.coef;//第二个多项式的项的系数变号(被减的)
                r=p2->next;
                q->next=p2;
                q=p2;//更新指针
                p2=r;
           }
       }
       q->next= p1==NULL?p2:p1;//链接到有剩余项的链的剩余的第一个指针即可完成运算
 
       cout<<"相减后的一元多项式为:\n";
       Output(P1);
//DestroyPoly(P2);语句不能加,因为P2链的许多结点链接到了新链中,只需要释放P2链中与P1链指数相同的节点和P2的头结点
       free(P2);
       P2=NULL;
       return;
    }
   cout<<"一元多项式为空,无法操作。\n";
}
 
void MultiplyPoly(Polynome &P1,Polynome&P2)//一元多项式相乘,将结果赋给P1
{
   if(!IsEmptyPoly(P1)&&!IsEmptyPoly(P2))
    {
       Polynome p1=P1->next,p2=P2->next;
       Polynome P;//开辟一条新链,最后将P1的头结点指向新链
       InitPoly(P);//初始化新链的头结点
 
       //双重循环:依次用第一个多项式的每一项乘以第二个多项式的每一项,将结果项的系数和指数存起来
       //视为“输入的”,采取创建一元多项式的思路,将每一组数据插入到新链中
       while(p1)
       {
           p2=P2->next;
           while(p2)
           {
                doublecoef=(p1->data.coef)*(p2->data.coef);//结果项的系数
                intexpo=p1->data.expo+p2->data.expo;//结果项的指数
                //以下同CreatPoly函数
                if(coef)//系数为0的项不用建立
                {
                    Polynome before,after;
                   FindPoly(P,before,after,expo);//找到合适位置
                   if(after&&after->data.expo==expo)
                    //若将要插入的项的指数已经存在,那么无需开辟新内存,只需要修改存在项的系数
                    {
                       after->data.coef=after->data.coef+coef;
 
                       if(after->data.coef==0)//修改后若系数为0,即该项消失,那么释放存在项的内存
                        {
                           before->next=after->next;//删除该结点,改变指针链接
                            free(after);
                        }
                    }
                    else//若将要插入的项的指数不存在,那么需开辟新内存,创建新结点
                    {
                        Polynomeq=(Polynome)malloc(sizeof(LNode));
                       q->data.coef=coef;
                        q->data.expo=expo;
                        before->next=q;//更新指针
                        q->next=after;
                    }
                }
                p2=p2->next;//后移指针
           }
           p1=p1->next;//后移指针
       }
 
       DestroyPoly(P1);//销毁两个原来的多项式
       DestroyPoly(P2);
 
       P1=P;//将结果赋给P1链
       cout<<"相乘后的一元多项式为:\n";
       Output(P1);
       return;
    }
   cout<<"一元多项式为空,无法操作。\n";
}
 
void DestroyPoly(Polynome &P)//销毁多项式
{
   while(P)
    {
       Polynome q=P->next;
       free(P);
       P=q;
    }
   P=NULL;
}
 
void Interaction()
{
   cout<<"请输入对应操作的序号:\n";
   cout<<"0:退出程序;\n";
   cout<<"1:建立一元多项式;\n";
   cout<<"2:打印一元多项式;\n";
   cout<<"3:输出一元多项式的项数;\n";
   cout<<"4:判断一元多项式是否为空;\n";
   cout<<"5:一元多项式求和;\n";
   cout<<"6:一元多项式求差;\n";
   cout<<"7:一元多项式求积;\n";
   cout<<"8:销毁一元多项式;\n";
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值