实验五查找及排序.docx
《实验五查找及排序.docx》由会员分享,可在线阅读,更多相关《实验五查找及排序.docx(22页珍藏版)》请在冰豆网上搜索。
![实验五查找及排序.docx](https://file1.bdocx.com/fileroot1/2023-2/1/d5f08eeb-a45e-47e1-98b8-f79f730a748f/d5f08eeb-a45e-47e1-98b8-f79f730a748f1.gif)
实验五查找及排序
实验五查找及排序
实验课程名:
数据结构与算法
一、实验目的及要求
1、掌握查找的不同方法,并能用高级语言实现查找算法。
2、熟练掌握顺序表的查找方法和有序顺序表的折半查找算法。
3、掌握常用的排序方法,并能用高级语言实现排序算法。
4、深刻理解排序的定义和各种排序方法的特点,并能加以灵活运用。
5、了解各种方法的排序过程及依据的原则,并掌握各种排序方法的时间复杂度的分析方法。
二、实验内容
任务一:
顺序表的顺序查找。
有序表的折半查找。
完成下列程序,该程序实现高考成绩表(如下表所示)的顺序查找,在输出结果中显示查找成功与查找不成功信息。
准考证号
姓名
各科成绩
总分
政治
语文
外语
数学
物理
化学
生物
179328
何芳芳
85
89
98
100
93
80
47
592
179325
陈红
85
86
88
100
92
90
45
586
179326
陆华
78
75
90
80
95
88
37
543
179327
张平
82
80
78
98
84
96
40
558
179324
赵小怡
76
85
94
57
77
69
44
502
解答:
(1)源代码:
#include//EOF(=^Z或F6),NULL
#include//atoi()
#include//eof()
#include//floor(),ceil(),abs()
#include//exit()
#include//cout,cin
//函数结果状态代码
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
//#defineOVERFLOW-2因为在math.h中已定义OVERFLOW的值为3,故去掉此行
typedefintStatus;//Status是函数的类型,其值是函数结果状态代码,如OK等
typedefintBoolean;//Boolean是布尔类型,其值是TRUE或FALSE
#defineMAX_LENGTH100
#include
#include
#include//malloc()等
#include//INT_MAX等
#include//EOF(=^Z或F6),NULL
#include//atoi()
#include//eof()
#include//floor(),ceil(),abs()
#include//exit()
#include//cout,cin
//函数结果状态代码
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
//#defineOVERFLOW-2因为在math.h中已定义OVERFLOW的值为3,故去掉此行
typedefintStatus;//Status是函数的类型,其值是函数结果状态代码,如OK等
typedefintBoolean;//Boolean是布尔类型,其值是TRUE或FALSE
#defineN5//数据元素个数
#defineEQ(a,b)((a)==(b))
#defineLT(a,b)((a)<(b))
#defineLQ(a,b)((a)<=(b))
typedeflongKeyType;//设关键字域为长整型
#definekeynumber//定义关键字为准考证号
structElemType//数据元素类型(以教科书图9.1高考成绩为例)
{
longnumber;//准考证号,与关键字类型同
charname[9];//姓名(4个汉字加1个串结束标志)
intpolitics;//政治
intChinese;//语文
intEnglish;//英语
intmath;//数学
intphysics;//物理
intchemistry;//化学
intbiology;//生物
inttotal;//总分
};
typedefstruct{
ElemType*elem;//数据元素存储空间基址,建表时按实际长度分配,0号单元留空
intlength;//表长度
}SSTable;
voidCreat_Seq(SSTable&ST,ElemTyper[],intn)
{//操作结果:
由含n个数据元素的数组r构造静态顺序查找表ST
inti;
ST.elem=(ElemType*)calloc(n+1,sizeof(ElemType));//动态生成n+1个数据元素空间(0号单元不用)
if(!
ST.elem)
exit(ERROR);
for(i=1;i<=n;i++)
ST.elem[i]=r[i-1];//将数组r的值依次赋给ST
ST.length=n;
}
voidAscend(SSTable&ST)
{//重建静态查找表为按关键字非降序排序
inti,j,k;
for(i=1;i{
k=i;
ST.elem[0]=ST.elem[i];//待比较值存[0]单元
for(j=i+1;j<=ST.length;j++)
ifLT(ST.elem[j].key,ST.elem[0].key)
{
k=j;
ST.elem[0]=ST.elem[j];
}
if(k!
=i)//有更小的值则交换
{
ST.elem[k]=ST.elem[i];
ST.elem[i]=ST.elem[0];
}
}
}
voidCreat_Ord(SSTable&ST,ElemTyper[],intn)
{//操作结果:
由含n个数据元素的数组r构造按关键字非降序查找表ST
Creat_Seq(ST,r,n);//建立无序的查找表ST
Ascend(ST);//将无序的查找表ST重建为按关键字非降序查找表
}
StatusDestroy(SSTable&ST)
{//初始条件:
静态查找表ST存在。
操作结果:
销毁表ST
free(ST.elem);
ST.elem=NULL;
ST.length=0;
returnOK;
}
intSearch_Seq(SSTableST,KeyTypekey)
{//在顺序表ST中顺序查找其关键字等于key的数据元素。
若找到,则返回
//该元素在表中的位置,否则返回0。
算法9.1
inti;
ST.elem[0].key=key;//哨兵
for(i=ST.length;!
EQ(ST.elem[i].key,key);--i);//从后往前找
returni;//找不到时,i为0
}
voidTraverse(SSTableST,void(*Visit)(ElemType))
{//初始条件:
静态查找表ST存在,Visit()是对元素操作的应用函数
//操作结果:
按顺序对ST的每个元素调用函数Visit()一次且仅一次
ElemType*p;
inti;
p=++ST.elem;//p指向第一个元素
for(i=1;i<=ST.length;i++)
Visit(*p++);
}
voidprint(ElemTypec)//Traverse()调用的函数
{
printf("%-8ld%-8s%4d%5d%5d%5d%5d%5d%5d%5d\n",c.number,c.name,c.politics,
c.Chinese,c.English,c.math,c.physics,c.chemistry,c.biology,c.total);
}
intmain()
{
ElemTyper[N]={{179328,"何芳芳",85,89,98,100,93,80,47},
{179325,"陈红",85,86,88,100,92,90,45},
{179326,"陆华",78,75,90,80,95,88,37},
{179327,"张平",82,80,78,98,84,96,40},
{179324,"赵小怡",76,85,94,57,77,69,44}};//数组不按关键字有序
SSTablest;
inti;
longs;
for(i=0;ir[i].total=r[i].politics+r[i].Chinese+r[i].English+r[i].math+r[i].physics+
r[i].chemistry+r[i].biology;
Creat_Seq(st,r,N);//由数组r产生顺序静态查找表st
printf("准考证号姓名政治语文外语数学物理化学生物总分\n");
Traverse(st,print);//按顺序输出静态查找表st
printf("请输入待查找人的考号:
");
scanf("%ld",&s);
i=Search_Seq(st,s);//顺序查找
if(i)
print(st.elem[i]);
else
printf("没找到\n");
Destroy(st);
return0;
}
(2)运行结果:
(3)运行结果分析:
运用顺序结构完成查询。
任务二:
哈希表的开放定址法算法。
在输出结果中显示查找成功与查找不成功信息。
解答:
(1)源代码:
#include
#include
#include//malloc()等
#include//INT_MAX等
#include//EOF(=^Z或F6),NULL
#include//atoi()
#include//eof()
#include//floor(),ceil(),abs()
#include//exit()
#include//cout,cin
//函数结果状态代码
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
//#defineOVERFLOW-2因为在math.h中已定义OVERFLOW的值为3,故去掉此行
typedefintStatus;//Status是函数的类型,其值是函数结果状态代码,如OK等
typedefintBoolean;//Boolean是布尔类型,其值是TRUE或FALSE
#defineEQ(a,b)((a)==(b))
#defineLT(a,b)((a)<(b))
#defineLQ(a,b)((a)<=(b))
#defineN11//数据元素个数
#defineSUCCESS1
#defineUNSUCCESS0
#defineDUPLICATE-1
#defineNULL_KEY0//0为无记录标志
#defineN10//数据元素个数
typedefintKeyType;//设关键字域为整型
structElemType//数据元素类型
{
KeyTypekey;
intord;
};
inthashsize[]={11,19,29,37};//哈希表容量递增表,一个合适的素数序列
intm=0;//哈希表表长,全局变量
structHashTable
{
ElemType*elem;//数据元素存储基址,动态分配数组
intcount;//当前数据元素个数
intsizeindex;//hashsize[sizeindex]为当前容量
};
voidInitHashTable(HashTable&H)
{//操作结果:
构造一个空的哈希表
inti;
H.count=0;//当前元素个数为0
H.sizeindex=0;//初始存储容量为hashsize[0]
m=hashsize[0];
H.elem=(ElemType*)malloc(m*sizeof(ElemType));
if(!
H.elem)
exit(OVERFLOW);//存储分配失败
for(i=0;iH.elem[i].key=NULL_KEY;//未填记录的标志
}
voidDestroyHashTable(HashTable&H)
{//初始条件:
哈希表H存在。
操作结果:
销毁哈希表H
free(H.elem);
H.elem=NULL;
H.count=0;
H.sizeindex=0;
}
unsignedHash(KeyTypeK)
{//一个简单的哈希函数(m为表长,全局变量)
returnK%m;
}
voidcollision(int&p,intd)//线性探测再散列
{//开放定址法处理冲突
p=(p+d)%m;
}
StatusSearchHash(HashTableH,KeyTypeK,int&p,int&c)
{//在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据
//元素在表中位置,并返回SUCCESS;否则,以p指示插入位置,并返回UNSUCCESS
//c用以计冲突次数,其初值置零,供建表插入时参考。
算法9.17
p=Hash(K);//求得哈希地址
while(H.elem[p].key!
=NULL_KEY&&!
EQ(K,H.elem[p].key))
{//该位置中填有记录.并且关键字不相等
c++;
if(ccollision(p,c);//求得下一探查地址p
else
break;
}
ifEQ(K,H.elem[p].key)
returnSUCCESS;//查找成功,p返回待查数据元素位置
else
returnUNSUCCESS;
//查找不成功(H.elem[p].key==NULL_KEY),p返回的是插入位置
}
StatusInsertHash(HashTable&,ElemType);//对函数的声明
voidRecreateHashTable(HashTable&H)
{//重建哈希表
inti,count=H.count;
ElemType*p,*elem=(ElemType*)malloc(count*sizeof(ElemType));
p=elem;
printf("重建哈希表\n");
for(i=0;iif((H.elem+i)->key!
=NULL_KEY)//该单元有数据
*p++=*(H.elem+i);
H.count=0;
H.sizeindex++;//增大存储容量
m=hashsize[H.sizeindex];
p=(ElemType*)realloc(H.elem,m*sizeof(ElemType));
if(!
p)
exit(OVERFLOW);//存储分配失败
H.elem=p;
for(i=0;iH.elem[i].key=NULL_KEY;//未填记录的标志(初始化)
for(p=elem;pInsertHash(H,*p);
}
StatusInsertHash(HashTable&H,ElemTypee)
{//查找不成功时插入数据元素e到开放定址哈希表H中,并返回OK;
//若冲突次数过大,则重建哈希表,算法9.18
intc,p;
c=0;
if(SearchHash(H,e.key,p,c))//表中已有与e有相同关键字的元素
returnDUPLICATE;
elseif(c{//插入e
H.elem[p]=e;
++H.count;
returnOK;
}
else
{
RecreateHashTable(H);//重建哈希表
returnUNSUCCESS;
}
}
voidTraverseHash(HashTableH,void(*Vi)(int,ElemType))
{//按哈希地址的顺序遍历哈希表
printf("哈希地址0~%d\n",m-1);
for(inti=0;iif(H.elem[i].key!
=NULL_KEY)//有数据
Vi(i,H.elem[i]);
}
StatusFind(HashTableH,KeyTypeK,int&p)
{//在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据
//元素在表中位置,并返回SUCCESS;否则,返回UNSUCCESS
intc=0;
p=Hash(K);//求得哈希地址
while(H.elem[p].key!
=NULL_KEY&&!
EQ(K,H.elem[p].key))
{//该位置中填有记录.并且关键字不相等
c++;
if(ccollision(p,c);//求得下一探查地址p
else
returnUNSUCCESS;//查找不成功(H.elem[p].key==NULL_KEY)
}
ifEQ(K,H.elem[p].key)
returnSUCCESS;//查找成功,p返回待查数据元素位置
else
returnUNSUCCESS;//查找不成功(H.elem[p].key==NULL_KEY)
}
voidprint(intp,ElemTyper)
{
printf("address=%d(%d,%d)\n",p,r.key,r.ord);
}
intmain()
{
ElemTyper[N]={{17,1},{60,2},{29,3},{38,4},{1,5},{2,6},{3,7},{4,8},{60,9},{13,10}};
HashTableh;
inti,p;
Statusj;
KeyTypek;
InitHashTable(h);
for(i=0;i{//插入前N-1个记录
j=InsertHash(h,r[i]);
if(j==DUPLICATE)
printf("表中已有关键字为%d的记录,无法再插入记录(%d,%d)\n",r[i].key,r[i].key,r[i].ord);
}
printf("按哈希地址的顺序遍历哈希表:
\n");
TraverseHash(h,print);
printf("请输入待查找记录的关键字:
");
scanf("%d",&k);
j=Find(h,k,p);
if(j==SUCCESS)
print(p,h.elem[p]);
else
printf("没找到\n");
j=InsertHash(h,r[i]);//插入第N个记录
if(j==ERROR)//重建哈希表
j=InsertHash(h,r[i]);//重建哈希表后重新插入
printf("按哈希地址的顺序遍历重建后的哈希表:
\n");
TraverseHash(h,print);
printf("请输入待查找记录的关键字:
");
scanf("%d",&k);
j=Find(h,k,p);
if(j==SUCCESS)
print(p,h.elem[p]);
else
printf("没找到\n");
DestroyHashTable(h);
return0;
}
(2)运行结果:
(3)运行结果分析:
运用哈希表开放定地址算法实现。
任务三:
各种插入排序算法的实现。
解答:
(1)源代码:
#include
#include
#include//malloc()等
#include//INT_MAX等
#include//EOF(=^Z或F6),NULL
#include//atoi()
#include//eof()
#include//floor(),ceil(),abs()
#include//exit()
#include//cout,cin
//函数结果状态代码
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
//#defineOVERFLOW-2因为在math.h中已定义OVERFLOW的值为3,故去掉此行
typedefintStatus;//Status是函数