排序实验报告.docx
- 文档编号:10989089
- 上传时间:2023-02-24
- 格式:DOCX
- 页数:27
- 大小:322.73KB
排序实验报告.docx
《排序实验报告.docx》由会员分享,可在线阅读,更多相关《排序实验报告.docx(27页珍藏版)》请在冰豆网上搜索。
排序实验报告
《数据结构》
课程设计报告
专业计算机科学与技术
班级
姓名
学号
指导教师
起止时间2012.12~2013.1
课程设计:
排序综合
一、任务描述
排序综合
任务:
利用随机函数产生n个随机整数(20000以上),对这些数进行多种方法进行排序。
要求:
(1)至少采用三种方法实现上述问题求解(提示,可采用的方法有插入排序、希尔排序、起泡排序、快速排序、选择排序、堆排序、归并排序)。
并把排序后的结果保存在不同的文件中。
(2)统计每一种排序方法的性能(以上机运行程序所花费的时间为准进行对比),找出其中两种较快的方法。
二、问题分析
1、功能分析
分析设计课题的要求,要求编程实现以下功能:
(1)排序表的建立—即创建顺序表;
(2)顺序表的排序—即直接插入排序、希尔排序、起泡排序、快速排序、简单选择排序操作;
(3)统计每一种排序方法的性能—即测试上机运行程序所花费的时间;
2、数据对象分析
数据信息:
随机整数
数据数量可以预先确定(20000以上)
三、数据结构设计
使用顺序表实现,有关定义如下:
typedefintStatus;
typedefintKeyType;//设排序码为整型量
typedefintInfoType;
typedefstruct{//定义被排序记录结构类型
KeyTypekey;//排序码
InfoTypeotherinfo;//其它数据项
}RedType;
typedefstruct{
RedType*r;//存储带排序记录的顺序表
//r[0]作哨兵或缓冲区
intlength;//顺序表的长度
}SqList;//定义顺序表类型
四、功能设计
(一)主控菜单设计
为实现通各种排序的功能,首先设计一个含有多个菜单项的主控菜单程序,然后再为这些菜单项配上相应的功能。
程序运行后,给出6个菜单项的内容和输入提示,如下:
1.直接插入排序
2.希尔排序
3.起泡排序
4.快速排序
5.简单选择排序
0.退出系统
(二)程序模块结构
由课题要求可将程序划分为以下几个模块(即实现程序功能所需的函数):
●主控菜单项选择函数menu()
●创建排序表函数InitList_Sq()
●对顺序表L进行直接插入排序函数Insertsort()
●希尔排序函数ShellSort();
●起泡排序函数Bubble_sort()
●快速排序函数QSort()
●简单选择排序函数SelectSort()
(三)函数调用关系
程序的主要结构(函数调用关系)如下图所示。
Menu()InitList_Sq(L)
Main()
Insertsort(L)ShellSort()Bubble_sort()QSort()SelectSort()
其中main()是主函数,它进行菜单驱动,根据选择项0~5调用相应的函数。
main()函数使用for循环实现重复选择。
其循环结构如下:
for(;;)
{
longstart,end;
switch(menu())
{
case1:
printf("*直接插入排序*\n");
start=clock();
Insertsort(L);
end=clock();
printf("%dms\n",end-start);
fp=fopen("D:
直接插入排序.txt","w");
if(fp==NULL)//打开文件失败
{
printf("打开文件失败!
\n");
exit
(1);
}
for(i=1;i<=L.length;i++)
fprintf(fp,"%d",L.r[i]);
fclose(fp);
break;
case2:
printf("*希尔排序*\n");
start=clock();
ShellSort(L,an,14);
end=clock();
printf("%dms\n",end-start);
fp=fopen("D:
希尔排序.txt","w");
if(fp==NULL)//打开文件失败
{
printf("打开文件失败!
\n");
exit
(1);
}
for(i=1;i<=L.length;i++)
fprintf(fp,"%d",L.r[i]);
fclose(fp);
break;
case3:
printf("*起泡排序*\n");
start=clock();
Bubble_sort(L);
end=clock();
printf("%dms\n",end-start);
fp=fopen("D:
起泡排序.txt","w");
if(fp==NULL)//打开文件失败
{
printf("打开文件失败!
\n");
exit
(1);
}
for(i=1;i<=L.length;i++)
fprintf(fp,"%d",L.r[i]);
fclose(fp);
break;
case4:
printf("*快速排序*\n");
start=clock();
QSort(L,0,L.length);
end=clock();
printf("%dms\n",end-start);
fp=fopen("D:
快速排序.txt","w");
if(fp==NULL)//打开文件失败
{
printf("打开文件失败!
\n");
exit
(1);
}
for(i=1;i<=L.length;i++)
fprintf(fp,"%d",L.r[i]);
fclose(fp);
break;
case5:
printf("*简单选择排序*\n");
start=clock();
SelectSort(L);
end=clock();
printf("%dms\n",end-start);
fp=fopen("D:
简单选择排序.txt","w");
if(fp==NULL)//打开文件失败
{
printf("打开文件失败!
\n");
exit
(1);
}
for(i=1;i<=L.length;i++)
fprintf(fp,"%d",L.r[i]);
fclose(fp);
break;
case0:
printf("\t退出!
\n");
return;
}
}
(四)文件结构
1、sort.h:
顺序表相关的定义与函数声明
2、sort.cpp:
顺序表排序运算的实现
3、menu.h:
主菜单函数的声明
4、menu.cpp:
主菜单函数的实现
5、mn.cpp:
主函数
(五)各函数的算法设计
1、InitList_Sq()
算法原理:
数组指针r指示线性表的基址,length指示线性表的当前长度,将随机生成的数赋给线性表,并生成相应文件。
流程图:
开始
申请内存
随机生成30000个数字
生成文件
Fp=NULL
将顺序表打印到文件内终止程序
关闭文件
结束
代码描述:
StatusInitList_Sq(SqList&L)
{//构造一个线性表
FILE*fp;
L.r=(RedType*)malloc(LIST_INIT_SIZE*sizeof(RedType));
if(!
L.r)exit(OVERFLOW);//存储分配失败
L.length=30001;//表长度为30001
srand((unsigned)time(NULL));
for(inti=1;i<=L.length;i++)
L.r[i].key=rand()%30001+1;
fp=fopen("D:
构造一个线性表.txt","w");
if(fp==NULL)//打开文件失败
{
printf("打开文件失败!
\n");
exit
(1);
}
for(i=1;i<=L.length;i++)
fprintf(fp,"%d",L.r[i]);
fclose(fp);
returnOK;
}//InitList_Sq
算法的时间复杂度分析:
O(n)
2、Insertsort()
算法原理:
每步将一个待排序的对象,按其排序码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。
在已形成的有序表中顺序查找,并在适当位置插入,把原来位置上的元素向后顺移。
流程图:
开始
i=2
i 是 L.r[i].key 是 L.r[0]=L.r[i] j=i-1 L.r[0].key 是 L.[j+1]=L.r[j] j-- L.r[j+1]=L.r[0] i++ 结束 代码描述: voidInsertsort(SqList&L)//对顺序表L进行直接插入排序 {for(inti=2;i<=L.length;i++) if(LT(L.r[i].key,L.r[i-1].key))//需将L.r[i]插入有序表 {L.r[0]=L.r[i];//复制为“哨兵”,暂存 for(intj=i-1;LT(L.r[0].key,L.r[j].key);j--) L.r[j+1]=L.r[j]; //位置j指示了第一个key≤L.r[i].key的元素 L.r[j+1]=L.r[0];//将暂存在r[0]中的记录插入到正确位置 }} 算法的时间复杂度分析: O(n2) 3、ShellInsert() 算法原理: 1、分组、组内直接插入排序;2、组数逐次减小;3、组数=1,结束。 流程图: 开始 i=dk+1 i 是 L.r[i].key 是 L.r[0]=L.r[i] j=i-dk (j>0)&&(LT(L.r[0].key,L.r[j].key)否 是 L.r[j+dk]=L.r[j] j-=dk L.r[j+dk]=L.r[0] i++ 结束 代码描述: voidShellInsert(SqList&L,intdk) {//一趟Shell排序,dk为步长 inti; for(i=dk+1;i<=L.length;i++) { if(LT(L.r[i].key,L.r[i-dk].key)) { L.r[0]=L.r[i]; intj; for(j=i-dk;(j>0)&&(LT(L.r[0].key,L.r[j].key));j-=dk) L.r[j+dk]=L.r[j]; L.r[j+dk]=L.r[0]; } } } 4、 ShellSort() 流程图: 开始 k=0 k ShellInsert(L,dlta[k]) k++ 结束 代码描述: voidShellSort(SqList&L,intdlta[],intt) {//Shell排序,dlta[]为增量序列,t为增量个数 intk; for(k=0;k ShellInsert(L,dlta[k]); }//ShellSort 算法的时间复杂度分析: O(n(㏒2n)2) 5、Bubble_sort() 算法原理: 每趟不断将记录两两比较,若发现逆序,则交换两个记录,使排序码较小的元素逐渐从后部移向前部(就象水底的气泡一样逐渐向上冒)。 流程图: 开始 n=L.length i=1 i flag=0 j=n-1 j<=i L.r[j+1].key flag=1 L.r[j]←→L.r[j+1] j-- flag=0 i++ 结束 代码描述: voidBubble_sort(SqList&L) { RedTypex; intn; n=L.length;//表长 for(inti=1;i {intflag=0;//进入循环,清标志 for(intj=n-1;j>=i;j--) if(LT(L.r[j+1].key,L.r[j].key)) { flag=1;//有交换,置标志 x=L.r[j];//L.r[j]←→L.r[j+1] L.r[j]=L.r[j+1]; L.r[j+1]=x; } if(flag==0)break;//若无交换则可结束冒泡排序 } } 算法的时间复杂度分析: O(n2) 6、Partition() 算法原理: 从n个待排记录中任取一个记录Ri作标准,调整序列中各个记录的位置,使得: 排在ri前的记录排序码<=ri.key排在ri后的排序码,该过程为一趟快速排序。 这样就确定了Ri在序列中的最终位置,同时将序列分成两个子序列。 流程图: 开始 L.r[0]=L.r[low] Pivotkey=L.r[low].key Low 是 low 是 --high L.r[low]←→L.r[high] low 是 ++low L.r[low]←→L.r[high] L.r[low]=L.r[0] returnlow 结束 代码描述: intPartition(SqList&L,intlow,inthigh){ /*交换子表r[low…high]的记录,使枢轴记录到位,并返回其位置。 返回时,在枢轴之前的记录排序码均不大于其排序码,之后的记录排序码均不小于其排序码。 */ L.r[0]=L.r[low];//以子表的首记录作为枢轴,放入r[0]单 intpivotkey; pivotkey=L.r[low].key;//取枢轴的排序码存入pivotkey变量 while(low RedTypex; RedTypet; while(low x=L.r[low]; L.r[low]=L.r[high]; L.r[high]=x;//将比枢轴排序码小的记录交换到低端 while(low t=L.r[high]; L.r[high]=L.r[low]; L.r[low]=t;//将比枢轴排序码大的记录交换到高端 } L.r[low]=L.r[0];//枢轴记录到位 returnlow;//返回枢轴记录所在位置 }//Partition 7、QSort() 算法原理: 1、对Partition()确定的两个子序列分别进行快速排序,则又可确定2个记录在序列中的最后位置,同时将序列分成4个子序列。 2、重复直至每个序列的长度均为1时,全部记录排序完毕。 流程图: 开始 Low pivotloc=Partition(L,low,high) QSort(L,low,pivotloc-1) QSort(L,pivotloc+1,high) 结束 代码描述: voidQSort(SqList&L,intlow,inthigh){//对顺序表L中的子序列r[low…high]作快速排序 if(low intpivotloc; pivotloc=Partition(L,low,high);//一趟快排,将r[]一分为二 QSort(L,low,pivotloc-1);//在左子区间进行递归快排,直到长度为1 QSort(L,pivotloc+1,high);//在右子区间进行递归快排,直到长度为1 } } 算法的时间复杂度分析: O(nlogn) 8、SelectSort() 算法原理: 第1趟: 从R[1]~R[n]中选取最小值,与R[1]交换; 第2趟: 从R[2]~R[n]中选取最小值,与R[2]交换; ……………………… 第i趟: 从R[i]~R[n]中选取最小值,与R[i]交换; ……………………… 第n-1趟: 从R[n-1]~R[n]中选取最小值,与R[n-1]交换. 共通过n-1趟,得到一个按排序码从小到大排列的有序序列 流程图: 开始 i=1 i 是 k=i j=i+1 j<=L.length否 是 L.r[j].key k=j k! =i否 是 L.r[i]←→L.r[j] ++j ++i 结束 代码描述: voidSelectSort(SqList&L) {//对顺序表进行简单选择排序 RedTypex; for(inti=1;i {//在L.r[i..L.length]中选择key最小的记录 intk=i; for(intj=i+1;j<=L.length;j++) if(LT(L.r[j].key,L.r[k].key))k=j; if(k! =i){ x=L.r[i]; L.r[i]=L.r[j]; L.r[j]=x; } } }//SelectSort 算法的时间复杂度分析: 算法的改进方法(这部分可以选择): 五、测试数据和结果 1、测试数据 随机产生30000个数 2、测试结果 本程序在VC++环境下实现,下面是对以上测试数据的运行结果。 (1)主菜单显示如下: (2)建立通信录单链表: 六、结束语 本设计完成了课题要求的任务,较熟练地运用了顺序表来解决问题,实现了顺序表的各种排序的基本算法,设计了较便捷的操作界面。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 排序 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)