堆排序
1.代码模板
void HeapSort(SqList *L); // 堆排序
void HeapAdjust(SqList *L, int s, int m); // 堆调整 将L->arr[s...m]调整成一个大顶堆
void HeapSort(SqList *L)
{
// 从下到上,从右到左,把L中的arr构建成一个大顶堆
for (int i = L->length / 2; i > 0; i -- )
HeapAdjust(L, i, L->length);
// 正式的排序过程
for (int i = L->length; i > 1; i -- ) {
swap(L, 1, i); // 将堆顶元素和当前未经排序子序列的最后一个元素交换
HeapAdjust(L, 1, i - 1); // 将L->arr[1...i-1]重新调整为大顶堆
}
}
void HeapAdjust(SqList *L, int s, int m)
{
int temp = L->arr[s];
//
for (int j = 2 * s; j <= m; j *= 2) { // j为s的左孩子,j+1为s的右孩子
if (j < m && L->arr[j] < L->arr[j+1]) // j不是最后一个结点,且左孩子小于右孩子
++j;
if (temp >= L->arr[j])
break;
L->arr[s] = L->arr[j]; // 将该二叉树的最大值赋给根节点
s = j; // s指向原最大值的位置
}
L->arr[s] = temp; // 插入
}
2.算法介绍
堆排序是对简单选择排血的一种改进,也属于选择类排序。做出的改进思想是:简单选择排序中,在含有n个元素的序列中找到最小的元素需要比较n-1次,但这一趟的其他比较结果并没有被保存下来,我们只选出了最小值,在下一次比较时,有许多比较其实已经被做过了,但由于前一趟没有保存下来,所以这些比较操作在这一趟的比较中又被重复执行了,导致排序的总比较次数较多。
堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;每个结点的值都小于或等于其左右孩子的值,称为小顶堆。
堆排序算法是一种利用大顶堆或小顶堆结构进行排序的算法,其算法思想是:先将待排的序列从下到上、从右到左地构造成一个大顶堆,此时整个序列的最大值就是堆顶的根节点,把根节点移走,将堆数组的末尾元素(即序列的最小值)当做新的根结点,将其重新调整为一个大顶堆,注意此时被移走的原根结点不参与排序,然后反复执行移走跟结点再重新调整的操作,这样被移走的元素就构成了一个有序的序列。
补充:在一颗完全二叉树中,若当前结点的序号是s,则其左孩子的序号一定为2s,右孩子的序号一定为2s+1,孩子的孩子也是以2为倍数增加。
3.实例
#include <iostream>
using namespace std;
const int N = 100;
typedef struct
{
int arr[N];
int length;
} SqList;
void swap(SqList *L, int i, int j)
{
int temp = L->arr[i];
L->arr[i] = L->arr[j];
L->arr[j] = temp;
}
void HeapSort(SqList *L);
void HeapAdjust(SqList *L, int s, int m);
void HeapSort(SqList *L)
{
for (int i = L->length / 2; i > 0; i -- ) // 构造大顶堆
HeapAdjust(L, i, L->length);
for (int i = L->length; i > 0; i -- ) {
swap(L, 1, i);
HeapAdjust(L, 1, i - 1);
}
}
void HeapAdjust(SqList *L, int s, int m)
{
int temp = L->arr[s];
for (int j = 2 * s; j <= m; j *= 2) {
if (j < m && L->arr[j] < L->arr[j+1])
++j;
if (temp >= L->arr[j])
break;
L->arr[s] = L->arr[j];
s = j;
}
L->arr[s] = temp;
}
int main()
{
SqList L;
L.arr[1] = 50;
L.arr[2] = 10;
L.arr[3] = 90;
L.arr[4] = 30;
L.arr[5] = 70;
L.arr[6] = 40;
L.arr[7] = 80;
L.arr[8] = 60;
L.arr[9] = 20;
L.length = 9;
HeapSort(&L); // 堆排序测试
for (int i = 1; i <= L.length; i ++ )
cout << L.arr[i] << " ";
}
注:内容参考自《大话数据结构》