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

时间: 2024-10-08 23:06:08

ADT - Binary Heap(二叉堆) &&的相关文章

二叉堆(binary heap)

堆(heap) 亦被称为:优先队列(priority queue),是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.在队列中,调度程序反复提取队列中第一个作业并运行,因而实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权.堆即为解决此类问题设计的一种数据结构. 本文地址:http://www.cnblogs.com/archimedes/p/binary-heap.html,转载请注明源地址. 逻辑定义 n个

堆(Heap)和二叉堆(Binary heap)

堆(Heap): The operations commonly performed with a heap are: create-heap: create an empty heap heapify: create a heap out of given array of elements find-max or find-min: find the maximum item of a max-heap or a minimum item of a min-heap (aka, peek)

数据结构 之 二叉堆(Heap)

注:本节主要讨论最大堆(最小堆同理). 一.堆的概念 堆,又称二叉堆.同二叉查找树一样,堆也有两个性质,即结构性和堆序性. 1.结构性质: 堆是一棵被全然填满的二叉树.有可能的例外是在底层.底层上的元素从左到右填入.这种树称为全然二叉树(complete binary tree).下图就是这样一个样例. 对于全然二叉树,有这样一些性质: (1).一棵高h的全然二叉树,其包括2^h ~ (2^(h+1) - 1)个节点.也就是说.全然二叉树的高是[logN],显然它是O(logN). (2).全然

在A*寻路中使用二叉堆

接上篇:A*寻路初探 GameDev.net 在A*寻路中使用二叉堆 作者:Patrick Lester(2003年4月11日更新) 译者:Panic 2005年3月28日 译者序:     这一篇文章,是"A* Pathfinding for Beginners.",也就是我翻译的另一篇文章<A*寻路初探>的补充,在这篇文章里,作者再一次展现了他阐述复杂话题的非凡能力,用通俗易懂的语句清晰的解释了容易让人迷惑的问题.还是那句话,如果你看了这篇文章仍然无法领会作者的意图,那

D&amp;F学数据结构系列——二叉堆

二叉堆(binary heap) 二叉堆数据结构是一种数组对象,它可以被视为一棵完全二叉树.同二叉查找树一样,堆也有两个性质,即结构性和堆序性.对于数组中任意位置i上的元素,其左儿子在位置2i上,右儿子在左儿子后的单元2i+1中,它的父亲在[i/2](向下取整)中. 因此,一个数据结构将由一个数组.一个代表最大值的整数.以及当前的堆的大小组成.一个典型的优先队列(priority queue)如下: 1 #ifndef _BinHeap_H 2 struct HeapStruct; 3 type

笔试算法题(46):简介 - 二叉堆 &amp; 二项树 &amp; 二项堆 &amp; 斐波那契堆

二叉堆(Binary Heap) 二叉堆是完全二叉树(或者近似完全二叉树):其满足堆的特性:父节点的值>=(<=)任何一个子节点的键值,并且每个左子树或者右子树都是一 个二叉堆(最小堆或者最大堆):一般使用数组构建二叉堆,对于array[i]而言,其左子节点为array[2*i],其右子节点为 array[2*i+1]:二叉堆支持插入,删除,查找最大(最小)键值的操作,但是合并二叉堆的复杂度较高,时间复杂度为O(N):但是二项堆或者斐波 那契堆则仅需要O(logN): 二项树(Binomial

数据结构--二叉堆与堆排序

二叉堆的概念 二叉堆,BinaryHeap,是二叉树中的常见的一种结构.通常以最大堆和最小堆的形式呈现.最大堆指的是父节点大于等于孩子节点的value值,也就是说对于最大堆而言,根元素是二叉堆最大的元素.最小堆的概念是与最大堆的概念是相似的.下图是最大堆的示意图: 二叉堆和排序之间的联系 二叉堆最显著的特征就是根元素是二叉树元素间最大的或者最小的.因此每次将二叉树最大或者最小的元素取出来,同时保证每次进行这样的操作后,剩下的元素依然可以保持二叉堆的性质,这样迭代这个过程,就可以完成排序的目的.

《数据结构与算法分析:C语言描述》复习——第五章“堆”——二叉堆

2014.06.15 22:14 简介: 堆是一种非常实用的数据结构,其中以二叉堆最为常用.二叉堆可以看作一棵完全二叉树,每个节点的键值都大于(小于)其子节点,但左右孩子之间不需要有序.我们关心的通常只有堆顶的元素,而整个堆则被封装起来,保存在一个数组中. 图示: 下图是一个最大堆: 实现: 优先队列是STL中最常用的工具之一,许多算法的优化都要利用堆,使用的工具就是优先队列.STL中的优先队列通过仿函数来定义比较算法,此处我偷懒用了“<”运算符.关于使用仿函数的好处,我之后如果有时间深入学习S

数据结构 二叉堆 &amp; 堆排序

二叉堆,是一个满二叉树,满足堆的性质.即父节点大于等于子节点(max heap)或者是父节点小于等于子节点(min heap).二叉堆的如上性质常用于优先队列(priority queue)或是用于堆排序. 由于max heap 与min heap类似,下文只针对min heap进行讨论和实现. 如上图,是根据字母的ASCII码建立的最小堆. 我们用数组对满二叉树采用宽度优先遍历存储堆结构,如下图所示: 从数组下标1开始存储堆,这样的处理方式可以得到如下性质: 1.堆中的每个父节点k,他的两个子