一、前言
前面我们讲了直接插入排序和希尔排序这两种插入排序,如果还有什么问题就请点击下面的链接
那么今天我们就来讲一讲选择排序。
二、选择排序
基本思想: 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。
三、直接选择排序
*在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素。
* 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换。
* 在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素。
如下图:
注:除了上面的图所演示的每次选一个最大或最小的数这种方法外,我们还可以同时选出最大和最小的数直接进行排序。为了实现这种方法,我们可以使用两个指针,同时从数组的两边进行移动,选出最大和最小的,放到数组的两边,然后指针分别往后和往前移动一步。直到两个指针相遇或错过。
* 代码实现如下:
void SelectSort(int* a, int n) { int begin = 0; int end = n - 1; while(begin < end) { int maxi = begin; int mini = begin; for(int i = 0; i <= end; i++) { if(a[i] > a[maxi]) { maxi = i } if(a[i] < a[mini]) { mini = i; } } swap(&a[begin], &a[mini]); if(begin == maxi) maxi = mini swap(&a[end], &a[maxi]); begin++; end--; } }
直接选择排序的特性总结:
1、 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用。
2.、时间复杂度:O(N^2)。
3、空间复杂度:O(1)。
4.、稳定性:不稳定。
四、堆排序
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。(以下我们以排降序为例)
代码实现如下:
向下调整算法:
void AdjustDown(int* a, int n, int root) { int parent = root; int child = parent * 2 + 1;//先默认最小的是左孩子 while (child < n) { if (child + 1 < n && a[child + 1] < a[child])//找出小的那个孩子,右孩子要存在 { child += 1; } if (a[child] < a[parent]) { Swap(&a[child], &a[parent]); parent = child; child = parent * 2 + 1; } else { break; } } }
void HeapSort(int* a, int n) { //建堆,对于任何一棵树(左右子树可能都不是小堆),要建成堆,就从最后一个非叶子节点进行向下调整 for (int i = (n - 1 - 1) / 2; i >= 0; i--) { AdjustDown(a, n, i); } //进行排序 int end = n - 1; while(end > 0) { swap(&a[0], &a[end]); //重新建堆 AdjustDown(a, end, 0); end--; } }
我们来简单测试一下堆排序:
int main() { int a[10] = { 6,4,3,7,9,86,1,5,0,2}; int size = sizeof(a) / sizeof(int); HeapSort(a, size); for (int i = 0; i < 10; i++) { printf("%d ", a[i]); } printf("\n"); return 0; }
运行结果如下:
直接选择排序的特性总结:
1. 堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度:O(N*logN)。
3. 空间复杂度:O(1)。
4. 稳定性:不稳定。