堆排序原理
堆排序就是把最大堆(或最小堆)堆顶的元素取出,将剩余的堆继续调整为最大堆(最小堆),再次将最大堆(或最小堆)堆顶的元素取出,这一过程持续到剩余的堆只有一个元素时结束。
步骤
<1>产生最大堆:从下图我们可以看见,我们是至下而上地调整初始堆的,因为最大堆调整能够保证下标i的结点之后结点都满足最大堆的性质,所以至下而上的调整能够在改造过程中保持这一性质。
<2>反复调整为最大堆,将堆顶元素和堆底元素交换,分离堆底元素,重复直到堆中剩下一个元素位置。
#include<stdio.h> //最小堆实现的是降序 void FilterDown(int *ar, int start, int end) //start,end都是物理下标 { int i = start; //root int j = 2 * start + 1; //leftchild int tmp = ar[i]; while (j <= end) { if (j < end && ar[j] > ar[j+1]) j += 1; //首先,判断右孩子是否存在;比较左右孩子,找出更小的那个 if (tmp <= ar[j]) //找出放置start的位置 { break; } ar[i] = ar[j]; //元素进行上移 i = j; j = 2 * i + 1; } ar[i] = tmp; } void Make_Heap(int *ar, int n) //调整为最小堆 { int end = n - 1; //最后一个结点物理下标 int pos = (end - 1) / 2; //找到最后一个度为1的结点(分支结点)。 while (pos >= 0) { FilterDown(ar, pos, end); //由下至上依次调整 --pos; } } void Swap(int &a, int &b) { int temp = a; a = b; b = temp; } void Sort_Heap(int *ar, int n) //n代表数组元素个数 { for (int i = 0; i < n-1 ; ++i) //需要调整n-1次 { int j = n - 1 - i; Make_Heap(ar, j+1); //j是下标,j+1是当前堆中元素个数 Swap(ar[0], ar[j]); } } int main() { int ar[] = { 45,78,12,34,90,56,8,18 }; int n = sizeof(ar) / sizeof(ar[0]); Sort_Heap(ar, n); for (int i = 0; i < n; ++i) printf("%-4d", ar[i]); return 0; }
本程序在VS2017下运行通过