堆排序是比较难以理解的算法,构造不同的堆(大顶堆/小顶堆)可以得到不同的排列顺序。如果我们需要将数组进行从小到大的顺序排列,就需要构造大顶堆。为了方便个人复习,在这里给出我自己调试通过的一段代码:
1 #include <stdio.h> 2 typedef int Item; 3 // 构造大顶堆 4 void heap_adjust(Item a[], int parent, int length) 5 { 6 Item temp = a[parent]; // 保存当前父节点 7 int child = 2 * parent + 1; // 先获得左孩子(若下标从1开始,则左孩子为2*parent) 8 9 while (child < length){ 10 //如果有右孩子节点,并且右孩子节点的值大于左孩子节点,则选取右孩子节点 11 if (child+1 < length && a[child] < a[child+1]){// child+1<length防止数组越界 12 child++; 13 } 14 //如果父节点的值已经大于孩子节点的值,则直接结束循环 15 if (temp >= a[child]) break; 16 //把孩子节点的值赋给父节点 17 a[parent] = a[child]; 18 //选取孩子节点的左孩子节点,继续向下筛选(必须保证每次调整后,底部的树也是大顶堆) 19 parent = child; 20 child = 2 * parent + 1; 21 } 22 a[parent] = temp;//将根结点放到最终位置上 23 } 24 25 void heap_sort(Item a[], int left, int right) 26 { 27 int i, length = right - left + 1; 28 Item t; 29 //循环建立初始堆(从下往上构造大顶堆),注意下标从0开始时i=n/2-1 30 for (i = length/2-1; i >= 0; i--){ 31 heap_adjust(a, i, length); 32 } 33 34 //进行n-1次循环,完成排序 35 for (i = length - 1; i > 0; i--){ 36 t = a[0]; a[0] = a[i]; a[i] = t; //最后一个元素和第一个元素交换 37 heap_adjust(a, 0, i);//筛选R[0]节点,得到n-1个节点的堆 38 } 39 } 40 41 42 int main() 43 { 44 int a[] = {1,3,2,5,4,3,7,2,9,8}; 45 heap_sort(a, 0, 9); 46 47 return 0; 48 }