Fork me on GitHub

数据结构与算法——堆 特点与算法实现(一)

 

 

1. 堆的特点:

1.1. 每个节点最多可以有两个节点

1.2. 根节点的键值是所有堆节点键值中最大者(如果是最小堆则相反),且每个节点的值都比其两个或一个子节点的值大(如果是最小堆则相反)

1.3. 除了根节点没有兄弟节点,最后一个左子节点可以没有兄弟节点,其他节点必须有兄弟节点

 

2. 堆的结构:

堆是你见过的最有个性的树!它是用数组表示的树

 

 

在数组中快速创建堆

 

 

 2.1. 首先我们需要找到最后一个结点的父结点如图(a),我们找到的结点是 87,然后找出该结点的最大子节点与自 己比较,若该子节点比自身大,则将两个结点交换. 图(a)中,87 比左子节点 95 小,则交换之.如图(b)所示

 

2.2. 我们移动到前一个父结点 93,如图(c)所示.同理做第一步的比较操作8,结97果9不43需8要40交1换

 

 

 

3.继续移动结点到前一个父结点 82,如图(d)所示,82 小于右子节点 95,则 82 与 95 交换,如图(e)所示,82 交换 后,其值小于左子节点,不符合最大堆的特点,故需要继续向下调整,如图(f)所示

 

4.所有节点交换完毕,最大堆构建完成

 

 

3. 堆的算法实现

堆数据结构的定义

1 #define DEFAULT_CAPCITY 128
2 
3 typedef struct _Heap
4 {
5     int *arr;        //存储堆元素的数组
6     int size;        //当前已存储的元素个数
7     int capacity;    //当前存储的容量
8 }Heap;

 

 建(最大)堆

 1 bool initHeap(Heap &heap, int *orginal, int size);
 2 static void buildHeap(Heap &heap);
 3 static void adjustDown(Heap &heap, int index);
 4 
 5 /*初始化堆*/
 6 bool initHeap(Heap &heap, int *orginal, int size)
 7 {
 8     int capacity = DEFAULT_CAPCITY>size? DEFAULT_CAPCITY:size;
 9     
10     heap.arr = new int[capacity];
11     if(!heap.arr) return false;
12     
13     heap.capacity = capacity;
14     heap.size = 0;
15     
16     //如果存在原始数据则构建堆
17     if(size>0)
18     {
19         memcpy(heap.arr, orginal, size*sizeof(int));
20         heap.size = size;
21         buildHeap(heap);
22     }
23     else 
24     {
25         heap.size = 0;
26     }
27     return true;
28 }
29 
30 /*将当前的节点和子节点调整成最大堆*/
31 void adjustDown(Heap &heap, int index)
32 {
33     int cur=heap.arr[index];    //当前待调整的节点
34     int parent,child;
35     
36     /*判断否存在大于当前节点子节点,如果不存在 ,则堆本身是平衡的,不需要调整;
37     如果存在,则将最大的子节点与之交换,交换后,如果这个子节点还有子节点,
38     则要继续按照同样的步骤对这个子节点进行调整*/
39     for(parent=index; (parent*2+1)<heap.size; parent=child)
40     {
41         child=parent*2+1;
42         //取两个子节点中的最大的节点
43         if(((child+1)<heap.size)&&(heap.arr[child]<heap.arr[child+1]))
44         {
45             child++;
46         }
47         //判断最大的节点是否大于当前的父节点
48         if(cur>=heap.arr[child])
49         {    
50             //不大于,则不需要调整,跳出循环
51             break;
52         }
53         else 
54         {
55             //大于当前的父节点,进行交换,然后从子节点位置继续向下调整
56             heap.arr[parent]=heap.arr[child];
57             heap.arr[child]=cur;
58         }
59     }
60 }
61 
62 /* 从最后一个父节点(size/2-1 的位置)逐个往前调整所有父节点(直到根节点),
63 确保每一个父节点都是一个最大堆,最后整体上形成一个最大堆 */
64 void buildHeap(Heap &heap)
65 {
66     int i;
67     for(i=heap.size/2-1; i>=0; i--)
68     {
69         adjustDown(heap, i);
70     }
71 }

  

后续:数据结构与算法——堆 特点与算法实现(二)

 

posted @ 2020-10-18 19:41  索智源  阅读(419)  评论(0编辑  收藏  举报