常用排序算法之选择排序 ( 直接选择排序、堆排序 )

选择排序的方法是:每次从待排序的数据元素集合中选取关键字最小(或最大)的数据元素放到数据元素集合的最前(或最后),数据元素集合不断缩小,当数据元素集合为空时选择排序结束。常用的选择排序有直接选择排序和堆排序。

 

直接选择排序

方法:从待排序的数据元素集合中选取关键字最小的数据元素并将它与原始数据元素集合中的第一个数据元素交换位置;然后从不包括第一个位置上数据元素的集合选取关键字最小的数据元素并将它与原始数据元素集合中的第二个数据元素交换位置;如此重复,直到数据元素集合中中剩下一个数据元素为止。

C++实现:

《常用排序算法之选择排序 ( 直接选择排序、堆排序 )》
《常用排序算法之选择排序 ( 直接选择排序、堆排序 )》
SelectSort.cpp

   
    
     1 
    void
     SelectSort( DataType a[], 
    int
     n )
2 {
3 int i, j, small;
4 DataType temp;
5
6 for ( i = 0 ; i < n - 1 ; i ++ )
7 {
8 small = i;
9 for ( j = i + 1 ; j < n; j ++ )
10 {
11 if ( a[j].key < small.key )
12 small = j;
13 }
14 if ( small != i )
15 {
16 temp = a[i];
17 a[i] = a[small];
18 a[small] = temp;
19 }
20 }
21 }

时间复杂度:第1次排序要进行 n-1 次比较,第2次排序要进行 n-2 次比较,… ,第 n-1 次排序要进行1次比较,所以总的比较次数为:

比较次数 = (n-1) + (n-2) + … + 1 = n(n-1)/2

在各次排序中,数据元素的移动次数最好为0次,最坏为3次。所以总的移动次数最好为0次,最坏为 3(n-1) 次。因此,直接选择排序算法的时间复杂度为 O(n^2) 。

空间复杂度为 O(1) 。

直接选择排序由于每次都要从无序记录区选出最小记录后,与无序区的第一个记录交换,而交换可能引起关键字相同的数据元素位置发生变化。所以它是不稳定的排序算法。如果在选出最小记录后,将它前面的无序记录依次后移,然后再将最小记录放在有序区的后面,这样就能保证排序算法的稳定性。

———————————————————————————

堆排序

基本思想:在直接选择排序中,待排序的数据元素集合构成一个线性结构,要从有n个数据元素的线性表中选择出一个最小的数据元素需要比较n-1次。如果能把待排序的数据元素集合构成一个完全二叉树结构,而每次选择出一个最大(或最小)的数据元素只需比较完全二叉树的高度次,即 lbn 次,则排序算法的时间复杂度就是 O(n x lbn) 。

方法:构造一个最大堆并循环执行如下过程直到数组为空:

    <1>. 把堆顶 a[0] 元素(为最大元素)和当前最大堆的最后一个元素交换。

    <2>. 最大堆元素个数减 1 。

    <3>. 由于第<1>步后根结点不再满足最大堆的定义,所以调整根结点使之满足最大堆的定义。

堆排充是一种不稳定的排序方法。

时间复杂度: O(n x lbn) 。

空间复杂度: O(1) 。

 

 

 

 

 

点赞