数据结构实验指导书.docx
- 文档编号:5735671
- 上传时间:2022-12-31
- 格式:DOCX
- 页数:48
- 大小:52.15KB
数据结构实验指导书.docx
《数据结构实验指导书.docx》由会员分享,可在线阅读,更多相关《数据结构实验指导书.docx(48页珍藏版)》请在冰豆网上搜索。
数据结构实验指导书
数据结构实验指导书
仲志平王元航编写
安徽师范大学物理与电子信息学院
信息技术教研室
二0一一年八月
前言
《数据结构》在计算机科学中是一门综合性的专业主干课,专业基础课,主要介绍如何合理地组织数据、有效地存储和处理数据,正确地设计算法以及对算法的分析和评价.通过本课程的学习,使学生深入透彻地理解数据结构的逻辑结构和物理结构的基本概念以及有关算法,培养基本的、良好的程序设计技能,编制高效可靠的程序,为电子信息工程专业、通信工程专业学生今后学习其它相关专业课程奠定基础.
本实验指导书是为了配合“实用数据结构”课程的教学而编写的.指导书包括3个实验,每个实验均由实验目的、基本概念和实验内容三个部分构成.其中实验内容包括“验证性内容”和“设计性内容”两部分.“验证性内容”提供了参考程序,主要是加深对基本概念的理解、增加感性认识.“设计性内容”则是考察学生对所学知识灵活运用的能力.为了帮助同学们对所学知识的理解,在基本概念中提供了各种数据结构所对应的操作的算法.在附录中提供了一些结构较复杂的操作算法及相应的实例.
实验操作是本课程教学内容的一个重要方面,因此要求同学在每次实验操作之前,仔细阅读实验指导书和教材中的相关内容,复习和掌握好算法工具(C语言),读懂“验证性内容”,准备好“设计性内容”的方案.操作过程中细心观察各种现象和结果,做好记录,最终完成实验报告.
目录
实验一顺序存储线性表、栈与队列1
一、实验目的1
二、基本概念1
三、实验内容4
实验二链式存储线性表、栈与队列9
一、实验目的9
二、基本概念9
三、实验内容14
实验三二叉树与图17
一、实验目的17
二、基本概念17
三、实验内容22
实验四查找与排序27
一、实验目的27
二、基本概念27
三、实验内容36
附录39
拓扑排序39
堆排序44
实验一顺序存储线性表、栈与队列
一、实验目的
1.了解和掌握顺序存储线性表、栈与队的基本概念、存储方式.
2.掌握顺序存储线性表、栈与队等数据结构的相关运算和算法,并能灵活应用.
二、基本概念
1.线性表
线性表是由一组有限的数据元素的集合,它是一种最简单、最常见的数据结构.线性表的一般表示形式为:
L=(a1,a2,…,an)
其中L为线性表,ai(i=1,2,…,n)是属于某数据对象的元素,n(n≥0)为元素个数,又称为表长,n=0时为空表.
顺序表中的数据元素存储在一组地址连续的存储单元中,其存储结构具有以下特点:
①线性表中所有元素所占的存储空间是连续的;
②线性表中各数据元素在存储空间中是按逻辑顺序依次存放的.
顺序表的的主要运算有插入、删除、查找和排序.
(1)顺序表的运算
顺序表的插入运算算法(算法1.1)
输入:
顺序表的存储空间V(0:
m-1);线性表的长度n(n≤m);插入的位置i(i表示在第i个元素之前插入);插入新的元素b.
输出:
插入后的顺序表存储空间V(0:
m-1)及线性表的长度n.
PROCEDUREINSL(V,m,n,i,b)
1.IF(n=m)THEN{OVERFLOW;RETURN}
2.IF(i>n-1)THENi=n
3.IF(i<0)THENi=0
4.FORj=n-1TOiBY-1DOV(j+1)=V(j)
5.V(i)=b
6.n=n+1
7.RETURN
顺序表的删除运算算法(算法1.2)
输入:
顺序表的存储空间V(1:
m-1);顺序表的长度n(n≤m);
删除的位置i(表示删除第i个元素).
输出:
删除后的顺序表存储空间V(0:
m-1)及顺序表的长度n.
PROCEDUREDESL(V,m,n,i)
1.IF(n=0)THEN{UNDERFLOW;RETURN}
2.IF(i<0)or(i>n-1)THEN
{“Notthiselementinthelist”;RETURN}
3.FORj=iTOn-1DOV(j)=V(j+1)
4.n=n-1
5.RETURN
2.栈
栈是限定仅在表尾进行插入和删除操作的线性表.栈的表尾端称为栈顶(top),表头端称为栈底(bottom).栈可表示为:
S=(a1,a2,a3,…,an)
其中a1为栈底元素,an为栈顶元素,栈中元素按a1,a2,…,an次序入栈,又按an,an-1,…,a2,a1次序出栈.若n=0,则称为空栈.因此栈又称为后进先出(LastInFirstOut,LIFO)线性表.
若用一维数组作为栈的存储空间,则称为顺序栈.顺序栈的运算:
顺序栈的插入运算算法(算法1.3)
入栈运算是指在栈顶位置插入一个新元素.首先将栈顶指针进1(即top加1),然后将新元素插入到栈顶指针指向的位置.
输入:
栈顺序存储空间S(0:
m-1);栈顶指针top;入栈元素为x.
输出:
新元素入栈后的栈顺序存储空间S(0:
m-1)以及栈顶指针top.
PROCEDUREPUSH(S,m,top,x)
1.IF(top=m-1)THEN{Stack-OVERFLOW;RETURN}
2.top=top+1
3.S(top)=x
4.RETURN
顺序栈的删除运算算法(算法1.4)
首先将栈顶元素(栈顶指针指向的元素)赋给一个指定的变量,然后将栈顶指针退1(即便top减1).
输入:
栈顺序存储空间S(0:
m-1),栈顶指针top.
输出:
退栈后的栈顺序存储空间S(0:
m-1)以及栈顶指针top;存放弹出元素的变量y.
PROCEDUREPOP(S,m,top,y)
1.IF(top=-1)THEN{Stack-UNDERFLOW;RETURN}
2.y=S(top)
3.top=top-1
4.RETURN
3.队列
队列是只允许在表的一端进行插入,而在另一端进行删除的线性表.允许插入的一端称为队尾(rear),允许删除的一端称为队头(front).因此,队列又称为先进先出(FirstInFirstOut,FIFO)线性表.
若用一维数组作为队列的存储空间,则称为顺序队列.顺序队列的运算:
顺序队列的插入运算算法(算法1.5)
输入:
循环队列顺序存储空间Q(0:
m-1);队尾指针rear;排头指针front;标志s;入队的元素x.
输出:
入队后的循环队列存储空间Q(0:
m-1);队尾指针rear;标志s.
PROCEDUREADDCQ(Q,m,rear,front,s,x)
1.IF(s=1)and(rear=front)THEN
{Queue-OVERFLOW;RETURN}
2.rear=rear+1
3.IF(rear=m)THENrear=0
4.Q(rear)=x
5.s=1
6.RETURN
顺序队的删除运算算法(算法1.6)
输入:
循环队列顺序存储空间Q(0:
m-1);队尾指针rear;排头指针front;标志s.
输出:
退队后的循环队列存储空间Q(0:
m-1);排头指针front;标志s,存放退出元素的变量y.
PROCEDUREDELCQ(Q,m,rear,front,s,y)
1.IF(s=0)THEN
{Queue-UNDERFLOW;RETURN}
2.front=front+1
3.IF(front=m)THENfront=0
4.y=Q(front)
5.IF(front=rear)THENs=0
6.RETURN
三、实验内容
(一)分析以下各算法的原理并上机验证
1.建立一个长度为10的有序表,设计算法删除第j个元素,j由键盘输入(1≤j≤10).
提示:
用函数delete实现删除元素的过程,在main()函数中建立有序表,为了简化程序,输入时就按序输入.
[参考程序]
intn=10;/*n为表长*/
inta[10];
main()
{
voiddelete(intj);/*函数声明*/
intj,i;
printf("Pleaseinputthelist:
\n");
for(i=0;i scanf("%d",&a[i]); printf("Pleaseinputj: "); scanf("%d",&j); delete(j);/*函数调用*/ for(i=0;i printf("%d\t",a[i]); } voiddelete(intj) { inti; if(j<1||j>n) { printf("Error! \n"); exit(0); } for(i=j-1;i a[i]=a[i+1]; n--;/*修改表长*/ } 2.设顺序栈S[1: m],top为栈顶指示器,请设计进栈算法. 说明: 顺序栈S可用一维数组S[1: m]表示,top为一栈顶指针变量,top=0表示栈空,top=m表示栈满. [参考程序] #definem10 ints[m+1],top=0;/*s[0]单元不用,s[1: m]用于栈*/ voidpush(intx) { if(top==m) printf("Overflow! \n"); else { top++; s[top]=x; } } main() { voidpush(intx); inti,d; do{ printf("InputanumbertoPUSH,0tostop: "); scanf("%d",&d); if(d! =0)push(d); } while(d! =0); printf("ElementsintheSTACK: \n"); for(i=top;i>0;i--) printf("s[%d]=%d\n",i,s[i]); } 3.利用一维数组Q[0: 9]实现一个循环队列,并任意进行插入和删除操作. 要求: 插入或删除由键盘控制,例如输入“I”表示插入,输入“D”表示删除(此时应显示被删除的元素),输入“E”则表示结束操作. [参考程序] voidaddcq(intcq[],intm,intx)/*入队*/ { externfront,rear; intr; if((rear+1)%m==front) printf("Queueisfull! \n");/*队满*/ else { rear=(rear+1)%m; cq[rear]=x; } } intdelcq(intcq[],intm)/*出队*/ { externfront,rear; if(front==rear) { printf("Queueisempty! \n");/*队空*/ return(-9999);/*队空则返回-9999*/ } else { front=(front+1)%m; return(cq[front]); } } #include"stdio.h" #defineM10 intq[M]; intfront,rear; main() { charc; intd; front=rear=M-1; do{ printf("I--insert,D--delete,E--end\nWhichoperationtodo? "); c=getchar();getchar(); if(c=='I'||c=='i') { printf("Inputadatatoinsert: "); scanf("%d",&d);getchar(); addcq(q,M,d); } elseif(c=='D'||c=='d') { d=delcq(q,M); if(d! =-9999)printf("%disdeletedfromthequeue.\n",d); } } while(c! ='E'&&c! ='e');/*退出操作*/ printf("Bye! \n"); } (二)按要求进行算法设计并调试运行 1.写一个将向量L(a1,a2,···,an)倒置的算法,并调试运行. 2.建立一个长度为10的顺序表L,然后设计算法,实现在顺序表中第k个元素结点前插入一个新元素,并输出插入新元素之后的顺序表. 实验二链式存储线性表、栈与队列 一、实验目的 1.了解和掌握链式存储线性表、栈与队的基本概念、存储方式. 2.掌握链式存储线性表、栈与队等数据结构的相关运算和算法,并能灵活应用. 二、基本概念 1.线性链表 线性表的链式存储结构称为线性链表.在链式存储方式中,每个结点由两部分组成: 一部分用于存储数据元素值,称为数据域;另一部分用于存放指针,称为指针域. 在链式存储方式中,存储数据的存储空间可以不连续,各数据结点的存储顺序与数据元素之间的逻辑关系可以不一致,而数据元素之间的逻辑关系是由指针域来确定的. (1)单链表的运算 单链表结点的数据结构定义: structnode { datatypedata; structnode*next; }; 单链表的插入运算算法(算法2.1) voidInsertSCL(structnode*L,datatypex,inti) /*将x插入链表的第i个位置*/ { p=L; j=0; while((p! =null)&&(j { p=p->next; j++; }/*使指针p指向第i-1个结点*/ if(p==null)printf(“第i-1个结点不存在”); else { s=(structnode*)malloc(sizeof(structnode));/*申请一个结点s*/ s->data=x; s->next=p->next;/*使新结点指向链表的第i个结点*/ p->next=s; } } 单链表的删除运算算法(算法2.2) datatypeDeleteSCL(structnode*L,inti) /*删除链表L中的第i个元素,将被删除的结点的值作为函数值返回*/ { p=L; j=0; while((p! =null)&&(j { p=p->next; j++; }/*使指针p指向第i-1个结点*/ if(p==null)printf(“第i-1个结点不存在”); else { q=p->next;/*使指针q指向第i个结点*/ p->next=q->next; x=q->data; free(q);/*释放被删除结点的空间*/ return(x);/*返回被删除结点的值*/ } } (2)双向链表的运算 双向链表结点的数据结构定义: structDL { datatypedata; structDL*prior,*next; }; 双向链表的插入运算算法(算法2.3) InsertDCL(structDL*L,structDL*p,datatypee)/*将元素e插入到双向链表L中p指针所指的元素的前边*/ { s=(structDL*)malloc(sizeof(structDL));/*申请一个结点s*/ s->data=x; s->next=p; s->prior=p->prior;/*使新结点的前驱指针指向p结点的前驱结点*/ p->prior->next=s;/*使p结点的前驱结点的后继指针指向新结点*/ p->prior=s; } 双向链表的删除运算算法(算法2.4) datatypeDeleteDCL(structDL*L,structDL*p)/*删除双向链表L中p指针所指的元素,并将被删除的结点的值作为函数值返回*/ { x=p->data;/*将删除结点的值赋给x*/ p->prior->next=p->next;/*使p结点的前驱结点的后继指针指向p结点的后继结点*/ p->next->prior=p->prior;/*使p结点的后继结点的前驱指针指向p结点的前驱结点*/ free(p); return(x); } 2.链栈 栈的链式存储结构称为链栈. 链式栈结点结构定义: structnode { datatypedata; structnode*next; }; 链栈的插入运算算法(算法2.5) 输入: 链栈的栈顶指针top;入栈的元素值x. 输出: 元素x入栈后的链栈栈顶指针top. PROCEDUREPUSHLL(top,x) NEW(p)[从可利用栈取得一个新结点] V(p)=x[置新结点数据域] NEXT(p)=top[置新结点指针域] top=p[改变栈顶指针] RETURN 链栈的退栈运算算法(算法2.6) 输入: 带链栈的栈顶指针top. 输出: 退栈后的带链栈栈顶指针top;存放退出结点元素值的变量y. PROCEDUREPOPLL(top,y) y=V(top)[取出栈顶元素值] p=top top=NEXT(p)[改变栈顶指针] DISPOSE(p)[被删除结点送回可利用栈] RETURN 3.带链的队列 队列的链式存储结构称为带链的队列. 链队结构定义: structLQ { datatypedata; structLQ*front,*rear; }; 链队的插入运算算法(算法2.7) 输入: 带链队列的队尾指针rear;入队的新元素x. 输出: 元素x入队后的带链队列队尾指针rear. PROCEDUREADDLL(rear,x) NEW(p)[从可利用栈取得一个新结点p] V(p)=x[置新结点的数据域] NEXT(p)=0[置新结点的指针为空] NEXT(rear)=p rear=p[改变队尾指针] RETURN 链队的删除运算算法(算法2.8) 输入: 带链队列的排头指针front. 输出: 退队后的带链队列排头指针front;存放退出结点值的变量y. PROCEDUREDELLL(front,y) y=V(front)[取出排头元素值] p=front front=NEXT(front)[改变排头指针] DISPOSE(p)[释放删除的结点] RETURN 三、实验内容 (一)分析以下各算法的原理并上机验证 建立一个含10个年龄结点的线性链表,然后设计算法,实现在链表中第k个元素结点前插入一个新元素newage. 说明: 用一个结构体数组来存储链表中的各个结点,且数组的第0个元素作为附加的头结点,并由头指针head指向. [参考程序] structage { intdata; structage*next; }; structagenode[11],new; #include"stdio.h" main() { voidinsert(structage*head,intk,intnewage); structage*head,*p; inti,k,newage; head=&node[0]; printf("Pleaseinput10ages: \n"); /*构造链表*/ p=head; for(i=1;i<=10;i++) { p->next=&node[i]; p=p->next; scanf("%d",&(p->data)); } p->next=NULL; printf("Pleaseinputkandnewage: \n"); scanf("%d%d",&k,&newage); insert(head,k,newage); /*输出链表*/ p=head; while(p->next! =NULL) { p=p->next; printf("%d\t",p->data); } } voidinsert(structage*head,intk,intnewage) { structage*p; inti; /*查找插入点*/ p=head; i=0; while(p! =NULL&&i { p=p->next; i++; } if(p==NULL) printf("Error! Nopositiontoinsert! \n"); else { new.data=newage; new.next=p->next; p->next=&new; } } (二)按要求进行算法设计并调试运行 1.建立一个含10个结点的线性链表,然后设计算法删除链表中第k个元素结点. 2.编写程序,计算线性单链表长度.(先构造一个线性单链表,再输出该链表的长度) 3.编写程序,实现线性单链表的逆转.(先构造一个线性单链表,再输出逆转后的线性单链表) 实验三二叉树与图 一、实验目的 1.掌握二叉树的逻辑结构、存储结构及其基本操作. 2.学会用二叉树的特性、遍历的递归算法以及哈夫曼算法解决实际问题. 3.掌握图的概念、存储方式和遍历算法. 二、基本概念 1.树与二叉树 (1)树 树(Tree)是由n(n≥0)个结点组成的有限集合T,其中有且仅有一个结点称为根结点,其余结点可以分为m(m≥0)个互不相交的有限子集T1,T2,…,Tm,且每一个子集Ti本身又是一棵树,称为根结点的子树.当n=0时称为空树. 树一般用链式存储结构来表示,即以多重链表结构来描述树. (2)二叉树 二叉树(BinaryTree)是n(n≥0)个结点的有限集合,它或为空树(n=0),或由一个根结点和两棵分别称为左子树和右子树的互不相交的二叉树构成. 通常用具有两个指针域的链表作为二叉树的存储结构. 二叉树是树型结构的基本形态,其应用十分广泛.如二叉排序树与哈夫曼树等. 二叉树的遍历是指按一定规律或路径对二叉树中每个结点进行访问且仅访问一次.分为先序遍历(DLR)、中序遍历(LDR)和后序遍历(LRD)三种.它们的算法如下: 二叉树结点结构 structBTnode { datatypedata; structBTnode*lchild,*rchild;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 指导书