哈工程数据结构实验报告八系Word格式.docx
《哈工程数据结构实验报告八系Word格式.docx》由会员分享,可在线阅读,更多相关《哈工程数据结构实验报告八系Word格式.docx(15页珍藏版)》请在冰豆网上搜索。
哈尔滨工程大学本科生院制
实验1单链表的实现与应用
------------------------------------------------------------------------------------------------------
【预习部分】
一、实验目的
通过编程实验,进一步增强对单链表的理解和掌握。
二、实验要求
编写程序实现单链表的基本操作(初始化、撤销、插入、删除、取数据元素、求数据元素个数),并设计测试数据,能全面地测试所设计程序的功能。
三、实验原理
1.单链表结构
线性表是一种可以在任意位置插入和删除数据元素操作、由n(n≥0)个相同类型数据元素a0,a1,…,an-1组成的线性结构。
单链表是线性表的一种。
而单链表中构成链表的结点只有一个指向直接后继结点的指针域。
其结构特点是逻辑上相邻的数据元素在物理上不一定相邻。
2.单链表数据插入原理
①要在带头结点的单链表第i(0≤i≤size)个结点前插入一个存放数据元素x的结点,首先要在单链表中寻找到第i-1个结点并由指针p指示,然后动态申请一个结点存储空间并由指针q指示,并把数据元素x的值赋予新结点的数据元素域(即q->
data=x),最后修改新结点的指针域指向ai结点(即q->
next=p->
next),并修改ai-1结点的指针域指向新结点q(即p->
next=q)。
②循环条件由两个子条件逻辑与组成,其中子条件p->
next!
=NULL保证指针所指结点存在,子条件j<
i-1保证最终让指针p指向ai-1结点。
3.单链表数据删除原理
要在带头结点的单链表中删除第i(0≤i≤size-1)个结点,首先要在单链表中寻找到第i-1个结点并由指针p指示,然后让指针s指向ai结点(即s=p->
next),并把数据元素ai的值赋予x(即*x=s->
data),最后把ai结点脱链(即p->
next->
next),并动态释放ai结点的存储空间(即free(s))。
删除过程如图2-14所示。
图中的①对应算法中的删除语句。
四、实验环境
VisualStudio2010
五、实验步骤(程序代码)
//5555.cpp:
定义控制台应用程序的入口点
//
#include"
stdafx.h"
int_tmain(intargc,_TCHAR*argv[])
{
return0;
}
#include<
stdio.h>
stdlib.h>
malloc.h>
typedefintDataType;
typedefstructNode
{
DataTypedata;
structNode*next;
}SLNode;
voidListInitiate(SLNode**head)
*head=(SLNode*)malloc(sizeof(SLNode));
(*head)->
next=NULL;
voidDestroy(SLNode**head)
SLNode*p,*p1;
p=*head;
while(p!
=NULL)
{
p1=p;
p=p->
next;
free(p1);
}
*head=NULL;
intListInsert(SLNode*head,inti,DataTypex)
SLNode*p,*q;
intj;
p=head;
j=-1;
while(p->
=NULL&
&
j<
i-1)
p=p->
j++;
if(j!
=i-1)
printf("
插入位置参数错!
"
);
return0;
}
q=(SLNode*)malloc(sizeof(SLNode));
q->
data=x;
p->
next=q;
return1;
intListDelete(SLNode*head,inti,DataType*x)
SLNode*p,*s;
next!
j++;
s=p->
*x=s->
data;
free(s);
intListGet(SLNode*head,inti,DataType*x)
SLNode*p;
i)
{
=i)
取元素位置参数错!
*x=p->
}
intListLength(SLNode*head)
SLNode*p=head;
intsize=0;
=NULL)
size++;
returnsize;
voidmain(void)
SLNode*head;
inti,x;
ListInitiate(&
head);
for(i=0;
i<
10;
i++)
ListInsert(head,i,i+1);
ListLength(head);
ListGet(head,i,&
x);
printf("
%d"
x);
\n"
ListDelete(head,6,&
x);
Destroy(&
六、实验结果
实验结果如下:
主程序实现的功能为:
建立一个线性表,首先依次输入数据元素1,2,3,…,10,然后删除数据元素7,最后依次显示当前线性表中的数据元素。
由实验结果可知,实验程序正确执行了功能。
七、分析与总结
单链表和顺序表相比,主要优点是不需要预先确定数据元素的最大个数,插入和删除操作不需要移动数据元素;
主要缺点是查找数据元素时需要顺序进行,不能像顺序表那样随机查找任意一个数据元素。
另外,每个结点中要有一个指针域,因此空间单元利用率不高。
而且单链表操作的算法也较复杂。
经过本次实验,我掌握了单链表的基本操作——初始化、撤销、插入、删除、取数据元素、求数据元素个数等,提高了自己的编程能力。
实验2堆栈的实现与应用
通过编程实验,进一步增强对堆栈的理解和掌握。
编写程序实现顺序堆栈的基本操作(初始化、非空否、入栈、出栈、取栈顶数据元素),并设计测试数据,能全面地测试所设计程序的功能。
1.顺序堆栈结构
堆栈定义为限定只能在固定一端进行插入和删除操作的线性表。
其特点是后进先出。
允许进行插入和删除操作的一端称为栈顶,另一端称为栈底。
它的作用是可以完成从输入数据序列到某些输出数据序列的转换。
顺序堆栈是顺序存储结构的堆栈。
顺序栈的存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。
2.数据集合
{a0,a1,…,an-1}ai的数据类型为DataType。
3操作集合
(1)StackInitiate(S):
初始化堆栈
(2)StackNotEmpty(S):
堆栈S非空否
(3)StackPush(S,x):
入栈
(4)StackPop(S,d):
出栈
(5)StackTop(S,d):
取栈顶数据元素
#defineMaxStackSize100
typedefstruct
{DataTypestack[MaxStackSize];
inttop;
}SeqStack;
voidStackInitiate(SeqStack*S)
S->
top=0;
intStackNotEmpty(SeqStackS)
if(S.top<
=0)return0;
elsereturn1;
intStackPush(SeqStack*S,DataTypex)
{if(S->
top>
=MaxStackSize)
堆栈已满无法插入!
else
{S->
stack[S->
top]=x;
top++;
intStackPop(SeqStack*S,DataType*d)
top<
=0)
{printf("
堆栈已空无数据元素出栈!
top--;
*d=S->
top];
intStackTop(SeqStackS,DataType*d)
{if(S.top<
堆栈已空!
{*d=S.stack[S.top-1];
{SeqStackmyStack;
StackInitiate(&
myStack);
i++)
StackPush(&
myStack,i+1);
StackTop(myStack,&
当前栈顶数据元素为:
%d\n,x"
依次出栈的数据元素序列如下:
while(StackNotEmpty(myStack))
{StackPop(&
myStack,&
建立一个顺序堆栈,首先依次输入数据元素1,2,3,......,10,然后依次出栈堆栈中的数据元素并显示。
顺序堆栈与链式堆栈的主要区别在于,顺序栈的实现在于使用了数组这个基本数据结构,数组中的元素在内存中的存储位置是连续的,且编译器要求我们在编译期就要确定数组的大小,这样对内存的使用效率并不高,一来无法避免因数组空间用光而引起的溢出问题,二在系统将内存分配给数组后,则这些内存对于其他任务就不可用;
而对于链栈而言,使用了链表来实现栈,链表中的元素存储在不连续的地址,由于是动态申请内存,所以我们可以以非常小的内存空间开始,另外当某个项不使用时也可将内存返还给系统。
经过本次实验,我掌握了顺序堆栈的基本操作——始化、非空否、入栈、出栈、取栈顶数据元素等,进一步提高了自己的编程能力。
实验3排序、查找算法的实现与应用
通过编程实验,进一步增强对排序、查找算法的理解和掌握。
(1)在[0,999]区间内,随机生成N个整数(N>
=20);
(2)编程实现一种排序算法,对这N个数据进行递增排序;
(3)编程实现一种查找算法,在已排序的数据序列中查找指定数据。
1.排序原理
排序是对数据元素序列建立某种有序排列的过程,是把一个数据元素序列整理成按关键字递增(或递减)排列的过程。
主要有以下几种排序方法:
交换排序的基本思想是利用交换数据元素的位置进行排序的方法。
插入排序的基本思想是每步将一个待排序的数据元素,按其关键码大小,插入到前面已经排好序的一组数据元素的适当位置上,直到数据元素全部插入为止。
选择排序的基本思想是是每次从待排序的数据元素集合中选取关键字最小(或最大)的数据元素放到数据元素集合的最前(或最后),数据元素集合不断缩小,当数据元素集合为空时选择排序结束。
归并排序主要是二路归并排序,基本思想是可以把一个长度为n的无序序列看成是n个长度为1的有序子序列,首先做两两归并,得到n/2个长度为2的有序子序列;
再做两两归并,…,如此重复,直到最后得到一个长度为n的有序序列。
2.查找原理
查找是查询某个关键字是否在(数据元素集合)表中的过程,也称作检索。
常用的一种算法为二分查找(又称折半查找)。
算法的基本思想是先给数据排序(例如按升序排好),形成有序表,然后再将key与正中元素值相比,若key小,则缩小至前半部内查找;
再取其中值比较,每次缩小1/2的范围,直到查找成功或失败为止。
反之,如果key大,则缩小至后半部内查找。
//paixu.cpp:
定义控制台应用程序的入口点。
time.h>
intb[20];
intSelectSort(intb[],intn)
inti,j,small;
inttemp;
n-1;
i++)
{small=i;
//设第i个数据元素关键字最小
for(j=i+1;
n;
j++)//寻找关键字最小的数据元素
if(b[j]<
b[small])small=j;
//记住最小元素的下标
if(small!
=i)//当最小元素的下标不为i时交换位置
temp=b[i];
b[i]=b[small];
b[small]=temp;
for(i=0;
i<
n;
i++)
%d"
b[i]);
"
}
return1;
intBiSearch(intb[],intn,intkey)
{intlow=0,high=n-1;
//确定初始查找区间上下界
intmid;
while(low<
=high)
mid=(low+high)/2;
//确定查找区间中心下标
if(b[mid]==key)return1;
//查找成功
elseif(b[mid]<
key)low=mid+1;
elsehigh=mid-1;
//查找失败
intrandom(intn)
inti,a;
srand((unsignedint)time(NULL));
//当前时间作种子,每次都不同
for(i=0;
n-1;
a=rand();
//生成0~32767之间的一个数值
a=a/200;
b[i]=a;
{inti,n,a,flag;
n=20;
random(n);
\n"
SelectSort(b,n-1);
flag=BiSearch(b,n,60);
if(flag)printf("
已找到"
elseprintf("
未找到"
经检验,程序可以正确实现如下功能:
在[0,999]区间内,随机生成N个整数(N>
=20)、对这N个数据进行递增排序并在已排序的数据序列中查找指定数据。
交换排序主要包括冒泡排序和快速排序两种。
我在实验中采用的是冒泡排序的算法,其基本思想是每趟不断将数据元素两两比较,并按“前小后大”(或“前大后小”)规则交换。
这种排序方法的优点是每趟结束时,不仅能挤出一个最大值到最后面位置,还能同时部分理顺其他元素;
一旦下趟没有交换发生,还可以提前结束排序。
有序顺序表上的查找算法主要有顺序查找和二分查找两种方法。
此次实验中采用的是二分查找算法。
其基本思想是先给数据排序(例如按升序排好),形成有序表,然后再将key与正中元素值相比,若key小,则缩小至前半部内查找;
经过本次实验,我掌握了在[0,999]区间内,随机生成N个整数(N>
=20)的算法,掌握了对这N个数据进行递增排序的算法,掌握了在已排序的数据序列中查找指定数据的算法,进一步提高了自己的编程能力,收获很大。