《数据结构》实验指导书源代码.docx
- 文档编号:3244608
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:67
- 大小:49.76KB
《数据结构》实验指导书源代码.docx
《《数据结构》实验指导书源代码.docx》由会员分享,可在线阅读,更多相关《《数据结构》实验指导书源代码.docx(67页珍藏版)》请在冰豆网上搜索。
《数据结构》实验指导书源代码
实验一线性表的链式存储结构
一、实验目的:
1.掌握线性表的链式存储结构。
2.熟练地利用链式存储结构实现线性表的基本操作。
3.能熟练地掌握链式存储结构中算法的实现。
二、实验内容:
1.用头插法或尾插法建立带头结点的单链表。
2.实现单链表上的插入、删除、查找、修改、计数、输出等基本操作。
三、实验要求:
1.根据实验内容编写程序,上机调试、得出正确的运行程序。
2.写出实验报告(包括源程序和运行结果)。
四、实验学时:
2学时
五、实验步骤:
1.进入编程环境,建立一新文件;
2.参考以下相关内容,编写程序,观察并分析输出结果。
①定义单链表的数据类型,然后将头插法和尾插法、插入、删除、查找、修改、计数、输出等基本操作都定义成子函数的形式,最后在主函数中调用它,并将每一种操作前后的结果输出,以查看每一种操作的效果。
②部分参考程序
//单链表的建立(头插法),插入,删除,查找、修改、计数、输出
#include
#defineelemtypeint
structlink
{elemtypedata;//元素类型
link*next;//指针类型,存放下一个元素地址
};
//头插法建立带头结点的单链表
link*hcreat()
{links,p;
elemtypei;
cout<<”输入多个结点数值(用空格分隔),为0时算法结束”;
cin>>i;
p=newlink;
p->next=NULL;
while(i)//当输入的数据不为0时,循环建单链表
{s=newlink;
s->data=i;
s->next=p->next;
p->next=s;
cin>>i;}
returnp;
}
//输出单链表
voidprint(1ink*head)
{
1ink*p;
p=head->next;
while(p->next!
=NULL)
{
cout<
p=p->next;
}
cout<
cout< } ∥在单链表head中查找值为x的结点 Link*Locate(1ink*head,elemtypex) { Link*p; p=head->next; while((p! =NULL)&&(p->data! =x)) p=p->next; returnp;} //在head为头指针的单链表中,删除值为x的结点 voiddeletel(1ink*head,elemtypex) { 1ink*p,*q; q=head; p=head->next; while((p! =NULL)&&(p->data! =x)) { q=p; p=p->next;} If(p==NULL)cout<<“要删除的结点不存在”; else q->next=p->next; delete(p); } } //在头指针head所指的单链表中,在值为x的结点之后插入值为y的结点 voidinsert(1ink*head,elemtypex,elemtypey) {link*p,*s; s=newlink; s->data=y; if(head->next==NULL)//链表为空 { head->next=s; s->next=NULL: } p=Locate(head,x);//调用查找算法‘ if(p==NULL) cout<<”插入位置非法”: else (s->next=p->next; p->next=s; } } //将单链表p中所有值为x的元素修改成y voidchange(1ink*p,elemtypex,elemtypey) { link*q; q=p->next; while(q! =NULL) {if(q->data==x)q->data=y; q=q->next; } } voidcount(1ink*h)//统计单链表中结点个数 { 1ink*p;intn=0; p=h->next; while(p! =NULL) {n++;p=p->next;} returnn; } voidmain() {intn; elemtypex,y; link*p,*q; p=hcreat();//头插法建立链表 print(p);//输出刚建立的单链表 cout<<”请输入要删除的元素”; cin>>y; deletel(p,y); print(p);//输出删除后的结果 cout<<”请输入插入位置的元素值(将待插元素插入到它的后面)”; cin>>x; cout<<”请输入待插元素值”; cin>>y; insert(p,x,y); print(p);//输出插入后的结果 cout<<”请输入要修改前、后的元素值”; cin>>x>>y; change(p,x,y); print(p); cout<<”请输入要查找的元素值”; cin>>x; q=Locate(p,x); if(q==NULL)cout< ”< elsecout< ”< n=count(p); cout<<”链表中结点个数为: ”< } //单链表的建立(尾插法)、插入、删除、查找、修改、计数、输出 #include #defineelemtypeint structlink {elemtypedata;//元素类型 link*next;//指针类型,存放下-个元素地址 }; //尾插法建立带头结点的单链表 link*rcreat() {link*s,*p,*r; elemtypei; cout<<”输入多个结点数值(用空格分隔),为0时算法结束”; cin>>i; p=r=newlink; p->next=NULL; while(i) {s=newlink; s->data=i; r->next=s; r=s; cin>>i;} r->next=NULL; returnp; } //输出单链表 voidprint(1ink*head) {link*p; p=head->next; while(p->next! =NULL) { cout< p=p->next; ) cout< cout< } link*Locate(1ink*head,intx)∥在单链表中查找第x个结点 {link*p; p=head; intj=0; while((p! =NULL)&&(j {p=p->next;j++;} returnp; } voiddeleteI(1ink*head,elemtypex) //在head为头指针的单链表中,删除值为x的结点 { link*p,*q; q=head; p=head->next; while((p! =NULL)&&(p->data! =x)) { q=p; p=p->next;) if(p==NULL)cout<<”要删除的结点不存在“; else { q->next=p->next; delete(p); }} voidinsert(1ink*head,intx,elemtypey) //在头指针head所指单链表中,在第x个结点之后插入值为y的结点 {link*p,*s; s=newlink; s->data=y; if(head->next==NULL)//链表为空 { head->next=s; s->next=NULL: } p=Locate(head,x);//调用查找算法 if(p==NULL) cout<<”插入位置非法”; else {s->next=p->next; p->next=s; }} voidchange(1ink*p,elemtypex,elemtypey) {∥将单链表P中所有值为x的元素改成值为y link*q; q=p->next; while(q! =NULL) {if(q->data==x)q->data=y; q=q->next; } } voidcount(1ink*h)//统计单链表中结点个数 (1ink*p;intn=0; p=h->next; while(p! =NULL) {n++;p=p->next;} retumn; } voidmain() {intn; linkp,q; p=rcreat();//尾插法建立链表 print(p);//输出刚建立的单链表 cout<<”请输入要删除的元素”; cin>>y; deletel(p,y); print(p);//输出删除后的结果 cout<<”请输入插入位置”; cin>>x; cout<<”请输入待插元素值”; cin>>y; insert(p,x,y); print(p);//输出插入后的结果 cout<<”请输入修改前、后的元素值”; cin>>x>>y; change(p,x,y); print(p); cout<<“请输入要查找的元素值”; cin>>x; q=Locate(p,x); if(q==NULL)cout< ”< elsecout< ”< n=count(p); cout<<”链表中结点个数为: ”< } 六、选作实验 试设计一元多项式相加(链式存储)的加法运算。 A(X)=7+3X+9X8+5X9 B(X)=8X+22X7-9X8 1.建立一元多项式; 2.输出相应的一元多项式; 3.相加操作的实现。 实验二循环链表的操作 一、实验目的: 通过本实验中循环链表和双向链表的使用,使学生进一步熟练掌握链表的操作方式。 二、实验内容: 本次实验可以从以下两个实验中任选一个: 1.建立一个单循环链表并实现单循环链表上的逆置。 所谓链表的逆置运算(或称为逆转运算)是指在不增加新结点的前提下,依次改变数据元素的逻辑关系,使得线性表(al,a2,a3,…,an)成为(an,…,a3,a2,a1)。 2.构建一个双向链表,实现插入、查找和删除操作。 三、实验要求: 1.根据实验内容编写程序,上机调试、得出正确的运行程序。 2.写出实验报告(包括源程序和运行结果)。 四、实验学时: 2学时 五、实验步骤: 1.进入编程环境,建立一新文件; 2.参考以下相关内容,编写程序,观察并分析输出结果。 ①建立一个带头结点的单循环链表,从头到尾扫描单链表L,把p作为活动指针,沿着链表向前移动,q作为p前趋结点,r作为q的前趋结点。 其中,q的next值为r;r的初值置为head。 ②双向链表的构造与单链表相同,至于它的插入与删除运算比单链表复杂,插入运算需要4步操作,删除运算需要2步操作,注意语句的次序,不要任意交换位置,以免不能正确插入或删除结点。 ③部分参考程序 //循环链表 ∥头文件h1.h的内容 #defineNULL0 #include #include typedefstructnode {intnum; structnode*next; }linklist; ∥以下是主程序 #include”h1.h” ∥输出循环链表的信息 voidoutput(linklist*head) {linklist*p; p=head->next; while(p! =head) {printf(”%d”,p->num); p=p->next; } printf(”\n”); } //建立单循环链表 Linklist*creat(intn) { intk; linklist*head,*r,*p; p=(linklist*)malloc(sizeof(linklist)); head=p; r=p; p->next=p; for(k=1;k<=n;k++) { p=(linklist*)malloc(sizeof(linklist)); p->num=k; r->next=p; r=p; } p->next=head; return(head); } ∥逆置函数 linklist*invert(linklist*head) { Linklist*p,*q,*r; p=head->next; q=head; while(p! =head) {r=q; q=p; p=p->next; q->next=r; } head->next=q; return(head); } voidmain() {intn; Linklist*head; printf(“输入所建立的循环链表的结点个数: \n”); scanf(“%d”,&n); head=creat(n); printf(”输出建立的单循环链表: \n”); output(head); printf(”现在进行逆置! \n”); head=invert(head); printf(”输出进行逆置运算后的单循环链表的结点信息! \n”); output(head); } //双向链表参考程序 //以下是头文件hh.h的内容 #include #include typedefstructdupnode {intdata; structdupnode*next,*prior; }dulinklist; //以下是主程序的内容 #include”hh.h” //create函数用来构建双向链表 dulinklist*create() {dulinklist*head,*p,*r; inti,n; head=(dulinklist*)malloc(sizeof(dulinklist)); head->next=NULL; head->prior=NULL; r=head; printf(“请输入所建双向链表中结点的个数: \n”); scanf(“%d”,&n); for(i=l;i<=n;i++) {p=(dulinklist*)malloc(sizeof(dulinklist)); printf(”输入结点的值: \n”); scanf(”%d’,&p->data); p->next=NULL; r->next=p; p->prior=r; r=r->next; } return(head); } //find函数用来实现在双向链表中按序号查找某个结点的功能。 voidfind(dulinklist*h) { intk,i; dulinklist*p; p=h; i=0: printf(”输入要查找结点的序号: \n”); scanf(”%d”,&k); while((p! =NULL)&&(i { p=p->next; i++: } if(p) {printf(”所查到的结点的值为: \n”); printf(”%d\n”,p->data); } else printf(”没找到该结点! \n”); } //insdulist函数用来实现在双向链表中按序号插入结点的功能 dulinklist*insdulist(dulinklist*head,inti,intx) {dulinklist*p,*s; intj; p=head;j=0; whi1e((p->next! =head)&&(j {p=p->next; j++; } If(j==i-1) { s=(dulinklist*)malloc(sizeof(dulinklist)); s->data=x; s->prior=p; s->next=p->next; p->next->prior=s; p->next=s; } else printf(”error\n”); returnhead; } //deledulist函数实现在双向链表中按序号删除某个结点的功能 dulinklist*deledulist(dulinklist*head,inti) {dulinklist*p; intj; p=head; j=0 while((p->next! =head)&&(j {p=p->next; j++; } If(j==i) {p->prior->next=p->next; p->next->prior=p->prior; free(p); } else printf(”error\n”); returnhead; } //output函数用来输出整个双向链表的结点值 voidoutput(dulinklist*h) { dulinklist*p; p=h->next; while(p! =NULL) {printf(”输出该双向链表的结点,分别为: \n”); printf(”%d\n”,p->data); p=p->next; } } voidmain() {dulinklist*head; intflag=l,i,k,x; while(flag)//flag作为判断循环的标志位 {printf(”1.建立双向链表\n”); printf(”2.查找某个结点\n”); printf(”3.插入一个结点\n”); prtntf(”4.删除一个结点\n”); printf(”5.退出\n”); printf(”请输入选择: \n“); scanf(”%d”,&i); switch(i) {case1: head=create0;break; case2: find(head);break; case3: printf(”输入待插的结点的序号及新插入结点的data值.\n”); scanf(”%d%d”,&k,&x); head=insdulist(head,k,x); output(head); break; case4: printf(”输入要删除的结点的序号.\n”); scanf(”%d,&k); head=deledulist(head,k); output(head); break; case5: flag=0; } }//while循环结束 } 此程序不论是插入、查找还是删除运算均是按序号的方式来处理,当然也可改为按结点的值来作相应的处理,试修改以上程序实现按值操作的功能。 六、选作实验 利用单循环链表存储结构,解决约瑟夫(Josephus)环问题。 即: 将编号是1,2,…,n(n>0)的n个人按照顺时针方向围坐一圈,每人持有一个正整数密码。 开始时任选一个正整数作为报数上限值m,从某个人开始顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有的人全部出列为止。 令n最大值取30。 设计一个程序,求出出列顺序,并输出结果。 实验三树形结构 一、实验目的: 1.掌握二叉树的数据类型描述及二叉树的特性。 2.掌握二叉树的链式存储结构(二叉链表)的建立算法。 3.掌握二叉链表上二叉树的基本运算的实现。 二、实验内容: 从以下1、2和3、4中各选择一项内容 1.用递归实现二叉树的先序、中序、后序3种遍历。 2.用非递归实现二叉树的先序、中序、后序3种遍历。 3.实现二叉树的层次遍历。 4.将一棵二叉树的所有左右子树进行交换。 三、实验要求: 1.根据实验内容编程,上机调试、得出正确的运行程序。 2.写出实验报告(包括源程序和运行结果)。 四、实验学时: 4学时 五、实验步骤: 1.进入编程环境,建立一新文件; 2.参考以下相关内容,编写程序,观察并分析输出结果。 1将建立二叉树及先序、中序、后序3种遍历算法都写成子函数,然后分别在主函数中调用它,但在建立二又树中,必须把二叉树看成完全二叉树的形式。 若不是完全二叉树,则在输入数据时,用虚结点(不存在)表示(本算法中,用“,”号代替)。 2用非递归法实现二叉树的遍历 非递归算法中,必须设置堆栈,可以直接用一维数组来代替栈,但必须另外设置栈顶指针。 ③实现二叉树的层次遍历 用一个一维数组代替队列,实现二叉树的层次遍历。 ④将一棵二叉树的所有左右子树进行交换。 本算法只要增加一个实现二叉树左右子树交换的子函数即可。 为了便于查看,在主函数将交换前后的三种遍历效果,分别输出。 以下为部分参考程序: //递归实现二叉树的3种遍历 #include typedefcharelemtype; structbitree {定义二叉树数据类型 elemtypedata;//结点信息 bitree*lchild,*rchild;//左右孩子 }; bitree*create()//建立二叉链表 {bitree*root,*s,*q[100];//q为队列,最大空间为100 intfront=l,rear=0;//队列头、尾指针 charch; root=NULL; cout<<”请输入结点值(‘,’为虚结点,‘#’结束): ”< cin>>ch; while(ch! =’#’) {s==NULL; if(ch! =’,’) {s=newbitree; s->data=ch; s->lchild=NULL; s->rchild=NULL; } rear++; q[rear]=s;//进队 if(rear==1)root=s; else {if((s! =NULL)&&(q[front]! =NULL)) {if(rear%2==0
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 指导书 源代码
![提示](https://static.bdocx.com/images/bang_tan.gif)