数据结构实验指导书文档格式.docx
- 文档编号:20066016
- 上传时间:2023-01-16
- 格式:DOCX
- 页数:16
- 大小:27.29KB
数据结构实验指导书文档格式.docx
《数据结构实验指导书文档格式.docx》由会员分享,可在线阅读,更多相关《数据结构实验指导书文档格式.docx(16页珍藏版)》请在冰豆网上搜索。
--i){
p=(LinkList)malloc(sizeof(LNode));
scanf(&
p->
data);
//输入元素值
p->
next=L->
next;
L->
next=p;
//插入
}
}//CreateList_L
3、分别在单链表的第3个位置和第9个位置插入67和10,给出插入成功或失败的信息,并输出单链表中的各元素值。
单链表的插入操作算法如下:
StatusListInsert_L(ListLInk&
L,inti,ElemTypee){
//在带头结点的单链表L中第i个位置前插入元素
p=L;
j=0;
while(p&
&
j<
i-1){p=p→next;
++j;
if(!
p||j>
i-1)returnERROR;
s=(LinkList)malloc(sizeof(LNode));
s→data=e;
s→next=p→next;
p→next=s;
returnOK;
}//LinkList_L
4、删除单链表中的第6个数据元素和第8个数据元素,给出删除成功或失败的信息,并输出单链表中的各元素值。
单链表的删除操作如下:
StatusListDelete_L(LinkListL,inti,ElemType&
e){
//删除以L为头指针(带头结点)的单链表中第i个结点
p=L;
j=0;
while(p->
next&
j<
i-1){p=p->
}
//寻找第i个结点,并令p指向其前趋
if(!
(p->
next)||j>
i-1)returnERROR;
//删除位置不合理
q=p->
next=q->
//删除并释放结点
e=q->
data;
free(q);
returnOK;
}//ListDelete_L
5、取单链表中的第5个数据元素和第7个数据元素
StatusGetElem_L(LinkListL,inti,ElemType&
e){
//L为带头结点的单链表的头指针。
//当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR
p=L→next;
j=1;
//初始化
i){//顺序往后找
p=p→next;
}
if(!
i)returnERROR;
//第i个元素不存在
elsee=p→data;
//取第i个元素
}//GetElem_L
五、问题讨论
1、单链表具有什么优缺点?
2、单链表的定义与顺序表的定义有什么区别?
3、逆序创建单链表有什么好处?
4、为什么单链表中取元素、插入和删除操作在开始不判断给定位置i的合法性?
5、当给定位置大于单链表长度时,取元素、插入和删除操作分别是如何执行的?
6、如何改进单链表的定义,使其可以在操作前判断判断给定位置i的合法性?
六、实验报告内容
1、实验目的
2、实验内容和具体要求
3、完成情况和实验记录,实验记录为实验过程中遇到的问题及解决方法
4、程序清单
5、所输入的数据及相应的运行结果
6、问题回答
7、实验心得
实验二、二叉树的遍历
1、掌握二叉树的特点及其存储方式。
2、掌握二叉树的创建。
3、掌握二叉树前序、中序、后序遍历的基本方法及应用。
1、用前序方法建立一棵二叉树。
2、编写前序遍历二叉树的程序。
3、编写中序遍历二叉树的程序。
4、编写后序遍历二叉树的程序。
5、编写统计二叉树叶子结点个数的程序
1、二叉树的二叉链表存储类型定义
typedefstructBiTNode
{datatypedata;
structBiTNode*lchild,*rchild;
}BiTNode,*BiTree;
2、建立下图所示的二叉树
以字符串的形式“根左子树右子树”定义一棵二叉树时,创建二叉树的算法如下:
StatusCreateBiTree(BiTree&
T){
ch);
if(ch=='
'
)T=NULL;
else{
(T=newBiTNode))
exit(OVERFLOW);
T->
data=ch;
//生成根结点
CreateBiTree(T->
lchild);
//构造左子树
rchild);
//构造右子树
}//CreateBiTree
3、编程实现以上二叉树的前序、中序和后序遍历操作,输出遍历序列
(1)先序遍历二叉树的递归算法如下:
voidPreorder(BiTreeT,void(*visit)(TElemType&
e))
{//先序遍历二叉树
if(T){
visit(T->
//访问结点
Preorder(T->
lchild,visit);
//遍历左子树
rchild,visit);
//遍历右子树
(2)中序遍历二叉树的递归算法如下:
voidInorder(BiTreeT,void(*visit)(TElemType&
{//中序遍历二叉树
Inorder(T->
(3)后序遍历二叉树的递归算法如下:
voidPostorder(BiTreeT,void(*visit)(TElemType&
{//后序遍历二叉树
Postorder(T->
(4)先序遍历二叉树的非递归算法如下:
StatusPreOrderTraverse(BiTreeT,Status(*visit)(TElemType&
e)){
InitStack(S);
p=T;
While(p||!
StackEmpty(S)){
if(p){if(!
visit(p->
data))returnERROR;
Push(S,p);
p=p->
lchild;
else{
Pop(S,p);
p=p->
rchild;
}//else
}//while
(5)中序遍历二叉树的非递归算法如下:
StatusInOrderTraverse(BiTreeT,Status(*visit)(TElemType&
if(p){Push(S,p);
4、统计以上二叉树中叶子结点的个数
算法基本思想:
先序(或中序或后序)遍历二叉树,在遍历过程中查找叶子结点,并计数。
由此,需在遍历算法中增添一个“计数”的参数,并将算法中“访问结点”的操作改为:
若是叶子,则计数器增1。
算法如下:
voidCountLeaf(BiTreeT,int&
count){
if(T){
if((!
T->
lchild)&
(!
rchild))
count++;
//对叶子结点计数
CountLeaf(T->
lchild,count);
rchild,count);
}//if
}//CountLeaf
1、先序、中序、后序遍历二叉树的区别?
2、在先序、中序非递归算法中为什么使用栈?
能不能借助其它数据结构来实现?
实验三、折半查找和二叉排序树
1、掌握查找的特点。
2、掌握折半查找的基本思想及其算法。
3、熟悉二叉排序树的特点,掌握二叉排序树的插入、删除操作。
1、设有关键字序列k={5,14,18,21,23,29,31,35},查找key=21和key=25的数据元素。
2、根据关键字序列{45、24、53、12、37、93}构造二叉排序树,并完成插入13删除关键字53和24的操作。
1、折半查找
(1)从键盘输入上述8个整数5,14,18,21,23,29,31,35,存放在数组bub[8]中,并输出其值。
(2)从键盘输入21,查找是否存在该数据元素,若存在,则输出该数据元素在表中的位置,否则给出查找失败的信息。
(3)从键盘输入25,查找是否存在该数据元素,若存在,则输出该数据元素在表中位置,否则给出查找失败的信息。
折半查找算法如下:
intSearch_Bin(SSTableST,KeyTypekval){
low=1;
high=ST.length;
//置区间初值
while(low<
=high){
mid=(low+high)/2;
if(kval==ST.elem[mid].key)
returnmid;
//找到待查元素
elseif(kval<
ST.elem[mid].key))
high=mid-1;
//继续在前半区间进行查找
elselow=mid+1;
//继续在后半区间进行查找
return0;
//顺序表中不存在待查元素
}//Search_Bin
2、二叉排序树
(1)二叉排序树结点定义
typedefstructBiTNode{//结点结构
TElemTypedata;
structBiTNode*lchild,*rchild;
//左右孩子指针
}BiTNode,*BiTree;
(2)从键盘上输入六个整数45、24、53、12、37、9构造二叉排序树
(3)输出其中序遍历结果。
(4)插入数据元素13,输出其中序遍历结果。
在二叉排序树上插入结点的算法如下:
StatusInsertBST(BiTree&
T,ElemTypee){
SearchBST(T,e.key,NULL,p)){
s=newBiTNode;
//为新结点分配空间
s->
data=e;
lchild=s->
rchild=NULL;
p)T=s;
//插入s为新的根结点
elseif(LT(e.key,p->
data.key))
lchild=s;
//插入*s为*p的左孩子
elsep->
rchild=s;
//插入*s为*p的右孩子
returnTRUE;
//插入成功
elsereturnFALSE;
}//InsertBST
(5)删除数据元素24和53,输出其中序遍历结果。
在二叉排序树上删除结点的算法如下:
VoidDelete(BSTreebst,keytypex){
BSTreef=NULL,p=bst;
key!
=x)
if(p->
key>
x){f=p;
else{f=p;
if(p==NULL){
printf(“无关键字x\n”);
exit(0);
lchild=NULL)
if(f->
lchild==p)f->
lchild=p->
elsef->
rchild=p->
else{q=p;
s=p->
while(s->
rchild!
=NULL){q=s;
s=s->
if(q==p)p->
lchild=s->
elseq->
rchild=s->
free(s);
1、折半查找递归算法该怎么描述?
2、二叉排序树中序遍历结果有什么特点?
3、在二叉树排序树中插入一个新结点,总是插入到叶结点下面吗?
4、在任意一棵非空二叉排序树中,删除某结点后又将其插入,则所得二排序叉树与原二排序叉树相同吗?
实验四、内部排序
1、掌握排序的有关概念和特点。
2、熟练掌握直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序等算法的基本思想。
。
3、关键字序列有序与无序,对于不同的排序方法有不同的影响,通过该实验进一步加深理解。
设有关键字序列k={12,45,21,12,30,2,68,33},试用各种排序算法进行排序。
1、从键盘输入上述8个整数,存放在数组quick[8]中,并输出值。
2、输出各种排序算法每一趟排序的结果,观察关键字次序的变化。
(1)直接插入排序算法如下:
voidInsertionSort(SqList&
L){
//对顺序表L作直接插入排序。
for(i=2;
i<
=L.length;
++i)
if(L.r[i].key<
L.r[i-1].key){
L.r[0]=L.r[i];
//复制为监视哨
for(j=i-1;
L.r[0].key<
L.r[j].key;
--j)
L.r[j+1]=L.r[j];
//记录后移
L.r[j+1]=L.r[0];
//插入到正确位置
}//InsertSort
(2)希尔排序算法如下:
voidShellInsert(SqList&
L,intdk){
for(i=dk+1;
=n;
++i)
if(L.r[i].key<
L.r[i-dk].key){
L.r[0]=L.r[i];
//暂存在R[0]
for(j=i-dk;
j>
0&
(L.r[0].key<
L.r[j].key);
j-=dk)
L.r[j+dk]=L.r[j];
//记录后移,查找插入位置
L.r[j+dk]=L.r[0];
}//ShellInsert
voidShellSort(SqList&
L,intdlta[],intt)
{//增量为dlta[]的希尔排序
for(k=0;
k<
t;
++t)
ShellInsert(L,dlta[k]);
//一趟增量为dlta[k]的插入排序
}//ShellSort
(3)冒泡排序算法如下:
voidBubbleSort(ElemR[],intn){
i=n;
while(i>
1){
lastExchangeIndex=1;
for(j=1;
i;
j++)
if(R[j+1].key<
R[j].key){
Swap(R[j],R[j+1]);
lastExchangeIndex=j;
//记下进行交换的记录位置
}//if
i=lastExchangeIndex;
}//while
}//BubbleSort
(4)快速排序算法如下:
intPartition(RedTypeR[],intlow,inthigh){
R[0]=R[low];
pivotkey=R[low].key;
//枢轴
while(low<
high){
while(low<
high&
R[high].key>
=pivotkey)
--high;
//从右向左搜索
R[low]=R[high];
high&
R[low].key<
=pivotkey)
++low;
//从左向右搜索
R[high]=R[low];
R[low]=R[0];
returnlow;
}//Partition
voidQSort(RedType&
R[],ints,intt){
//对记录序列R[s..t]进行快速排序
if(s<
t){//长度大于1
pivotloc=Partition(R,s,t);
//对R[s..t]进行一次划分
QSort(R,s,pivotloc-1);
QSort(R,pivotloc+1,t);
}//QSort
(5)简单选择排序的算法描述如下:
voidSelectSort(ElemR[],intn){
//对记录序列R[1..n]作简单选择排序。
for(i=1;
n;
++i){//选择第i小的记录,并交换到位
j=SelectMinKey(R,i);
//在R[i..n]中选择关键字最小的记录
if(i!
=j)R[i]←→R[j];
//与第i个记录交换
}//SelectSort
(6)堆排序算法描述如下:
voidHeapSort(HeapType&
H){
//对顺序表H进行堆排序
for(i=H.length/2;
i>
0;
--i)
HeapAdjust(H.r,i,H.length);
//建大顶堆
for(i=H.length;
1;
--i){
H.r[1]←→H.r[i];
HeapAdjust(H.r,1,i-1);
//对H.r[1]进行筛选
}//HeapSort
voidHeapAdjust(RcdType&
R[],ints,intm)
{
rc=R[s];
//暂存R[s]
for(j=2*s;
=m;
j*=2){//j初值指向左孩子
if(j<
m&
R[j].key<
R[j+1].key)++j;
if(rc.key>
=R[j].key)break;
R[s]=R[j];
s=j;
R[s]=rc;
}//HeapAdjust
(7)归并排序算法描述如下:
voidMsort(RcdTypeSR[],
RcdType&
TR1[],ints,intt){
//将SR[s..t]归并排序为TR1[s..t]
if(s==t)TR1[s]=SR[s];
else
{
m=(s+t)/2;
Msort(SR,TR2,s,m);
//递归地将SR[s..m]归并为有序的TR2[s..m]
Msort(SR,TR2,m+1,t);
Merge(TR2,TR1,s,m,t);
}
}//Msort
3、如果上述8个整数按照升序输入,即k1={2,12,12,21,30,33,45,68},输出各种排序算法每一趟排序的结果,观察关键字次序的变化。
4、如果上述
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 指导书
![提示](https://static.bdocx.com/images/bang_tan.gif)