实习一 线性表及其应用 (题目:一元稀疏多项式的加法运算 )
一、需求分析
1.输入并建立两个多项式;
2.多项式a与b相加,建立和多项式c;
3.输出多项式a,b,c。输出格式:比如多项式a为:A(x)=c1xe1+
c2xe2+…+ cmxem,其中,ci和ei分别为第i项的系数和指数,且各项按
指数的升幂排列,即0≤e1<e2<…<em。多项式b,c类似输出。
4测试数据
(1)(1+x+x2+x3+x4+x5)+(-x3-x4)=(1+x+x2+x5)
(2)(x+x100)+(x100+x200)=(x+2x100+x200)
(3)(2x+5x8-3x11)+(7-5x8+11x9)=(7+2x+11x9-3x11)
#include<stdio.h> #include<malloc.h> #include<stdlib.h> typedef int DaTatype; typedef struct Node { DaTatype xishu; DaTatype zhishu; struct Node *next; }SLNode; void ListInitiate(SLNode **head) //初始化 { *head=(SLNode*)malloc(sizeof(SLNode)); (*head)->next=NULL; } int ListInsert(SLNode *head,DaTatype xishu,DaTatype zhishu)//插入 { SLNode *p,*q; p=head; while(p->next!=NULL) { if((p->next->zhishu)>zhishu)break; //比较指数大小 p=p->next; //链表中节点指数大,则比较链表下一个 } q=(SLNode*)malloc(sizeof(SLNode)); //链表中节点指数小,则在该节点前插入 q->xishu=xishu; q->zhishu=zhishu; q->next=NULL; q->next=p->next; p->next=q; return 1; } int ListGet(SLNode *head) //输出 { SLNode *p; p=head->next; int kaiguan=1; if(p==NULL)printf("0\n"); //判断头结点为空的输出 while(p!=NULL) //判断头结点非空 { if(kaiguan==1) //多项式第一项的输出 { if(p->zhishu==0) //当指数为时,只输出系数xishu printf("%d",p->xishu); else if(p->xishu==1) //系数为1时输出X^zhishui或x {if(p->zhishu==1)printf("x"); else printf("x^%d",p->zhishu); } else if(p->xishu==-1) //系数为-1时输出-X^zhishui或-x {if(p->zhishu==1)printf("-x"); else printf("-x^%d",p->zhishu); } else if(p->xishu>0) //系数大于0时 {if(p->zhishu==1)printf("%dx",p->xishu); else printf("%dx^%d",p->xishu,p->zhishu); } else if(p->xishu<0) //系数为负数时,原样输出 {if(p->zhishu==1)printf("%dx",p->xishu); else printf("%dx^%d",p->xishu,p->zhishu); } kaiguan=0; } else{ //多项式的其余项都前带符号输出 if(p->zhishu==0) {if(p->xishu!=0) printf("+%d",p->xishu); } else if(p->xishu==1) {if(p->zhishu==1)printf("+x"); else printf("+x^%d",p->zhishu); } else if(p->xishu==-1) {if(p->zhishu==1)printf("-x"); else printf("-x^%d",p->zhishu); } else if(p->xishu>0) //系数大于0时,系数前面带“+” {if(p->zhishu==1)printf("+%dx",p->xishu); else printf("+%dx^%d",p->xishu,p->zhishu); } else if(p->xishu<0) //系数为负时,原样输出 {if(p->zhishu==1)printf("%dx",p->xishu); else printf("%dx^%d",p->xishu,p->zhishu); } } p=p->next; } printf("\n"); return 1; } /* while(p->next!=NULL) { while(p->zhishu==0) { printf("%d",p->xishu); p=p->next; if(p==NULL&&p->xishu<0) return 0; else printf("+"); } while(p->xishu==1&&p->zhishu==1) { printf("x"); p=p->next; if(p==NULL&&p->xishu<0) return 0; else printf("+"); } while(p->xishu==1&&p->zhishu!=1) { printf("x^%d",p->zhishu); p=p->next; if(p==NULL&&p->xishu<0) return 0; else printf("+"); } while(p->xishu==-1&&p->zhishu==1)//指数不为零时系数为1时的输出 { printf("-x"); p=p->next; if(p==NULL&&p->xishu<0) return 0; else printf("+"); } while(p->xishu==-1&&p->zhishu!=1)//指数不为零时系数为1时的输出 { printf("-x^%d",p->zhishu); p=p->next; if(p==NULL&&p->xishu<0) return 0; else printf("+"); } while(p->xishu!=1&&p->xishu!=-1&&p->zhishu!=0&&p->zhishu!=1) { printf("%dx^%d",p->xishu,p->zhishu); p=p->next; if(p==NULL&&p->xishu<0) return 0; else printf("+"); } printf("%dx^%d",p->xishu,p->zhishu); p=p->next; if(p->xishu>0) printf("+"); } printf("%dx^%d",p->xishu,p->zhishu);*/ int ListAdd(SLNode*head1,SLNode*head2,SLNode*head3) { SLNode *p,*q,*s,*r; int n=0; p=head1;q=head2;s=head3; while(p->next!=NULL) //先将a存入c中 { r=(SLNode*)malloc(sizeof(SLNode)); r->zhishu=p->next->zhishu; r->xishu=p->next->xishu; r->next=NULL; s->next=r; p=p->next; s=s->next; } s=head3; while(s->next!=NULL &&q->next!=NULL ) { while(s->next!=NULL && s->next->zhishu<q->next->zhishu)//搜寻 { s=s->next; if(s->next!=NULL)n=1; if(n){ if( s->next->zhishu==q->next->zhishu ) { if(s->next->xishu+q->next->xishu!=0) {s->next->xishu=s->next->xishu+q->next->xishu; s=s->next;} else s->next=s->next->next; } else { r=(SLNode*)malloc(sizeof(SLNode)); r->zhishu=q->next->zhishu; r->xishu=q->next->xishu; r->next=s->next; s->next=r; s=s->next; }//插入 q=q->next; n=0; } } if(q->next!=NULL&&s->next==NULL)s->next=q->next; //剩余项的接到C链表的尾部 return 1; } int main() { SLNode *head1,*head2,*head3; int i,n; int xishu,zhishu; ListInitiate(&head1); ListInitiate(&head2); ListInitiate(&head3); printf("请输入a的项数:"); scanf("%d",&n); for(i=0;i<n;i++) { printf("输入a的第%d项系数:",i+1); scanf("%d",&xishu); printf("输入a的第%d项指数:",i+1); scanf("%d",&zhishu); ListInsert(head1,xishu,zhishu); } printf("输入b的项数:"); scanf("%d",&n); for(i=0;i<n;i++) { printf("输入b的第%d项系数:",i+1); scanf("%d",&xishu); printf("输入b的第%d项指数:",i+1); scanf("%d",&zhishu); ListInsert(head2,xishu,zhishu); } ListAdd(head1,head2,head3); printf("输入的多项式a为:\n"); ListGet(head1); printf("\n"); printf("输入的多项式b为:\n"); ListGet(head2); printf("\n"); printf("多项式c为:\n"); ListGet(head3); printf("\n"); return 1; }
实习一 线性表及其应用
题目:一元稀疏多项式的加法运算 实习时间:2012/9/20.10.12
一、需求分析
1.输入并建立两个多项式;
2.多项式a与b相加,建立和多项式c;
3.输出多项式a,b,c。输出格式:比如多项式a为:A(x)=c1xe1+
c2xe2+…+ cmxem,其中,ci和ei分别为第i项的系数和指数,且各项按
指数的升幂排列,即0≤e1<e2<…<em。多项式b,c类似输出。
4测试数据
(1)(1+x+x2+x3+x4+x5)+(-x3-x4)=(1+x+x2+x5)
(2)(x+x100)+(x100+x200)=(x+2x100+x200)
(3)(2x+5x8-3x11)+(7-5x8+11x9)=(7+2x+11x9-3x11)
二、设计
1. 设计思想
(1)存储结构
用带头结点的单链表存储多项式。
三个多项式链表中都只存储非零系数项。若多项式a与b中指数相
等的两项相加后,系数为零,则在和多项式c中不存储该指数项。
(2)主要算法基本思想
按照链表的基本操作,初始化三个链表,在两个链表中按指数由小到大分别插入a和b的多项式(系数和指数),将多项式a的链表复制给多项式c的链表,再调用求和函数(b的链表和c的链表相加),将求和的结果插入到c的链表中(作为多项式c),最后输出多项式a,b,c三个多项式。
【1】插入函数:设计按多项式指数的从小到大插入。从第一个元素开始判断,直到遇到比插入元素更大的指数或链表尾为止,再进行插入操作。
【2】求和函数: 先将多项式a的链表复制给多项式c的链表,在b的链表不为空的前提下,将b中的各项的指数与c中各项的指数比较大小。
(1)若相等,就将该项的系数相加,和不为零就将c中该项的系数替换为其和(何若为零则删除该节点)。
(2)若b中的指数大,就在c链表该节点之前插入b项的此节点。
(3)若b中的指数小,就一直查找到c链表尾。再将多余的b链表一起复制给c链表。
【3】输出函数(系数为0的项已被删除):
多项式第一项若为正数,无需符号,其余项带符号输出(定义一个开关变量)
(1) 系数为a,指数b为0的项输出(a)。
(2) 系数a为1,指数b为1的项输出(x)。
(3) 系数a为1,指数b不为1的项输出(x^b)。
(4) 系数a为-1,指数b为1的项输出(-x)。
(5) 系数a为-1,指数b不为1的项输出(-x^b)。
(6) 系数a不为1或-1,指数b不为0或1的项输出(ax^b)。
2. 设计表示
(1)函数调用关系图
main→ListInitiate→ListInsert→ListAdd→ListGet
(2)函数接口规格说明
void ListInitiate(SLNode **head)/*初始化以head为头指针的单链表*/
int ListInsert(SLNode *head,DaTatype xishu,DaTatype zhishu) /*在单链表中按指数的由小到大顺序插入多项式的指数和系数*/
int ListAdd(SLNode*head1,SLNode*head2,SLNode*head3)/*以head1为头指针的单链表与以head2为头指针的单链表相加等于以head3为头指针的单链表*/
Int ListGet(SLNode*head) /*输出以head为头指针的单链表*/
3. 实现注释 (即各项功能的实现程度)
(1)根据输入的n值建立多项式a,b的单链表;根据提示输入每项的系数和指数。
(2)可不按指数大小顺序任意输入多项式的每项(整数项)。
(3)按数学格式输出a,b两多项式,然后再输出相加后的和c的多项式。
4. 详细设计
【1】插入函数:
int ListInsert(SLNode *head,DaTatype xishu,DaTatype zhishu)//插入
{
SLNode *p,*q;
p=head;
while(p->next!=NULL)
{
if((p->next->zhishu)>zhishu)break; //比较指数大小
p=p->next; //链表中节点指数大,则比较链表下一个
}
q=(SLNode*)malloc(sizeof(SLNode)); //链表中节点指数小,则在该节点前插入
q->xishu=xishu;
q->zhishu=zhishu;
q->next=NULL;
q->next=p->next;
p->next=q;
return 1;
}
【2】求和函数:
int ListAdd(SLNode*head1,SLNode*head2,SLNode*head3)
{
SLNode *p,*q,*s,*r;
int n=0;
p=head1;q=head2;s=head3;
while(p->next!=NULL) //先将a存入c中
{
r=(SLNode*)malloc(sizeof(SLNode));
r->zhishu=p->next->zhishu;
r->xishu=p->next->xishu;
r->next=NULL;
s->next=r;
p=p->next;
s=s->next;
}
s=head3;
while(s->next!=NULL &&q->next!=NULL )
{
while(s->next!=NULL && s->next->zhishu<q->next->zhishu)//搜寻 {
s=s->next;
if(s->next!=NULL)n=1;
if(n){
if( s->next->zhishu==q->next->zhishu )
{
if(s->next->xishu+q->next->xishu!=0)
{s->next->xishu=s->next->xishu+q->next->xishu;
s=s->next;}
else s->next=s->next->next;
}
else
{
r=(SLNode*)malloc(sizeof(SLNode));
r->zhishu=q->next->zhishu;
r->xishu=q->next->xishu;
r->next=s->next;
s->next=r;
s=s->next;
}//插入
q=q->next;
n=0;
}
}
if(q->next!=NULL&&s->next==NULL)s->next=q->next; //剩余项的接到C链表的尾部
return 1;
}【3】输出函数(系数为0的项已被删除):
int ListGet(SLNode *head) //输出
{
SLNode *p;
p=head->next;
int kaiguan=1;
if(p==NULL)printf("0\n"); //判断头结点为空的输出
while(p!=NULL) //判断头结点非空
{
if(kaiguan==1) //多项式第一项的输出
{
if(p->zhishu==0) //当指数为时,只输出系数xishu
printf("%d",p->xishu);
else if(p->xishu==1) //系数为1时输出X^zhishui或x
{if(p->zhishu==1)printf("x");
else printf("x^%d",p->zhishu);
}
else if(p->xishu==-1) //系数为-1时输出-X^zhishui或-x
{if(p->zhishu==1)printf("-x");
else printf("-x^%d",p->zhishu);
}
else if(p->xishu>0) //系数大于0时
{if(p->zhishu==1)printf("%dx",p->xishu);
else printf("%dx^%d",p->xishu,p->zhishu);
}
else if(p->xishu<0) //系数为负数时,原样输出
{if(p->zhishu==1)printf("%dx",p->xishu);
else printf("%dx^%d",p->xishu,p->zhishu);
}
kaiguan=0;
}
else{ //多项式的其余项都前带符号输出
if(p->zhishu==0)
{if(p->xishu!=0)
printf("+%d",p->xishu);
}
else if(p->xishu==1)
{if(p->zhishu==1)printf("+x");
else printf("+x^%d",p->zhishu);
}
else if(p->xishu==-1)
{if(p->zhishu==1)printf("-x");
else printf("-x^%d",p->zhishu);
}
else if(p->xishu>0) //系数大于0时,系数前面带“+”
{if(p->zhishu==1)printf("+%dx",p->xishu);
else printf("+%dx^%d",p->xishu,p->zhishu);
}
else if(p->xishu<0) //系数为负时,原样输出
{if(p->zhishu==1)printf("%dx",p->xishu);
else printf("%dx^%d",p->xishu,p->zhishu);
}
}
p=p->next;
}
printf("\n");
return 1;
}
三、调试分析
1.调试过程中遇到的主要问题是如何解决的;
调试过程中存在少许C语言的基础语法错误,经独立仔细观察和调试修改正确,最大的难题是将各多项式按数学格式输出,经过很多次的调试,还是存在错误,向同学请教,仍不能解决,最后重新修改算法,最终达到输出要求。
部分错误:
2.时间和空间复杂度的分析;
【1】插入函数: 时间O(n^2),空间O(n)
【2】求和函数:时间O(m+n),空间O(m+n)
【3】输出函数(系数为0的项已被删除):时间O(n),空间O(1)
3.改进设想;
(1)求和函数:将多项式a的链表复制给多项式c的链表,再调用求和函数(b的链表和c的链表相加),将求和的结果插入到c的链表中(作为多项式c)。
修改思路:将多项式a的各项先与多项b的各项比较,运算后再插入多项式c的链表,(由于a,b多项式已按指数由小到大排序)修改后时间复杂度降低。
(2)输出函数:设计按数学格式输出时,算法多样。
4.经验和体会等。
深刻体会到多动手的重要性,只有多动手编程,才能熟练灵活的掌握C语言基础知识,才能更好的理解掌握数据结构的精髓。从而避免基础语法错误,让代码变得更简洁高效。如此才能准确高效的解决问题。
四、用户手册(即使用说明)
仅需按照提示输入数字即可。
五、运行结果
运行环境:C-free
1.(1+x+x2+x3+x4+x5)+(-x3-x4)=(1+x+x2+x5)
2. (x+x100)+(x100+x200)=(x+2x100+x200)
3.(2x+5x8-3x11)+(7-5x8+11x9)=(7+2x+11x9-3x11)
4.(-x+2x3)+( x-2x3)=0
六、源程序清单
https://wenku.baidu.com/view/a114cb269a89680203d8ce2f0066f5335b81671f