实验4 排序算法.docx
《实验4 排序算法.docx》由会员分享,可在线阅读,更多相关《实验4 排序算法.docx(13页珍藏版)》请在冰豆网上搜索。
实验4排序算法
数据结构实验报告
实验名称:
实验4——用简单数组实现排序
学生姓名:
班级:
班内序号:
运行环境:
VS20102010
学号:
日期:
1.实验要求
实验目的
通过选择下面两个题目之一,学习、实现、对比各种排序算法,掌握各种排序算法的优劣,以及各种算法使用的情况。
1.实验要求
使用简单数组实现下面各种排序算法,并进行比较。
排序算法:
1、插入排序
2、希尔排序
3、冒泡排序
4、快速排序
5、简单选择排序
6、堆排序(选作)
7、归并排序(选作)
8、基数排序(选作)
9、其他
要求:
1、测试数据分成三类:
正序、逆序、随机数据
2、对于这三类数据,比较上述排序算法中关键字的比较次数和移动次数(其中关键字交换计为3次移动)。
3、对于这三类数据,比较上述排序算法中不同算法的执行时间,精确到微秒(选作)
4、对2和3的结果进行分析,验证上述各种算法的时间复杂度
编写测试main()函数测试线性表的正确性
2.程序分析
2.1存储结构
数组:
数组下标:
0123456
数组元素
R7
R6
R5
R4
R3
R2
R1
2.2关键算法分析
(1)直接插入选择排
基本思想:
每次将一个待排序的记录按其关键码的大小插入到一个已经排序好的有序序列中,直到全部记录排序好。
设置r[0]为“哨兵”,从后向前查找有序区,边查找边后移,直到找到合适的位置,将r[0]插入。
每比较一次,k自增,每移动一次,m自增,最后输出m,k的值
}
voidInsertSort(intr[],intn)//插入排序
{
intk=0;
intm=0;
intj;
for(inti=2;i<=n;i++)//n-1趟排序
{
k++;
if(r[i]{
r[0]=r[i];//将待插入记录赋值给哨兵r[0]
r[i]=r[i-1];
m++;
for(j=i-1;r[0]{
r[j+1]=r[j];//元素后移
k++;
m++;
}
m++;
r[j+1]=r[0];//插入记录
}
}
cout<"<cout<<"比较次数:
"<}
时间复杂度:
O(n2)空间复杂度O
(1)
(2)希尔排序
基本思想:
将待排序的记录集分成多个子集,分别对这些子集进行排序,待整个序列基本有序时,在对记录进行一次直接插入排序。
设待排序对象序列有n个记录,先取dfor(intd=n/2;d>=1;d=d/2)
for(inti=d+1;i<=n;i++)
2然后缩小间隔d,例如取d=d/2,重复上述的子序列划分和排序工作。
3直到最后取d=1,将所有对象放在同一个序列中排序为止。
for(intd=n/2;d>=1;d=d/2)//以d为a增量?
{
for(inti=d+1;i<=n;i++)//一°?
趟希尔排序¨°
{
k++;
if(r[i]{
r[0]=r[i];
move++;
for(j=i-d;j>0&&r[0]{
r[j+d]=r[j];
k++;
move++;
}
r[j+d]=r[0];
}
}
}
时间复杂度O(n2)和O(nlog2n)之间
(3)冒泡排序
两两比较相邻的记录,如果反序,则交换位置,直到没有反序的记录为止。
voidBubbleSort(intr[],intn)
{
//外循环:
总共需要遍历的趟数
for(inti=1;i<=n;i++)//n-1趟排序
//内循环:
每一趟需要比较的次数
for(intj=0;j<=n-i;j++)
{
k++;
if(r[j]>r[j+1])//相邻记录比较
{
move+=3;
r[0]=r[j];
r[j]=r[j+1];
r[j+1]=r[0];
}
}}
时间复杂度O(n2)空间复杂度O
(1)
(4)快速排序
基本思想:
1.选择一个记录作为轴值,将记录分成2部分。
分别对这两部分重复上述过程。
①初始化
取第一个记录作为基准,保存在任意位置
i基准左侧待比较的记录,初始i=1
j基准右侧待比较的记录,初始j=n
②右侧扫描
从后向前找到第一个比基准小的记录,移至位置i
③左侧扫描
从前到后找到第一个比基准大的记录,移至位置j
反复执行②③,直到i=j结束,将r[0]移至r[i]。
一趟快速排序
:
intPartion(intr[],inti,intj,int&p,int&q)
{
intpivot=r[i];//选取基准记录
while(i{
while((i=pivot))//右侧扫描
{j--;p++;//比较次数
}
r[i]=r[j];
q++;
while((i{i++;
p++;//比较次数
}
r[j]=r[i];
q++;//移动次数
}
r[i]=pivot;
q++;
returni;
利用递归排遍所有的数
voidQsort(intr[],inti,intj,int&p,int&q)//p记录比较次数,q记录移动次数
{
if(i{
intpivotloc=Partion(r,i,j,p,q);//调用Partion2关键函数
Qsort(r,i,pivotloc-1,p,q);
Qsort(r,pivotloc+1,j,p,q);
}
}
(54)选择排序
基本思想:
第i趟排序在无序序列r[i..n]中选择关键码最小的记录,与r[i]交换,使有序序列不断增长直到全部排序完毕
1,假设无序区的r[i]是最小记录,附设一个变量index=i,然后依次将后续的记录与r[index]比较,如果比r[index]小,则index记录该位置。
2,比较完毕,交换r[index]和r[i]的记录。
intindex=i;//假设index是最小的
for(intj=i+1;j<=n;j++)//选择最小记录的位置
if(r[j]index=j;
}
for(inti=1;i{
intindex=i;//假设index为最小
for(intj=i+1;j<=n;j++)//查找最小记录的位置
{k++;
if(r[j]index=j;
}
if(index!
=i)//若第一个就是最小元素,不需交换
{
move+=3;
r[0]=r[i];
r[i]=r[index];
r[index]=r[0];//以r[0]作为临时空间交换记录
}
排序方法
平均情况
最好情况
最坏情况
辅助空间
直接插入排序
O(n2)
O(n)
O(n2)
O
(1)
希尔排序
O(nlog2n)~O(n2)
O(n1.3)
O(n2)
O
(1)
起泡排序
O(n2)
O(n)
O(n2)
O
(1)
快速排序
O(nlog2n)
O(nlog2n)
O(n2)
O(log2n)~O(n)
简单选择排序
O(n2)
O(n2)
O(n2)
O
(1)
堆排序
O(nlog2n)
O(nlog2n)
O(nlog2n)
O
(1)
归并排序
O(nlog2n)
O(nlog2n)
O(nlog2n)
O(n)
排序方法
最好情况
最坏情况
平均情况
直接插入排序
O(n)
O(n2)
O(n2)
起泡排序
0
O(n2)
O(n2)
简单选择排序
0
O(n)
O(n)
(6)比较程序执行时间
1,利用clock()函数,设置起始点,结束点,
定义一个100000大小的数组,产生100000个随机数
用不同的算法进行排序,显示执行时间
2.3其他
该程序运行时需要手动修改注释符
1.程序运行结果
2.
计算时间时数组数量级100000
快速排序用时最少
3.总结
出现的问题:
开始发现第一个算法移动次数正确,而以后各算法移动次数,比较次数均不正确
原因:
经第一次排序后,无序数就变为了有序数组,因而导致错误
解决办法:
每次只调用一种算法
心的:
排序过程通常要进行下列两种基本操作1.关键码之间的比较2.移动;记录从一个位置移动到另一个位置。
所以在待排序的个数一定的情况下,算法的执行时间主要消耗在关键码之间的比较和记录的移动上,因此高效率的算法应该尽可能少的关键码比较次数和记录的移动次数。
评价排序算法的另一个主要指标是执行算法所需要的辅助存储空间
总结:
稳定的排序:
直接插入排序,起泡排序,简单选择排序,归并排序
不稳定的排序:
希尔排序,快速排序,堆排序,在面对具体特点的序列时要灵活选择相应排序算法
改进:
函数的主程序需要改进,使其可以由操作者自由选择和输入数据排序而不需要每次修改代码使其运行