8.排序
8.1概念
1.什么是排序? 排序:将一组杂乱无章的数据按一定规律顺次排列起来。即,将无序序列排成一个有序序列(由小到大或由大到小)的运算。如果参加排序的数据结点包含多个数据域,那么排序往往是针对其中某个域而言。
8.2插入排序
8.2.1直接插入排序
1.基本思想: 每步将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。即边插入边排序,保证子序列中随时都是排好序的。 2.插入方法:
- 在插入a[i]前,数组a的前半段(a[0]----a[i-1])是有序段,后半段(a[i]~a[n-1])是停留于输入次序的“无序段”。
-插入a[i]使a[0]~a[i-1]有序,也就是要为 a[i] 找到有序位置 j (0≤j≤i) ,将a[i]插入在a[j]的位置上。
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[i-1];
for(j=i-2; L.r[0].key<L.r[j].key; --j)
L.r[j+1]=L.r[j];
L.r[j+1]=L.r[0] ;
}
}
3.算法特点: (1)稳定排序。 (2)算法简便,且容易实现。 (3)也适用于链式存储结构,只是在单链表上无需移动记录,只需修改相应的指针。 (4)更适合于初始记录基本有序(正序)的情况,当初始记录无序,n 较大时,此算法时间复杂度较高,不宜采用。
4.直接插入排序在什么情况下效率比较高? 直接插入排序在基本有序时效率较高; 在待排序的记录个数较少时,效率较高。
8.2.2折半插入排序
查找插入位置时采用折半查找法
void BlnsertSort ( SqList &L ) {
for ( i = 2; i <= L.length ; ++i){
L.r[0]= L.r[i];
low = 1 ; high = i-1 ;
while ( low <= high ) {
mid = ( low + high )/2;
if ( L.r[O].key < L.r[mid]. key )
high = mid -1 ;
else low = mid + 1;
}
for ( j=i-1; j>=high+1; -- j ) L.r[j+1] = L.r[j];
}
}
折半插入排序–算法分析:
- 折半查找比顺序查找快,所以折半插入排序就平均性能来说比直接插入排序要快;
- 它所需要的关键码比较次数与待排序对象序列的初始排列无关,仅依赖于对象个数。在插入第i个对象时,需要经过Llog2i」+1次关键码比较,才能确定它应插入的位置;
(1) 当n较大时,总关键码比较次数比直接插入排序的最坏情况要好得多,但比其最好情况要差; (2) 在对象的初始排列已经按关键码排好序或接近有序时,直接插入排序比折半插入排序执行的关键码比较次数要少; - 折半插入排序的对象移动次数与直接插入排序相同,依赖于对象的初始排列。
(1)减少了比较次数,但没有减少移动次数; (2)平均性能优于直接插入排序
8.2.3希尔排序
1.基本思想: 先将整个待排记录序列分割成若干子序列,分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。 2.过程:
3.特点:
- 缩小增量
- 多遍插入排序
- 希尔排序法是一种不稳定的排序算法。
8.3交换排序
1.基本思想: 两两比较,如果发生逆序则交换,直到所有记录都排好序为止。 2.常见的交换排序方法: 冒泡排序,快速排序。
8.3.1冒泡排序
1.思想: 前小后大的原则,让最大的到后面去,注意注意!:直到在某一趟排序过程中没有进行过交换记录的操作,说明序列已全部达到排序要则完成排序。
例1:
例2:
void bubble_sort(SqList &L){
int m,i,j; RedType x;
for(m=1; m<=n-1; m++){
for(j=1; j<=n-m; j++)
if(L.r[j].key>L.r[j+1].key){
x=L.r[j]; L.r[j]=L.r[j+1]; L.r[j+1]=x;
}
}
}
2.特点: 优点: 每趟结束时,不仅能挤出一个最大值到最后面位置,还能同时部分理顺其他元素; 如何提高效率? —旦某一趟比较时不出现记录交换,说明已排好序了,就可以结束本算法。
8.3.2快速排序
1.基本思想:
- 任取一个元素(如:第一个)为中心;
- 所有比它小的元素一律前放,比它大的元素一律后放,形成左右两个子表;
- 对各子表重新选择中心元素并依此规则调整;
- 直到每个子表的元素只剩一个
2.过程:
具体实现:选定一个中间数作为参考,所有元素与之比较,小的调到其左边,大的调到其右边。 中间数(枢轴):可以是第一个数、最后一个数、最中间一个数、任选一个数。
3.算法分析:
-
时间复杂度:平均计算时间是O(nlog2n)。 -
实验结果表明:就平均计算时间而言,快速排序是我们所讨论的所有内排序方法中最好的一个。 -
快速排序是一种不稳定的排序方法。 例如,一次划分后:49与49*相对位置变化。 -
输入数据次序越乱,所选划分元素值的随机性越好,排序速度越快,快速排序不是自然排序方法。 -
改变划分元素的选取方法,至多只能改变算法平均情况的下的世界性能,无法改变最坏情况下的时间性能。即最坏情况下,快速排序的时间复杂性总是O(n2)
8.4选择排序
8.4.1简单选择排序(直接选择排序)
1.基本思想: 在待排序的数据中选出最大(小)的元素放在其最终的|业且。 2.基本操作:
- 首先通过n-1次关键字比较,从n个记录中找出关键字最小的记录,将它与第一个记录交换。
- 再通过n-2次比较,从剩余的n-1个记录中找出关键字次小的记录,将
它与第二个记录交换。 重复上述操作,共进行n-1趟排序后,排序结束。
3.操作规则: 最小的到前面去。
4.特点: 不稳定。
8.4.2归并排序
1.基本思想: 将两个或两个以上的有序子序列“归并”为一个有序序列。 通常采用的是2-路归并排序。
2.过程:
整个归并排序仅需 log2n 趟
3.关键问题: 二如何将两个有序序列合并成一个有序序列。
8.4.3堆排序
8.5总结
|