1. 程式人生 > >ADT - Binary Heap(二叉堆) &&

ADT - Binary Heap(二叉堆) &&

val break pre ide 代碼 opera function eas queue

  今天早上起來完成了一個完整的基於二叉堆實現的優先隊列,其中包含最小優先和最大優先隊列。

  實際上上篇也說了優先隊列的特性,通過建堆和堆排序操作,我們就已經看到了這種數據結構中的數據具有某種優先級別,要麽非根節點大於他的子節點,要麽就相反,在最大優先隊列中最大優先級別就是指節點值最大的數據為根節點,每次出隊時肯定是最大的先出去,反之則是最小優先隊列,但要註意插入時的數據不一定是最大或最小的,優先隊列會通過一點小技巧找到所有節點之間的關系並對應起來,重新使得你隨意插入的數據滿足優先隊列的特性,因而這種數據結構的使用很普遍。比如:操作系統中的任務調度等。

  用線性表實現這種數據結構並不難,下面是優先隊列的代碼:

  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(二叉堆) &&