选择排序分为简单选择排序和堆排序
1. 简单选择排序
简单选择排序是一种不稳定排序算法,从未排序序列中选择关键字最小的元素与该序列中第一个关键字交换位置,每一趟排序可以确定一个元素的最终位置,空间复杂度:O(1),时间复杂度:O(n²)。
void SimpleSelectSort(ElemType A[], int n) {
int i, j, min, temp;
for (i = 0; i < n - 1; i++) {
min = i;
for (j = i + 1; j < n; j++) {
if (A[j] < A[min]) //不断更新最小关键字
min = A[j];
}
if (min != i) { //若找到最小的关键字
temp = A[i];
A[min] = A[i];
A[i] = temp;
}
}
}
2. 堆排序
堆排序是一种不稳定排序算法,堆排序分为大顶堆和小顶堆,本代码所用为大顶堆,基本思路:大根堆的堆顶为最大值,且其余非根结点的值小于等于其双亲结点,在双亲结点和孩子结点交换位置时,要选择孩子结点中更大的那一个值,空间复杂度为:O(1),时间复杂度为:O(n㏒₂n)。
void HeadAdjust(ElemType A[], int k, int n) { //调整结点位置
int i;
A[0] = A[k]; //A[0]暂存子树的根节点
for (i = 2 * k; i <= n; i *= 2) { //沿着关键字较大的子结点向下筛选
//如果左孩子比右孩子小,就把i指向右孩子,因为原则上temp是要和更大的交换
if (i < n && A[i] < A[i + 1])
i++; //就把i指向右孩子
if (A[0] >= A[i])
break;
else {
A[k] = A[i]; //将A[i]调整到双亲结点上
k = i; //修改k值,以便继续向下筛选
}
}
//前面没有每一次比较都互相交换,而是直接赋值,这里把被筛选的结点放入最终位置
A[k] = A[0];
}
void BuildMaxHeap(ElemType A[], int n) { //建立大根堆
//从i=n/2~1,即从最后一个双亲结点开始到顶,反复调整堆
// 把比根结点大的孩子结点与双亲结点交换位置,因为要建立的是大根堆
for (int i = n / 2; i > 0; i--)
HeadAdjust(A, i, n);
}
void HeapSort(ElemType A[], int n) { //开始堆排序
int i, temp;
BuildMaxHeap(A, n); //初始建堆
for (i = n; i > 1; i--) { //输出堆顶元素(和堆底元素交换位置)
temp = A[i];
A[i] = A[1];
A[1] = temp;
HeadAdjust(A, 1, i - 1); //把剩余的i-1个元素整理成堆
}
}