数据结构实验指导书.docx

上传人:b****6 文档编号:7040861 上传时间:2023-01-16 格式:DOCX 页数:16 大小:27.29KB
下载 相关 举报
数据结构实验指导书.docx_第1页
第1页 / 共16页
数据结构实验指导书.docx_第2页
第2页 / 共16页
数据结构实验指导书.docx_第3页
第3页 / 共16页
数据结构实验指导书.docx_第4页
第4页 / 共16页
数据结构实验指导书.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

数据结构实验指导书.docx

《数据结构实验指导书.docx》由会员分享,可在线阅读,更多相关《数据结构实验指导书.docx(16页珍藏版)》请在冰豆网上搜索。

数据结构实验指导书.docx

数据结构实验指导书

《数据结构》实验指导书

(适用于计算机科学与技术、网络工程专业)

 

计算机科学与技术学院

软件教研室

2006-8

 

目录

前言3

实验一、单链表的基本操作4

实验二、二叉树的遍历5

实验三、折半查找和二叉排序树7

实验四、内部排序9

前言

《数据结构》是计算机科学与技术、网络工程等专业的专业基础必修课,主要介绍如何合理地组织数据、有效地存储和处理数据,正确地设计算法以及对算法进行分析和评价。

本课程的学习应使学生深刻地理解数据结构的逻辑结构和物理结构的基本概念及有关算法,培养学生基本的、良好的程序设计技能以及针对具体问题,选择适当的数据结构,设计出有效算法的能力。

《数据结构》是一门理论和实践相结合的课程,它在整个计算机专业教学体系中处于举足轻重的地位,是计算机科学的算法理论基础和软件设计的技术基础,其上机实验的目的主要是编程实现数据结构各章的主要算法,训练学生实际动手进行程序设计和程序调试的能力,加深对数据结构相关概念和算法的理解。

实验一、单链表的基本操作

一、实验目的

1、掌握线性链表的操作特点,即指针是逻辑关系的映像。

2、掌握动态产生单链表的方法。

3、熟练掌握单链表的插入、删除操作特点,即指针赋值的先后次序。

4、熟练掌握单链表的取元素操作

二、实验内容

1、定义单链表类型并动态创建单链表

2、实现线性表链式存储结构下元素的插入操作

3、实现线性表链式存储结构下元素的删除操作

4、实现线性表链式存储结构下取元素操作

三、实验环境

TC或VC++

四、实验步骤

1、单链表的存储定义

typedefstructLNode{

ElemTypedata;//数据域

structLNode*next;//指针域

}LNode,*LinkList;

2、从键盘上依次输入21、18、30、75、42、56,逆序创建单链表,并输出单链表中的各元素值。

逆序创建单链表算法如下:

voidCreateList_L(LinkList&L,intn){

//逆序输入n个数据元素,建立带头结点的单链表

L=(LinkList)malloc(sizeof(Lnode));

L->next=NULL;//建立带头结点的单链表

for(i=n;i>0;--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

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&&jnext;++j;}

//寻找第i个结点,并令p指向其前趋

if(!

(p->next)||j>i-1)returnERROR;//删除位置不合理

q=p->next;p->next=q->next;//删除并释放结点

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;//初始化

while(p&&j

p=p→next;++j;

}

if(!

p||j>i)returnERROR;//第i个元素不存在

elsee=p→data;   //取第i个元素

returnOK;

}//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、编写统计二叉树叶子结点个数的程序

三、实验环境

TC或VC++

四、实验步骤

1、二叉树的二叉链表存储类型定义

typedefstructBiTNode

{datatypedata;

structBiTNode*lchild,*rchild;

}BiTNode,*BiTree;

2、建立下图所示的二叉树

以字符串的形式“根左子树右子树”定义一棵二叉树时,创建二叉树的算法如下:

StatusCreateBiTree(BiTree&T){

scanf(&ch);

if(ch=='')T=NULL;

else{

if(!

(T=newBiTNode))

exit(OVERFLOW);

T->data=ch;//生成根结点

CreateBiTree(T->lchild);//构造左子树

CreateBiTree(T->rchild);//构造右子树

}

returnOK;}//CreateBiTree

3、编程实现以上二叉树的前序、中序和后序遍历操作,输出遍历序列

(1)先序遍历二叉树的递归算法如下:

voidPreorder(BiTreeT,void(*visit)(TElemType&e))

{//先序遍历二叉树

if(T){

visit(T->data);//访问结点

Preorder(T->lchild,visit);//遍历左子树

Preorder(T->rchild,visit);//遍历右子树

}

}

(2)中序遍历二叉树的递归算法如下:

voidInorder(BiTreeT,void(*visit)(TElemType&e))

{//中序遍历二叉树

if(T){

Inorder(T->lchild,visit);//遍历左子树

visit(T->data);//访问结点

Inorder(T->rchild,visit);//遍历右子树

}

}

(3)后序遍历二叉树的递归算法如下:

voidPostorder(BiTreeT,void(*visit)(TElemType&e))

{//后序遍历二叉树

if(T){

Postorder(T->lchild,visit);//遍历左子树

Postorder(T->rchild,visit);//遍历右子树

visit(T->data);//访问结点

}

}

(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

returnOK;

}

(5)中序遍历二叉树的非递归算法如下:

StatusInOrderTraverse(BiTreeT,Status(*visit)(TElemType&e)){

InitStack(S);p=T;

While(p||!

StackEmpty(S)){

if(p){Push(S,p);p=p->lchild;}

else{

Pop(S,p);

if(!

visit(p->data))returnERROR;

p=p->rchild;

}//else

}//while

returnOK;

}

4、统计以上二叉树中叶子结点的个数

算法基本思想:

先序(或中序或后序)遍历二叉树,在遍历过程中查找叶子结点,并计数。

由此,需在遍历算法中增添一个“计数”的参数,并将算法中“访问结点”的操作改为:

若是叶子,则计数器增1。

算法如下:

voidCountLeaf(BiTreeT,int&count){

if(T){

if((!

T->lchild)&&(!

T->rchild))

count++;//对叶子结点计数

CountLeaf(T->lchild,count);

CountLeaf(T->rchild,count);

}//if

}//CountLeaf

五、问题讨论

1、先序、中序、后序遍历二叉树的区别?

2、在先序、中序非递归算法中为什么使用栈?

能不能借助其它数据结构来实现?

六、实验报告内容

1、实验目的

2、实验内容和具体要求

3、完成情况和实验记录,实验记录为实验过程中遇到的问题及解决方法

4、程序清单

5、所输入的数据及相应的运行结果

6、问题回答

7、实验心得

实验三、折半查找和二叉排序树

一、实验目的

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的操作。

三、实验环境

TC或VC++

四、实验步骤

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

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){

if(!

SearchBST(T,e.key,NULL,p)){

s=newBiTNode;//为新结点分配空间

s->data=e;

s->lchild=s->rchild=NULL;

if(!

p)T=s;//插入s为新的根结点

elseif(LT(e.key,p->data.key))

p->lchild=s;//插入*s为*p的左孩子

elsep->rchild=s;//插入*s为*p的右孩子

returnTRUE;//插入成功

}

elsereturnFALSE;

}//InsertBST

(5)删除数据元素24和53,输出其中序遍历结果。

在二叉排序树上删除结点的算法如下:

VoidDelete(BSTreebst,keytypex){

BSTreef=NULL,p=bst;

while(p&&p->key!

=x)

if(p->key>x){f=p;p=p->lchild;}

else{f=p;p=p->rchild;}

if(p==NULL){

printf(“无关键字x\n”);exit(0);}

if(p->lchild=NULL)

if(f->lchild==p)f->lchild=p->rchild;

elsef->rchild=p->rchild;

else{q=p;s=p->lchild;

while(s->rchild!

=NULL){q=s;s=s->rchild;}

if(q==p)p->lchild=s->lchild;

elseq->rchild=s->lchild;

free(s);}

}

五、问题讨论

1、折半查找递归算法该怎么描述?

2、二叉排序树中序遍历结果有什么特点?

3、在二叉树排序树中插入一个新结点,总是插入到叶结点下面吗?

4、在任意一棵非空二叉排序树中,删除某结点后又将其插入,则所得二排序叉树与原二排序叉树相同吗?

六、实验报告内容

1、实验目的

2、实验内容和具体要求

3、完成情况和实验记录,实验记录为实验过程中遇到的问题及解决方法

4、程序清单

5、所输入的数据及相应的运行结果

6、问题回答

7、实验心得

实验四、内部排序

一、实验目的

1、掌握排序的有关概念和特点。

2、熟练掌握直接插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序、基数排序等算法的基本思想。

3、关键字序列有序与无序,对于不同的排序方法有不同的影响,通过该实验进一步加深理解。

二、实验内容

设有关键字序列k={12,45,21,12,30,2,68,33},试用各种排序算法进行排序。

三、实验环境

TC或VC++

四、实验步骤

1、从键盘输入上述8个整数,存放在数组quick[8]中,并输出值。

2、输出各种排序算法每一趟排序的结果,观察关键字次序的变化。

(1)直接插入排序算法如下:

voidInsertionSort(SqList&L){

//对顺序表L作直接插入排序。

for(i=2;i<=L.length;++i)

if(L.r[i].key

L.r[0]=L.r[i];//复制为监视哨

for(j=i-1;L.r[0].key

L.r[j+1]=L.r[j];//记录后移

L.r[j+1]=L.r[0];//插入到正确位置

}

}//InsertSort

(2)希尔排序算法如下:

voidShellInsert(SqList&L,intdk){

for(i=dk+1;i<=n;++i)

if(L.r[i].key

L.r[0]=L.r[i];//暂存在R[0]

for(j=i-dk;j>0&&(L.r[0].key

j-=dk)

L.r[j+dk]=L.r[j];//记录后移,查找插入位置

L.r[j+dk]=L.r[0];//插入

}//if

}//ShellInsert

voidShellSort(SqList&L,intdlta[],intt)

{//增量为dlta[]的希尔排序

for(k=0;k

ShellInsert(L,dlta[k]);

//一趟增量为dlta[k]的插入排序

}//ShellSort

(3)冒泡排序算法如下:

voidBubbleSort(ElemR[],intn){

i=n;

while(i>1){

lastExchangeIndex=1;

for(j=1;j

if(R[j+1].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

while(low=pivotkey)

--high;//从右向左搜索

R[low]=R[high];

while(low

++low;//从左向右搜索

R[high]=R[low];

}

R[low]=R[0];returnlow;

}//Partition

voidQSort(RedType&R[],ints,intt){

//对记录序列R[s..t]进行快速排序

if(s

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;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;i>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;j<=m;j*=2){//j初值指向左孩子

if(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、如果上述

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1