文档介绍:数据结构课程设计
实验报告
内部排序算法比较
08级计算机科学与技术专业
E10814131
郭磊
2010年06月13日
【实验简介】
在教科书各种内部排序算法的时间复杂度分析结果只给出了算法执行的时间的阶,或大概的执行时间,如:直接插入排序即时间复杂度为O(n*n)
通过五组随机数据、一组正序数据与一组逆序数据比较6种常用的内部算法(起泡排序、直接插入排序、简单选择排序、快速查找排序、希尔排序、堆排序)的关键字比较次数和关键字移动次数,以取得直观感受;
用五组不同的长度不小于100的数据进行测试,并对测试结果作出简单的分析,对得出结果拨动大小的进行解释;
【设计模块】
调用
调用
调用
HeapAdjust
主函数
生成随机数
Switch函数
菜单函数
SelectSort
insertSort
BubbleSort
ShellSort
HeapSort
serchSort
QSort
根据菜单函数返回值调用相应的操作函数
【对应模块算法说明】
(1) 此算法程序中需要用到顺序表数据类型,数据元素的类型定义如下:
typedef struct{
KeyType key; //关键字项
}RedType;
typedef struct{
RedType r[MAXSIZE+1]; //0号单元闲置或用作哨兵单元
int length; //顺序表长度
int info; //记录关键字移动次数
int cmp; //关键字的比较次数
}Sqlist;
(2) 本实验用到六种排序算法,一个主函数和菜单函数,其中排序算法分别为起泡排序、直接插入排序、简单选择排序、快速查找排序、希尔排序、堆排序
;相应时间复杂度分析如下:
起泡排序:若待排序列为“正序”,则需进行一趟排序在排序过程中关键字需进行n-1次比较,无须移动纪录;若是“逆序”,则进行n-1趟排序,需n(n-1)/2次比较,并坐等数量级的移动,因此总的事件复杂度为O(n2);
直接插入排序待排序纪录是随机的,关键字间的移动次数和比较次数的平均值约为n*n/4,即时间复杂度为O(n2);
简单的选择排序虽然在排序过程中所需要的移动次数较少,最小时为0,最大时为3(n-1);但是关键字的比较次数总是相同的,均为n(n-1)/2,因此,时间复杂度亦为O(n2);
快速排序其平均时间是kn*㏑n,其中n为待排序列中纪录的个数,k为某个常数,其时间复杂度为O(n*㏑n);
希尔排序当增序序列为dlta[k]=2t-k+1-1时,时间复杂度为O(n3/2),其中t为排序趟数,1≤k≤t≤㏒2(n+1);
堆排序此排序对于含n个元素的序列排序时,总共进行的关键字比较次数不超过4n,且在最坏的情况下,其时间复杂度为O(n*㏑n);
算法分析如下:
①[0],[0]与第(i+1)个记录的关键字比较,若为逆序,则交换第i与第i+1两记录的位置,然后让i加1,重复以上操作,直至i=n-1为止;依次进行第二趟、第三趟……作同样的操作,直至所有的记录按正序排列(一般需要n-1趟比较,[1][n-i+1]依次比较,1≦ i ≦n-i,[n-i+1]的位置)
void BubbleSort(Sqlist *L) //冒泡排序
{
for(i=0;i<L->length;i++)
{
L->r[0]=L->r[1];
for(j=1;j<N-i;j++)
if(L->r[0].key>=L->r[j+1].key)
L->r[j]óL->r[j+1]; //交换两记录的位置
else
L->r[0]=L->r[j+1]; //保证L->r[0]始终为较大的记录
L->r[j+1]=L->r[0]; //把最大的记录放到祠堂排序的最高位置
}
printf(L->r[MAXSIZE]);//输出排序后数组和相关数据
}
②直接插入排序本算法的思路是,把L->r[0]设置为哨兵,排序时把第i个记录复制给哨兵,并于其前的i-1个记录进行比较,找到第一个比起大的记录,利用循环让记录后移,把其放到第一个比起大的记录前面。
void insertSort(Sqlist *L) //直接插入排序
{
for(i=2;i<=L->length;i++)
{
if((L->r[i].key < L->r[i-1].key))
{
L->r[0] = L->r[i]; //复制哨兵
L->r[i] = L->r[