ADT - Binary Heap(二叉堆) &&

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ADT - Binary Heap(二叉堆) &&相关的知识,希望对你有一定的参考价值。

  今天早上起来完成了一个完整的基于二叉堆实现的优先队列,其中包含最小优先和最大优先队列。

  实际上上篇也说了优先队列的特性,通过建堆和堆排序操作,我们就已经看到了这种数据结构中的数据具有某种优先级别,要么非根节点大于他的子节点,要么就相反,在最大优先队列中最大优先级别就是指节点值最大的数据为根节点,每次出队时肯定是最大的先出去,反之则是最小优先队列,但要注意插入时的数据不一定是最大或最小的,优先队列会通过一点小技巧找到所有节点之间的关系并对应起来,重新使得你随意插入的数据满足优先队列的特性,因而这种数据结构的使用很普遍。比如:操作系统中的任务调度等。

  用线性表实现这种数据结构并不难,下面是优先队列的代码:

  Head File:

技术分享
 1 #ifndef _PQ_H
 2 #define _PQ_H
 3 
 4 typedef struct
 5 {
 6     ElemType * arr;
 7     int size;
 8 }Heap;
 9 
10 Heap * Initialize_Heap();
11 static int HeapParent();
12 static int HeapLeft();
13 static int HeapRight();
14 static void Min_Heapify();
15 static void Max_Heapify();
16 void Build_Min_Heap();
17 void Build_Max_Heap();
18 void Heap_Sort();
19 int Heap_Minimum();
20 int Heap_Maximum();
21 int Heap_Extract_Min();
22 int Heap_Extract_Max();
23 static void Heap_Increase_Min_Key();
24 static void Heap_Increase_Max_Key();
25 void Heap_Insert_Max();
26 void Heap_Insert_Min();
27 void Destroy_Heap();
28 
29 #endif
PriorityQueue.h

  Operation Function:

技术分享
  1 #include <stdio.h>
  2 #include "PriorityQueue.h"
  3 
  4 /*
  5  *  初始化堆
  6  *     参数说明:无参数
  7  *
  8  *  返回堆
  9  */
 10 Heap * Initialize_Heap(void)
 11 {
 12     Heap * heap;
 13 
 14     heap = (Heap *)malloc(sizeof(Heap));
 15     heap -> arr = (ElemType *)malloc(sizeof(ElemType));
 16     heap -> size = -1;
 17 
 18     return heap;
 19 }
 20 
 21 /*
 22  *    节点i的双亲
 23  */
 24 static int HeapParent(int i)
 25 {
 26     return i/2;
 27 }
 28 
 29 /*
 30  *    节点i的左孩子
 31  */
 32 static int HeapLeft(int i)
 33 {
 34     return 2*i + 1;
 35 }
 36 
 37 /*
 38  *    节点i的右孩子
 39  */
 40 static int HeapRight(int i)
 41 {
 42     return 2*(i + 1);
 43 }
 44 
 45 /*
 46  *  维护最小堆的性质
 47  */
 48 static void Min_Heapify(Heap * heap, int i)
 49 {
 50     int l = HeapLeft(i);
 51     int r = HeapRight(i);
 52     int smallest;
 53     int temp;
 54 
 55     if(l < heap -> size && heap -> arr[l] < heap -> arr[i])
 56         smallest = l;
 57     else
 58         smallest = i;
 59     if(r < heap -> size && heap -> arr[r] < heap -> arr[i])
 60         smallest = r;
 61     if(smallest != i)
 62     {
 63         temp = heap -> arr[i];
 64         heap -> arr[i] = heap -> arr[smallest];
 65         heap -> arr[smallest] = temp;
 66         Min_Heapify(heap, smallest);
 67     }
 68 }
 69 
 70 /*
 71  *    维护最大堆的性质
 72  */
 73 static void Max_Heapify(Heap * heap, int i)
 74 {
 75     int _L = HeapLeft(i);
 76     int _R = HeapRight(i);
 77     int largest;
 78     int temp;
 79 
 80     if(_L < heap -> size && heap -> arr[_L] > heap -> arr[i])
 81         largest = _L;
 82     else
 83         largest = i;
 84     if(_R < heap -> size && heap -> arr[_R] > heap -> arr[largest])
 85         largest = _R;
 86     if(largest != i)
 87     {
 88         temp = heap -> arr[i];
 89         heap -> arr[i] = heap -> arr[largest];
 90         heap -> arr[largest] = temp;
 91         Max_Heapify(heap, largest);
 92     }
 93 }
 94 
 95 /*
 96  *  建最小堆
 97  */
 98 void Build_Min_Heap(Heap * heap)
 99 {
100     int i;
101 
102     for(i = heap -> size/2; i >= 0; i--)
103         Min_Heapify(heap, i);
104 }
105 
106 /*
107  *    建最大堆
108  */
109 void Build_Max_Heap(Heap * heap)
110 {
111     int i;
112 
113     for(i = heap -> size/2; i >= 0; i--)
114         Max_Heapify(heap, i);
115 }
116 
117 /*
118  *    最大优先队列 - 从小到大排序
119  */
120 void Heap_Sort(Heap * heap)
121 {
122     int i;
123     int temp;
124 
125     Build_Max_Heap(heap);
126     for(i = heap -> size; i >= 0; i--)
127     {
128         temp = heap -> arr[0];
129         heap -> arr[0] = heap -> arr[i];
130         heap -> arr[i] = temp;
131         -- heap -> size;
132         Max_Heapify(heap, 0);
133     }
134 }
135 
136 /*
137  *  最小优先队列 - 最小值
138  */
139 int Heap_Minimum(Heap * heap)
140 {
141     return heap -> arr[0];
142 }
143 
144 /*
145  *    最大优先队列 - 最大值
146  */
147 int Heap_Maximum(Heap * heap)
148 {
149     return heap -> arr[0];
150 }
151 
152 /*
153  *  最小优先队列 - 去除最小值节点
154  */
155 int Heap_Extract_Min(Heap * heap)
156 {
157     int min;
158 
159     if(heap -> size < 0)
160     {
161         fprintf(stderr, "Heap underflow!\n");
162         return 0;
163     }
164     min = heap -> arr[0];
165     heap -> arr[0] = heap -> arr[heap -> size];
166     heap -> arr[heap -> size] = min;
167     -- heap -> size;
168     Min_Heapify(heap, 0);
169 
170     return min;
171 }
172 
173 /*
174  *    最大优先队列 - 去除最大值节点
175  */
176 int Heap_Extract_Max(Heap * heap)
177 {
178     int max;
179 
180     if(heap -> size < 0)
181     {
182         fprintf(stderr, "Heap underflow!\n");
183         return 0;            //提前退出
184     }
185     max = heap -> arr[0];
186     heap -> arr[0] = heap -> arr[heap -> size];
187     -- heap -> size;
188     Max_Heapify(heap, 0);
189 
190     return max;
191 }
192 
193 /*
194  *    将key的值赋给节点i。此处将key值插入最小堆中
195  *
196  *  参数说明:
197  *      1.接收一个已存在的堆
198  *      2.节点位置
199  *      3.与堆节后数据相同类型的键值
200  */
201 static void Heap_Increase_Min_Key(Heap * heap, int i, ElemType key)
202 {
203     int temp;
204 
205     if(key > heap -> arr[i])
206     {
207         printf("请输入大于该而节点值的数据\n");
208         return ;
209     }
210     heap -> arr[i] = key;
211     while(i > 0 && heap -> arr[HeapParent(i)] > heap -> arr[i])
212     {
213         temp = heap -> arr[i];
214         heap -> arr[i] = heap -> arr[HeapParent(i)];
215         heap -> arr[HeapParent(i)] = temp;
216         i = HeapParent(i);
217     }
218 }
219 
220 /*
221  *    将key的值赋给节点i。此处将key值插入最大堆中
222  *
223  *  参数说明:
224  *      1.接收一个已存在的堆
225  *      2.节点位置
226  *      3.与堆节后数据相同类型的键值
227  */
228 static void Heap_Increase_Max_Key(Heap * heap, int i, ElemType key)
229 {
230     int temp;
231 
232     if(key < heap -> arr[i])
233     {
234         printf("请输入大于该而节点值的数据\n");
235         return ;
236     }
237     heap -> arr[i] = key;
238     while(i > 0 && heap -> arr[HeapParent(i)] < heap -> arr[i])
239     {
240         temp = heap -> arr[i];
241         heap -> arr[i] = heap -> arr[HeapParent(i)];
242         heap -> arr[HeapParent(i)] = temp;
243         i = HeapParent(i);
244     }
245 }
246 
247 /*
248  *    将key值插入最小堆
249  */
250 void Heap_Insert_Min(Heap * heap, ElemType key)
251 {
252     ++ heap -> size;
253     heap -> arr[heap -> size] = -65533;
254     Heap_Increase_Min_Key(heap, heap -> size, key);
255 }
256 
257 /*
258  *    将key值插入最大堆
259  */
260 void Heap_Insert_Max(Heap * heap, ElemType key)
261 {
262     ++ heap -> size;
263     heap -> arr[heap -> size] = -65533;
264     Heap_Increase_Max_Key(heap, heap -> size, key);
265 }
266 
267 /*
268  *  如果堆存在则销毁堆
269  *
270  *  无参数/返回值
271  */
272 void Destroy_Heap(Heap * heap)
273 {
274     if(heap && heap -> arr)
275     {
276         free(heap -> arr);
277         free(heap);
278         heap = NULL;
279     }
280 }
PriorityQueue.c

  test file:

技术分享
 1 #include <stdio.h>
 2 #include <conio.h>
 3 
 4 int main(void)
 5 {
 6     ElemType val;
 7     Heap * heap;
 8     char c;
 9     int i, cont = 0;
10 
11     heap = Initialize_Heap();
12 
13     puts("1) Insert Heap    2) Extract Max");
14     puts("3) Display  4) Exit");
15 
16     while((c = getch()) != 4)
17     {
18         switch(c)
19         {
20             case 1 :  cont ++;
21                         printf("Enter key:");
22                         scanf("%d", &val);
23                         Heap_Insert_Max(heap, val);
24                 break;
25             case 2 :  cont --;
26                         printf("Max key = %d\n", Heap_Extract_Max(heap));
27                 break;
28             case 3 :  Build_Max_Heap(heap);
29                         printf("显示数据:\n");
30                         for(i = 0; i < cont; i++)
31                             printf("%d ", heap -> arr[i]);
32                         printf("NULL\n");
33                 break;
34         }
35     }
36 //    Destroy_Heap();
37 
38     return 0;
39 }
test.c

 

以上是关于ADT - Binary Heap(二叉堆) &&的主要内容,如果未能解决你的问题,请参考以下文章

二叉堆和堆排序(binary heap)

ADT - heap(堆)

STL源码分析之heap和priority_queue

数据结构 之 二叉堆(Heap)

STL测试3)优先级队列实现二叉堆

堆和优先队列