选择排序:每一趟在n-i+1个有数据中选取最大(小)的数据,作为有序数组的第i个元素。
直接选择排序:
- 在元素集合array[i]~array[j]中选择关键码最小的元素
- 若他不是这组元素中的第一个元素,就将它与这组元素中的第一个元素交换
- 在剩余的array[i+1]~array[n-1]集合中,重复以上步骤,直到结合只剩下一个元素,排序完成
代码实现:
void SelectSort(int array[], int size){
int min;//记录最小元素的下标
for (int i = 0; i < size - 1; i++){
min = i;
for (int j = i + 1; j < size; j++){
if (array[j] < array[min]){
min = j;
}
}
if (i != min){
int k = array[i];
array[i] = array[min];
array[min] = k;
}
}
Print(array, size);
}
总结:
- 时间复杂度:O(N^2)
- 稳定性:不稳定
堆排序:
堆排序是利用堆积树这种数据机构所设计的一种排序算法,它是通过堆来进行选择数据,需要注意的是排升序建大堆,排降序建小堆。
堆的逻辑结构就是一个完全二叉树,存储结构是一个一维数组,数组中的每一个元素满足
//小堆
array[i]<=array[i*2+1];
array[i]<=array[i*2+2];
//或
//大堆
array[i]>=array[i*2+1];
array[i]>=array[i*2+2];
节点node的左节点的数组下标是node2+1,右节点的数组下标是node2+2,根节点的数组下标为0。
处理一个待排序的序列,用堆排序进行排序分为以下几步:
1.建堆升序建大堆,降序建立小堆。
建大堆只能将待排序列中的最大值放在跟节点,小堆反之。
void GreateHeap(int array[], int size){
for (int i = (size - 2) / 2; i >= 0; i--){
AdjustDown(array, size, i);
}
}
void AdjustDown(int array[], int size, int root){
int i = 2 * root + 1;
int j = 2 * root + 2;
if (i >= size){
return;
}
int m = i;
if ( j<size && array[j]>array[i])
m = j;
if (array[m] > array[root]){
Swap(array + m, array + root);
AdjustDown(array, size, m);
}
}
2.经过一次建堆操作,找出了最大数,将这个最大的数交换到待排序列的最后位置,然后再对这个待排序列除去交换到最后位置的哪个元素再进行建堆操作,确认新的最值,然后再将新确认的最值和新的序列的最后一位元素继续交换,重复以上操作,直到新的待排序列只剩下一个元素,得到的序列就是升序(降序)的。
void HeapSort(int array[], int size){
GreateHeap(array, size);
for (int i = 0; i < size; i++){
Swap(array, array + size - i - 1);
AdjustDown(array, size-1 - i, 0);
}
}
总结:
时间复杂度:O(N*logN)
空间复杂度:O(1)
稳定性:不稳定