一、实现思想

  这里以数组作为存储结构,用假设出来的堆作为实现基础

  1、将最大值调整到堆顶

  2、将堆顶摘除,移动到数组末尾

  3、将剩下元素,重新构建堆,堆顶又是最大值,又移动到后面

  4、重复以上步骤,直到数组剩下最后一个元素

注意:最核心的步骤就在于堆的构建与调整(也是比较难讲述清楚的部分)

 

二、图例实现

  1


 

 

2、 


 

 

 

 3、


 

 

 4、


 

 

 

 

 5、


 

 

 

 6、


 

 

 

 

 三、实现代码

  有很多小细节要注意,很难一一说清楚,但是意会理解起来比较容易,可以按照下面框架去理解。

  1、输入一个k为顶的位置,调整k为顶的堆为大根堆的一个函数,sifi函数

  2、通过循环调用sifi函数,实现初建堆,

1  for (i = len / 2 - 1; i >= 0; i--) //当然这里的i可以改成len ,但是后面几个都是在做无用功,没必要,这也是一个妙处
2         //从最后一个分支节点调整至根节点,实现新建堆(最大堆或最小堆),当然我这里只是实现了最大堆
3         sift(i, len - 1);

  3、接下来是移动堆顶到后面,并且重新调整堆,使堆顶是下一个最大值

  

1 for (i = 1; i < len; i++)
2     {
3         temp = data[0];
4         data[0] = data[len - i];
5         data[len - i] = temp;
6         sift(0, len - i - 1);
7     }

 

完整实现代码

  

 1 #include <stdio.h>
 2 int data[] = {36, 30, 18, 40, 32, 45, 22, 50};
 3 //对以k为顶的堆,进行调整为大根堆或者小根堆
 4 /* 将完全二叉树存储到data[0]~data[length-1],则data[i]的左孩子是data[2*i+1] */
 5 void sift(int k, int last)
 6 {
 7     int i, j, temp;
 8     i = k;
 9 
10     j = 2 * i + 1; //i是被调整节点,j是i的左孩子
11     while (j <= last)
12     {
13         if (j < last && data[j] < data[j + 1])
14             j++; //j指向左右孩子的较大者//当然啦,如果想要变成最小堆,换一下符号即可
15         if (data[i] > data[j])
16             break; //已经是堆,不用交换
17         else
18         {
19             temp = data[j];
20             data[j] = data[i];
21             data[i] = temp;
22             i = j;
23             j = 2 * i + 1; //开始往下走
24         }
25     }
26 }
27 
28 void HeadSort(int len)
29 {
30     int i, temp;
31     for (i = len / 2 - 1; i >= 0; i--) //当然这里的i可以改成len ,但是后面几个都是在做无用功,没必要,这也是一个妙处
32         //从最后一个分支节点调整至根节点,实现新建堆(最大堆或最小堆),当然我这里只是实现了最大堆
33         sift(i, len - 1);
34     for (i = 1; i < len; i++)
35     {
36         temp = data[0];
37         data[0] = data[len - i];
38         data[len - i] = temp;
39         sift(0, len - i - 1);
40     }
41 }
42 
43 int main(void)
44 {
45     int len = 8;
46     for (int i = 0; i < len; i++)
47         printf("%d    ", data[i]);
48     printf("\n");
49     HeadSort(len);
50     for (int i = 0; i < len; i++)
51         printf("%d    ", data[i]);
52     return 0;
53 }
54 /* 
55 输出
56 ————————————————————————————————————————————
57 36    30    18    40    32    45    22    50    
58 18    22    30    32    36    40    45    50 
59 ————————————————————————————————————————————
60  */

(ps:我这里显示了行号,复制也会一同复制过去。你应该会竖直选择然后删除吧)

 

posted on 2020-08-04 20:23  Coderon  阅读(169)  评论(0编辑  收藏  举报