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