题目:设计一个一元稀疏多项式简单计算器
一、需求分析
1.首先需要判断是加运算还是减运算,然后输入并建立多项式,输入时各项顺序不限,程序可自动排序。
2.输出多项式, 本程序将采用类数学表达式的输出形式,例如项x7的输出形式为x^7.且系数值为1的非零次项的输出形式中略去系数1,如项1x8的输出形式为 x8, 项-1x3的输出形式为-x3,序列按指数降序排列。
3.多项式a和b相加,建立多项式a+b。
4.多项式a和b相减, 建立多项式a-b。
5. 本程序以用户和计算机的对话形式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入程序中规定的运算命令来决定相关运算。
6. 程序执行的命令包括:
1)输入0、1判断加减运算;2)输入多项式的项数;3)输入多项式的系数和指数.
7. 测试数据
(1)(2x + 5x8 - 3.1x11)+ (7 - 5x8 + 11x9);
(2) (6x-3 – x + 4.4 x2 - 1.2x9) - (-6x-3+5.4x2 –x2 + 7.8x15);
(3) (1 +x + x2 + x3 + x4 + x5) + (-x3- x4);
(4) (x +x3) + (-x - x3);
(5) (x +x100) + (x100+x200);
(6) (x +x2 + x3) + 0。
二、概要设计
为实现上述程序功能,用带表头结点的单链表存储多项式。
1)抽象数据类型一元多项式的定义如下:
ADT Polynomial {
数据对象:D = {ai | ai ∈ LNode, i = 1, 2,……, m, m>=0
LNode中的每个结点包含两个数据域和一个指针域,数据域分别为表示系数的实数和表示指数的整数,指针域指向下一个结点}
数据关系:R1 = {<ai-1 , ai> | ai-1 , ai∈ D, 且ai-1中的指数值> ai 中的指数值,i=2,…, n}
基本操作:
CreatPolyn(Polynomial &P,int m)
操作结果:输入m项的系数和指数,建立一元多项式P。
AddPolyn(Polynomial &Pa,Polynomial&Pb)
初始条件:一元多项式Pa和Pb已存在
操作结果:完成多项式相加运算,即:Pa= Pa + Pb,并销毁一元多项式Pb。
MinusPolyn(Polynomial &Pa,Polynomial&Pb)
初始条件:一元多项式Pa和Pb已存在
操作结果:完成多项式相加运算,即:Pa= Pa - Pb,并销毁一元多项式Pb。
}ADT Polynomial
2)本程序包含四个模块:
1.主程序模块——输入数据的实现,格式的控制输出;
2.创建多项式模块——实现多项式的创建;
3.加运算模块——实现两个多项式的加运算;
4.减运算模块——实现两个多项式的减运算。
各模块之间的调用关系如下:
主程序模块
创建多项式模块
加运算模块 减运算模块
三、详细设计
1.结点类型和指针类型
typedef struct LNode{
int expn; //指数
floatcoef; //系数
struct LNode*next;
}LNode, *Polynomial;
2.根据单链表的基本操作特点,使用带头结点的单链表存储多项式
void CreatPolyn(Polynomial &P,int m)
{
//输入m项的系数和指数,建立表示一个多项式的有序链表P
LNode*q,*pre,*s;
int i;
P=new LNode;
P->next=NULL; //先建立一个带头结点的单链表
for(i=1;i<=m;i++) //依次输入m个非零项
{
s=new LNode; //生成新结点
cin>>s->coef>>s->expn; //输入元素值
if(s->coef!= 0){
pre=P; //pre用于保存q的前驱,初值为头结点
q=P->next;
while(q&& q->expn > s->expn) //通过比较指数找到第一个小于或等于输入项指数的项q
{
pre=q;
q=q->next;
}
if(q&& q->expn == s->expn){
//如果输入元素和链表中已有的元素指数相等,则合并,否则,插入到它的前面
q->coef= q->coef + s->coef;
deletes;
}
else{
s->next=q;
pre->next=s;
}
}
}
} //CreatPolyn
void AddPolyn(Polynomial &Pa,Polynomial &Pb) {
//多项式加法:Pa=Pa+Pb,利用两个多项式的结点构成“和多项式”
LNode*r,*p1,*p2,*p3;
float sum;
p1=Pa->next;p2=Pb->next; //p1和p2初值分别指向Pa和Pb的第一个结点
p3=Pa; //p3指向和多项式的当前结点,初值为Pa
while(p1&& p2) //p1和p2均非空
{
if(p1->expn== p2->expn) //指数相等
{
sum=p1->coef+p2->coef; //sum保存两项的系数和
if(sum!=0) //系数和不为0
{
p1->coef=sum; //修改Pa当前结点p1的系数值为两项系数的和
p3->next=p1;p3=p1; //将修改后的Pa当前结点p1链在p3之后,p3指向p1
r=p2;p2=p2->next;deleter; //删除Pb当前结点r
p1=p1->next; //p1指向后一项
}
else //系数和为0
{
r=p1;p1=p1->next;deleter; //删除Pb当前结点p1
r=p2;p2=p2->next;deleter; //删除Pb当前结点p2
}
}
elseif(p1->expn > p2->expn) //Pa指数大
{
p3->next=p1; //将p1链在p3之后
p3=p1; //p3指向p1
p1=p1->next; //p1指向后一项
}
else //Pb指数大
{
p3->next=p2; //将p2链在p3之后
p3=p2; //p3指向p2
p2=p2->next; //p2指向后一项
}
}
p3->next=p1?p1:p2; //插入非空多项式的剩余段
delete Pb; //释放Pb的头结点
} //AddPolyn
void MinusPolyn(Polynomial &Pa,Polynomial &Pb) {
//多项式加法:Pa=Pa+Pb,利用两个多项式的结点构成“和多项式”
LNode*r,*p1,*p2,*p3;
float sum;
p1=Pa->next;p2=Pb->next; //p1和p2初值分别指向Pa和Pb的第一个结点
p3=Pa; //p3指向和多项式的当前结点,初值为Pa
while(p1&& p2) //p1和p2均非空
{
if(p1->expn== p2->expn) //指数相等
{
sum=p1->coef - p2->coef; //sum保存两项的系数差
if(sum!= 0) //系数和不为0
{
p1->coef=sum; //修改Pa当前结点p1的系数值为两项系数的差
p3->next=p1;p3=p1; //将修改后的Pa当前结点p1链在p3之后,p3指向p1
r=p2;p2=p2->next;deleter; //删除Pb当前结点r
p1=p1->next; //p1指向后一项
}
else //系数和为0
{
r=p1;p1=p1->next;deleter; //删除Pb当前结点p1
r=p2;p2=p2->next;deleter; //删除Pb当前结点p2
}
}
elseif(p1->expn > p2->expn) //Pa指数大
{
p3->next=p1; //将p1链在p3之后
p3=p1; //p3指向p1
p1=p1->next; //p1指向后一项
}
else //Pb指数大
{
p2->coef=-p2->coef;
p3->next=p2; //将p2链在p3之后
p3=p2; //p3指向p2
p2=p2->next; //p2指向后一项
}
}
p3->next=p1?p1:p2; //插入非空多项式的剩余段
delete Pb; //释放Pb的头结点
}
int main()
{//将输入项s插入到q和其前驱结点pre之间
PolynomialPa,Pb;
LNode *p;
inttemp,i,flag;
//判断是相加还是相减
cout<<"加运算请输1,减运算请输0: ";
cin>>flag;
//创建多项式Pa
cout<<"请输入多项式Pa的项数:";
cin>>temp; //输入多项式Pa的个数
cout<<"请输入多项式Pa的系数和指数,中间用一个空格隔开,一个项一行:\n";
CreatPolyn(Pa,temp); //调用函数,输入Pa每一项的系数和指数
//创建多项式Pb
cout<<"请输入多项式Pb的项数:";
cin>>temp; //输入多项式Pa的个数
cout<<"请输入多项式Pb的系数和指数,中间用一个空格隔开,一个项一行:\n";
CreatPolyn(Pb,temp); //调用函数,输入Pa每一项的系数和指数
if(flag)
AddPolyn(Pa,Pb);
else
MinusPolyn(Pa,Pb);
cout<<"多项式Pa和Pb相加后的结果是:\n";
p=Pa->next;
if(p == NULL)
cout<<0;
i=0;
while(p) //输出相加后的结果,每一项以x^n表示
{
if(i&& p->coef > 0)
cout<<"+";
if((p->coef == 1)&&p->expn != 0)
cout<< "x^" << p->expn;
elseif((p->coef == -1)&&p->expn != 0)
cout<< "-x^" << p->expn;
elseif(p->expn == 0)
cout<<p->coef;
else
cout<<p->coef<<"x^"<<p->expn;
p=p->next;
i++;
}
cout<<endl;
return 0;
}
四、调试分析
1.刚开始没有考虑到一个多项式中会出现多个相同指数的情况,导致测试数据(2)无法得到正确情况。
2.创建多项式时,加入处理同指数的代码,可是忘记考虑链表初始为空的情况,导致一直出现未知指针运行错误。
3.本程序的模块划分较为合理,模型抽象化合理,建立一个可以包含指数系数的单链表结点。
4.本程序操作简便,思想严密,创建多项式就采用降序比较插入的方法。
5.算法的时空分析
1)本程序采用带头结点的有序单链表,各种操作的算法时间复杂度比较合理。
2)基于单链表的各种运算和操作的时间复杂度如下:
创建多项式算法CreatPolyn读入n个元素,每读入一个元素要和当前已存在链表中的元素比较,确定其插入位置后,才进行后续操作,所以时间复杂度为(n2)。
求多项式的加运算,遍历了两个多项式,将两个多项式的m和n个元素添加到pa多项式中,所以时间复杂度为(m + n ).
求多项式的减运算,同上,时间复杂度为(m+ n)。
五、用户手册
1.本程序的运行环境为windows操作系统,执行文件为:稀疏多项式.cpp。
2.进入演示程序后即显示文本方式的用户界面:
3. 输入相应命令后,进入createPolyn,按提示输入数据,结束符为“回车符”:
4.执行运算,显示相应结果:
六、 测试结果
1)输入 (2x + 5x8 -3.1x11) + (7 - 5x8 + 11x9),输出为-3.1x11 + 11x9+2x +7;
2)输入 (6x -3 – x + 4.4 x2 - 1.2x9) -(-6x-3+ 5.4x2 –x2 + 7.8x15),输出为-7.8x15 - 1.2x9– x +12x-3+;
3)输入 (1 + x + x2 + x3 + x4 + x5)+ (-x3 - x4) ,输出为x5 + x2+ x + 1;
4)输入 (x + x3) + (-x - x3) ,输出为0;
5)输入 (x + x100) + (x100+x200) ,输出为x200 + 2x100+ x;
6)输入 (x + x2 + x3) + 0,输出为x3 + x2 +x.