合肥学院
计算机科学与技术系
课程设计报告
2009 ~2010 学年第 2 学期
课程数据结构与算法
课程设计名称一元多项式的计算问题
学生姓名周维
学号0804012040
专业班级08计科(2)
指导教师王昆仑教授
2010年6月
题目:(一元多项式的计算问题)要求能够按照指数降序排列建立并输出一元多项式;能够完成两个一元多项式的相加、相减,并将结果输入。
一、问题分析和任务定义
1.问题分析
本程序关键点是如何将输入的两个多项式相加、相减操作。
①如何将输入的一元多项式按指数的降序排列
②如何确定要输入的多项式的项数;
③如何将输入的两个一元多项式显示出来。
④如何将输入的两个一元多项式进行相加操作。
⑤如何将输入的两个一元多项式进行相减操作。
本程序是通过链表实现一元多项式的相加减操作。
2、任务定义
此程序需要完成如下的要求:将多项式按照指数降序排列建立并输出,将两个一元多项式进行相加、相减操作,并将结果输入。
a:输入多项式的项数并建立多项式;
b:输出多项式,输出形式分别为浮点和整数序列,序列按指数升序排列;
c:多项式a和b相加,建立多项式a+b;
d:多项式a和b相减,建立多项式a-b。
e:多项式的输出。
二、数据结构的选择和概要设计:
(1)数据结构的选用
A:基于链表中的节点可以动态生成的特点,以及链表可以灵活的添加或删除节点的数据结构,为了实现任意多项式的加法,减法,因此选择单链表的结构体,它有一个系数,指数,下一个指针3个元属;例如,图1中的两个线性链表分别表示一元多项式
和一元多项式。从图中可见,每个结点表示多项式中的一项。
图1 多项式表的单链存储结构
B:本设计使用了以下数据结构:
t ypedef struct {
float coef; //系数
int expn; //指数
} ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode;
C:设计本程序需用到九个模块,用到以下九个子函数如下:
1、void Menu()//建立菜单
2、LNode *InitList() // 创建链表
3、void ChaLNode(LNode *L,ElemType x)//插入链表
4、LNode *AddPolyn(LNode *A,LNode *B)//多项式相加
5、void Invert(LNode *L)//逆序输出链表
6、void Print(LNode *L)//输出多项式
7、main()//主程序模块调用链一元多项式的各种基本操作模块。
(2)多项式的输入
先输入多项式的项数,采用尾插法的方式,输入多项式中一个项的系数和指数,就产生一个新的节点,建立起它的右指针,并用头节点指向它;
(3)两个多项式的加法
“和多项式”链表中的结点无需另生成,而应该从两个多项式的链表中摘取。其运算规则如下:
假设指针A和B分别指向多项式a和多项式b中当前进行比较的某个结点,则比较两个结点中的指数项,有下列3种情况:
①指针A所指结点的指数值<指针B所指结点的指数值,则应摘取A指针所指结点插入到“和多项式”链表中去;
②指针A所指结点的指数值>指针B所指结点的指数值,则应摘取指针A所指结点插入到“和多项式”链表中去;
③指针A所指结点的指数值=指针B所指结点的指数值,则将两个结点中的系数相加,若和数不为零,则修改A所指结点的系数值,同时释放B所指结点;反之,从多项式A的链表中删除相应结点,并释放指针A和B所指结点。例如,由图2中的两个链表表示的多项式相加得到的“和多项式”链表如图2所示,图中的长方框表示已被释放的结点。
图2 相加得到的和多项式
上述多项式的相加过程归并两个有序表的过程极其类似,不同之处仅在于,后者在比较数据元素时只出现两种情况。因此,多项式相加的过程也完全可以利用线性链表的基本操作来完成。
(4)两个多项式的减法
两个多项式的减法实现,依然调用的是多项式加法的函数,只是在调用前,把多项式二的系数全部变为相反数c.coef=-c.coef;,然后多项式一和多项式二相加,这样就实现了多项式的相减。流程图如上。
(5)流程图
(1)在主函数中调用函数进行多项式的输入、输出,运用选择语句来选择加法、减法进行操作,流程图如图3:
图3 主函数流程图
(2)两个多项式相加就是两个多项式中同指数项的对应系数相加,若和不为零,则形成“和多形式”中的一项,所有指数不同的项均直接移位至“和多项式”中,流程图如图4:
图4 两个一元多项式相加
三、详细设计和编码
1、算法思想
(1)输入并建立多项式——InitList()
(2)输入多项式,输出形式为整数序列,这个输入功能在主函数实现
(3)多项式a和b相加,建立多项式a+b,输出相加的多项式——AddPolyn(A,B) (4)多项式a和b相减,建立多项式a-b,相减的功能调用的依然是相加的子函数
2、算法描述:
A:建立多项式链表
多项式单链表可以用尾插法建表来生成。通过从键盘按升幂的次序输入多项式各项的系数和指数
LNode *InitList()//创建链表
{
LNode *L;
L=(LNode*)malloc(sizeof(LNode));
L->next=NULL;
return(L);
}
void ChaLNode(LNode *L,ElemType x)//插入链表函数
{
LNode *s,*p;
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
p=L;
while(p->next)
p=p->next;
s->next=NULL;
p->next=s;
}
B:按照指数降序排列
void Invert(LNode *L)//逆序输出链表
{LNode *p,*q,*r;
p=L->next;
q=p->next;
while(q!=NULL)
{r=q->next;
q->next=p;
p=q;
q=r;
}
L->next->next=NULL;
L->next=p;
}
C:比较
if (a->expn < b->expn){pre=p;
p=p->next;}//如果多项式a的指数小于多项式b的指数,则指针P后移
if (a->expn > b->expn){
pre->next=q;
pre=pre->next;
q=q->next;}//如果多项式a的指数小于多项式b的指数,q后移
这个模块主要是比较两个多项式的指数大小
D、两个一元多项式的相加
while(p&&q)//判断q,p是不是为空,如果不为空则继续往下进行
{
a=p->data.expn;b=q->data.expn;
if(a
{
pre=p;p=p->next;//p后移
}
if(a==b)
{
sum=p->data.coef+q->data.coef;//当a,b相等,即指数相同,则系数相加
if(sum!=0)//判断sum是为0,如果不为0则保留该节点
{
p->data.coef=sum; B=q;
pre=p; p=p->next;
q=q->next;free(B);
}
Else //如果sum为0即系数为0,则删除该节点
{
temp=p;p=p->next;
pre->next=p;free(temp);
B=q;q=q->next;free(B);
}
}
if(a>b)
{
pre->next=q; pre=pre->next;
q=q->next; }}
if(q) //如果q中还有剩余,那么把q中剩余的项加到pre->next中
pre->next=q;
return(A);
}
两个一元多项式相加的法则是:两个多项式中同指数项的对应系数相加,若和不为零,则
形成“和多项式”中的一项;所有指数不同的项均直接移位至“和多项式”中。如果和为零,则删除该节点。
E:输出一个一元多项式
void Print(LNode *L)//输出多项式
{
LNode *p;
p=L->next;
while(p->next)
{
printf("(%fx^%d)+",p->data.coef,p->data.expn);
p=p->next;
}
printf("(%fx^%d)",p->data.coef,p->data.expn);输出最后一项
}
F:一元多项式相减
两个多项式的减法实现,并没有单独的建立一个子函数来实现这个功能,和多项式的相加一样,依然调用的是多项式加法的函数,只是在调用前,把多项式二的系数全部变为相反数c.coef=-c.coef;,然后多项式一和多项式二相加,这样就实现了多项式的相减,开始我建立一个实现多项式减法的子函数,最后为了程序的简洁最后还是改成了调用多项式相加函数
G:逆序输出链表的实现
void Invert(LNode *L)//逆序输出链表
{LNode *p,*q,*r;
p=L->next;
q=p->next;
while(q!=NULL)
{r=q->next;
q->next=p;
p=q;
q=r;
}
L->next->next=NULL;
L->next=p;
}
H、main()主函数
void main()
{LNode *La,*Lb;ElemType c; int a,i,k;
for(;1;){
La=InitList(); Lb= InitList();
Menu();
printf("请选择功能:");scanf("%d",&k);printf("\n");
switch(k){
case 1 :
printf("\t\t===========一元多项式相加===========\t\t");
printf("\n\n\n输入多项式一的项数:");
scanf("%d",&a);
if(a<=0){
printf("a不能小于1!\n");
printf("请从新输入多项式一的项数:");
scanf("%d",&a);
} for(i=0;i { printf("输入多项式一第%d项系数和指数:",i+1); scanf("%f%d",&c.coef,&c.expn); ChaLNode(La,c); } printf("输入多项式二的项数:"); scanf("%d",&a); if(a<=0){ printf("a不能小于1!\n"); printf("请从新输入多项式一的项数:"); scanf("%d",&a); } for(i=0;i { printf("输入多项式二第%d项系数和指数:",i+1); scanf("%f%d",&c.coef,&c.expn); ChaLNode(Lb,c); } printf("多项式一为:");Print(La);printf("\n"); printf("多项式二为:"); Print(Lb);printf("\n"); printf("多项式和为:");AddPolyn(La,Lb); Invert(La);Print(La);printf("\n");break; case 2: printf("\t\t===========一元多项式相减===========\t\t"); printf("\n\n\n输入多项式一的项数:"); scanf("%d",&a); if(a<=0){ printf("a不能小于1!\n"); printf("请从新输入多项式一的项数:"); scanf("%d",&a);} for(i=0;i { printf("输入多项式一第%d项系数和指数:",i+1); scanf("%f%d",&c.coef,&c.expn); ChaLNode(La,c); } printf("输入多项式二的项数:"); scanf("%d",&a); if(a<=0){ printf("a不能小于1!\n"); printf("请从新输入多项式一的项数:"); scanf("%d",&a); } for(i=0;i { printf("输入多项式二第%d项系数和指数:",i+1); scanf("%f%d",&c.coef,&c.expn); c.coef=-c.coef;ChaLNode(Lb,c); } printf("多项式一为:"); Print(La);printf("\n"); printf("多项式二为:"); Print(Lb);printf("\n"); printf("多项式差为:"); AddPolyn(La,Lb);Invert(La); Print(La);printf("\n");break; case 0: break;} if(k==0)break; printf("\n\n\n");}} 在主函数中调用函数进行多项式的输入、输出,运用选择语句来选择加法、减法进行操作四:上机调试 调试中遇到的问题与解决办法 1、语法错误及修改,编译中出现的语法问题主要在于子函数和变量的定义,括号的配对,关键字和函数名的书写,以及库函数的规范使用,这些问题都可以通过提示,对应的将其解决 2、我通过调试运行后发现,计算完成打印结果后马上就会退出。程序在运行起来以后,没有一个可以让程序暂时停止的地方,比如要求用户输入,或者什么的,程序顺序执行之后就退出了。 3、运行成功后,但是到最后输出结果的时候总是出现错误。通过对算法的分析发现,算法不正确,修改后最终完成了程序的调试。 五:设计体会 在开始看到程序题目的时候以为一元多项式的加减会很简单,可是在课程设计的过程中发现编写程序并不是开始想象的那样简单,在这过程中遇到了难题,比如如何逆序输出链表,经过认真思考和查相关的资料最后解决了这个问题,通过这次课程设计,我感觉到要真正做出一个程序并不很容易,但只要用心去做,总会有收获,特别是当我遇到一个问题,想办法去解决,最后终于找到方法时,心里的那份喜悦之情真是难以形容。编写程序中遇到问题再所难免,应耐心探究其中的原因,从出现问题的地方起,并联系前后程序,仔细推敲,逐个排查。直到最终搞清为止。 六、测试结果及其分析 如图6:一元多项式相加输入的项数小于1时出现的结果,运行结果如下: 图6一元多项式相加结果 如图7:一元多项式减法运行结果如下: 图7 一元多项式减法运行结果 如图8:当选择0时退出如图: 图8:当输入有错误时的情况 七、用户使用说明 根据提示选择多项式的加法还是减法1。相加2相减0.退出,比如选1,然后再根据提示输入一个一元多项式的项数。按enter键,按照指数递升的顺序依次输入非零项,例如4个非零项,要输入8个数,有4个指数,4个系数。按enter键,然后就会自动输出刚才输入的两个多项式及相加后的结果,然后还可以继续选择运算。如果退出选择0. 八、参考文献 [1] 王昆仑等编著《数据结构与算法》中国铁道出版社2007年6月第1版 [2] 郑莉等编著的《C++语言程序设计》(第3版) [3] 谭浩强著《C程序设计》北京:清华大学出版社2005年7月第三版 附录: 源程序 #include "stdio.h" #include"malloc.h" typedef struct { float coef; int expn; }ElemType; typedef struct LNode { ElemType data; struct LNode *next; }LNode; void Menu() { printf(" →→→→→\n"); printf(" ↑菜单↓\n"); printf(" ←←←←←\n"); printf(" ★◆★◆★◆★◆★◆★◆★◆★◆★◆★◆★◆★◆★◆★◆\n"); printf(" ◆★\n"); printf(" ★◆\n"); printf(" ◆****************一元多项式的运算****************★\n"); printf(" ★++++++++++◆\n"); printf(" ★+++++请选择功能键+++++◆\n"); printf(" ◆++++++★\n"); printf(" ★+ +◆\n"); printf(" ◆1===============一元多项式相加================ ★\n"); printf(" ◆★\n"); printf(" ★2===============一元多项式相减================◆\n"); printf(" ◆★\n"); printf(" ★0=====================退出==================== ◆\n"); printf(" ◆★\n"); printf(" ★**********************************************◆\n\n\n"); } LNode *InitList()//创建链表 { LNode *L; L=(LNode*)malloc(sizeof(LNode)); L->next=NULL; return(L); } void ChaLNode(LNode *L,ElemType x)//插入链表函数 { LNode *s,*p; s=(LNode*)malloc(sizeof(LNode)); s->data=x; p=L; while(p->next) p=p->next; s->next=NULL; p->next=s; } LNode *AddPolyn(LNode *A,LNode *B)//多项式相加{ LNode *p,*q,*temp,*pre; float sum;int a,b; p=A->next; q=B->next; pre=A; free(B); while(p&&q) { a=p->data.expn;b=q->data.expn; if(a { pre=p; p=p->next; } if(a==b) { sum=p->data.coef+q->data.coef; if(sum!=0) { p->data.coef=sum; B=q; pre=p; p=p->next; q=q->next; free(B); } else { temp=p; p=p->next; pre->next=p; free(temp); B=q; q=q->next; free(B); } } if(a>b) { pre->next=q; pre=pre->next; q=q->next; } } if(q) pre->next=q; return(A); } void Invert(LNode *L)//逆序输出链表 {LNode *p,*q,*r; p=L->next; q=p->next; while(q!=NULL) {r=q->next; q->next=p; p=q; q=r; } L->next->next=NULL; L->next=p; } void Print(LNode *L)//输出多项式 { LNode *p; p=L->next; while(p->next) { printf("(%fx^%d)+",p->data.coef,p->data.expn); p=p->next; } printf("(%fx^%d)",p->data.coef,p->data.expn); } void main() { LNode *La,*Lb;ElemType c; int a,i,k; for(;1;){ La=InitList(); Lb= InitList(); Menu(); printf("请选择功能:"); scanf("%d",&k); printf("\n"); switch(k){ case 1 : printf("\t\t===========一元多项式相加===========\t\t"); printf("\n\n\n输入多项式一的项数:"); scanf("%d",&a); if(a<=0){ printf("a不能小于1!\n"); printf("请从新输入多项式一的项数:"); scanf("%d",&a); } for(i=0;i { printf("输入多项式一第%d项系数和指数:",i+1); scanf("%f%d",&c.coef,&c.expn); ChaLNode(La,c); } printf("输入多项式二的项数:"); scanf("%d",&a); if(a<=0){ printf("a不能小于1!\n"); printf("请从新输入多项式一的项数:"); scanf("%d",&a); } for(i=0;i printf("输入多项式二第%d项系数和指数:",i+1); scanf("%f%d",&c.coef,&c.expn); ChaLNode(Lb,c); } printf("多项式一为:"); Print(La);printf("\n"); printf("多项式二为:"); Print(Lb);printf("\n"); printf("多项式和为:"); AddPolyn(La,Lb); Invert(La); Print(La); printf("\n");break; case 2: printf("\t\t===========一元多项式相减===========\t\t"); printf("\n\n\n输入多项式一的项数:"); scanf("%d",&a); if(a<=0){ printf("a不能小于1!\n"); printf("请从新输入多项式一的项数:"); scanf("%d",&a);}