当前位置:   article > 正文

数据结构与算法——优先队列类的C++实现(二叉堆)

c++二叉堆实现优先队列

优先队列简单介绍:

操作系统表明上看着是支持多个应用程序同一时候执行。其实是每一个时刻仅仅能有一个进程执行,操作系统会调度不同的进程去执行。

每一个进程都仅仅能执行一个固定的时间,当超过了该时间。操作系统就会暂停当前执行的进程,去调度其他进程来执行。

实现这样的进程调度的一种方法是使用队列。

開始的时候进程被放在队列的末尾,调度程序将重复提取队列中的第一个进程来执行。直到执行完成或时间片用完,若进程没有执行完成则将该进程放入队列的末尾。这样的策略不是特别合适,由于可能一些短的进程须要等待非常长的时间才干轮流到。一般来说,执行时间短的进程须要尽快的结束。所以那些执行时间短的进程须要比較高的优先权,相同,那些比較重要的进程也须要比較高的优先权。


这样的特殊的应用须要一种特殊的队列-----优先队列。能够用二叉堆实现优先队列。

二叉堆简单介绍:

二叉堆与二叉查找树类似,二叉树有两个性质:结构性质和堆序性质。


结构性质:

二叉堆是一棵全然二叉树,除了子节点外的其他节点都有两个儿子节点。


一棵高为h的全然二叉树有2^h到2^(h+1) - 1个节点。

全然二叉树的高为log(N),N为节点数目。
因为全然二叉树的特点,实现起来非常easy,用简单的数组就能够实现。

对于数组中的任何位置i上的元素,其左儿子在位置2*i上,右儿子在(2*i)+1上,其父节点在i/2上(让根节点在位置1)。


以下是一棵全然二叉树的数组实现图示:



堆序性质:

由于假设想高速找到最小单元。则最小单元应该在根上。在堆中,对于每个节点x,x的值大于等于子节点(叶子节点除外);没有二叉查找树的要求严格。


二叉堆的数据结构实现:

用一个数组 vector<Comparable> v;来存储全部的元素。


用currentSize来记录当前元素的数目。


  1. vector<Comparable> array;//存储二叉堆的节点
  2. int currentSize;//当前二叉堆中的节点数目

二叉堆的主要成员函数:

  1. bool isEmpty() const;//推断二叉堆是否为空
  2. const Comparable & findMin() const;//查找最小元素
  3. void insert(const Comparable & x);//插入元素x
  4. void deleteMin();//删除最小元素
  5. void deleteMin(Comparable & minItem);//删除最小元素,并以引用的方式返回该最小元素
  6. void makeEmpty();//清空该二叉堆
  7. void print() const;//打印该堆元素
  8. void buildHeap();//将元素移动到合适的位置
  9. void percolateDown(int hole);//下移动

二叉堆的主要成员函数介绍:

1、插入insert():

比方:当插入14的时候。第一步在堆的下一个可用的位置建立空穴。假设在该空穴插入14后满足堆序性,则插入成功。
但当在该空穴插入14之后不满足堆序性,则将该空穴的父节点移入空穴,之前的父节点的位置变为了空穴。


然后再尝试插入该新的空穴,假设不满足堆序。则反复之前的操作。




  1. /****************************************************************
  2. * 函数名称:insert(const Comparable & x)
  3. * 功能描写叙述: 删除最小元素
  4. * 參数列表: 无
  5. * 返回结果:void
  6. *****************************************************************/
  7. template<typename Comparable>
  8. void BinaryHeap<Comparable>::insert(const Comparable & x)
  9. {
  10. if(currentSize == array.size()-1)
  11. array.resize(2 * array.size());//扩大堆中数组的容量
  12. //获得空穴的位置
  13. int hole = ++currentSize;
  14. //上滤
  15. for(; hole > 1 && x < array[hole/2]; hole /= 2)
  16. array[hole] = array[hole/2];
  17. //将x插入到合适的位置
  18. array[hole] = x;
  19. }

2、删除最小元素deleteMin():

将堆中最小的一个元素删除之后(最下的元素位于堆数组的最前面)。必须将堆中最后一个元素x移动到堆中的某个合适的位置。

.


比方:在下图中删除最小元素的操作。
删除最小元素13。将最后一个元素31移动到13的位置;31比13的两个孩子的值都大,全部将两个孩子值比較小的上移动。所以将14上移动。然后31再和14的两个孩子的值比較。直到31比空穴的两个孩子的值都小,或者是空穴到了叶子节点。则直接将31插入到空穴。




  1. /****************************************************************
  2. * 函数名称:deleteMin()
  3. * 功能描写叙述: 删除最小元素
  4. * 參数列表: 无
  5. * 返回结果:void
  6. *****************************************************************/
  7. template<typename Comparable>
  8. void BinaryHeap<Comparable>::deleteMin()
  9. {
  10. if(isEmpty()){
  11. cout << "BinaryHeap is empty." << endl;
  12. return;
  13. }
  14. array[1] = array[currentSize];//将最后一个元素移动到最小元素的位置
  15. currentSize--;//元素总数减去1
  16. //将最后一个元素移动到合适的位置
  17. percolateDown(1);
  18. }
  19. /****************************************************************
  20. * 函数名称:percolateDown(int hole)
  21. * 功能描写叙述: 将array(hole)处的值向下移动
  22. * 參数列表: hole为堆中元素的位置标号
  23. * 返回结果:void
  24. *****************************************************************/
  25. template<typename Comparable>
  26. void BinaryHeap<Comparable>::percolateDown(int hole)
  27. {
  28. int child;
  29. //先保存array[hole]的值
  30. Comparable temp = array[hole];
  31. for(; hole * 2 <= currentSize; hole = child){
  32. child = hole * 2;
  33. //child != currentSize,表明此时空穴有右儿子
  34. //array[child] > array[child+1] 表明此时空穴有右儿子小于左儿子
  35. if(child != currentSize && array[child] > array[child+1])
  36. child++;//此时child表示为空穴的右儿子
  37. //空穴的右儿子小于array[hole]
  38. if(array[child] < temp)
  39. array[hole] = array[child];
  40. else
  41. break;
  42. }
  43. array[hole] = temp;
  44. }

以下是main函数,主要是对散列表类进行測试。


  1. //測试主函数
  2. int main()
  3. {
  4. srand(unsigned(time(0)));
  5. BinaryHeap<int> binaryHeap;
  6. vector<int> v;
  7. for(int i = 0; i < 10; ++i)
  8. v.push_back(rand() % 10);
  9. cout << "v: ";
  10. for(int i = 0; i < 10; ++i)
  11. cout << v[i] << " ";
  12. cout << endl;
  13. for(int i = 0; i < 10; ++i)
  14. binaryHeap.insert(v[i]);
  15. binaryHeap.print();
  16. for(int i = 0; i < 12; i++){
  17. int minVal = 0;
  18. binaryHeap.deleteMin(minVal);
  19. cout << "删除最小元素:" << minVal << endl;
  20. binaryHeap.print();
  21. }
  22. cout << "*****************************************" << endl;
  23. cout << "測试第二个构造函数: " << endl;
  24. BinaryHeap<int> binaryHeap2(v);
  25. binaryHeap2.print();
  26. for(int i = 0; i < 12; i++){
  27. int minVal = 0;
  28. binaryHeap2.deleteMin(minVal);
  29. cout << "删除最小元素:" << minVal << endl;
  30. binaryHeap2.print();
  31. }
  32. return 0;
  33. }

以下是二叉堆类的源码:

  1. /*************************************************************************
  2. > File Name: binaryHeap.cpp
  3. > Author:
  4. > Mail:
  5. > Created Time: 2016年04月14日 星期四 11时37分43秒
  6. ************************************************************************/
  7. #include <iostream>
  8. #include <vector>
  9. #include <time.h>
  10. #include <stdlib.h>
  11. using namespace std;
  12. /******************************************
  13. * 类的名称:二叉堆
  14. ******************************************/
  15. template<typename Comparable>
  16. class BinaryHeap
  17. {
  18. public:
  19. explicit BinaryHeap(int capacity = 100):array(capacity), currentSize(0){}
  20. explicit BinaryHeap(const vector<Comparable> & items);
  21. bool isEmpty() const;//推断二叉堆是否为空
  22. const Comparable & findMin() const;//查找最小元素
  23. void insert(const Comparable & x);//插入元素x
  24. void deleteMin();//删除最小元素
  25. void deleteMin(Comparable & minItem);//删除最小元素。并以引用的方式返回该最小元素
  26. void makeEmpty();//清空该二叉堆
  27. void print() const;//打印该堆元素
  28. private:
  29. vector<Comparable> array;//存储二叉堆的节点
  30. int currentSize;//当前二叉堆中的节点数目
  31. private:
  32. void buildHeap();//将元素移动到合适的位置
  33. void percolateDown(int hole);//下移动
  34. };
  35. /****************************************************************
  36. * 函数名称:print() const
  37. * 功能描写叙述: 打印该堆元素
  38. * 參数列表: 无
  39. * 返回结果:无
  40. *****************************************************************/
  41. template<typename Comparable>
  42. void BinaryHeap<Comparable>::print() const
  43. {
  44. cout << "二叉堆的元素: " << endl;
  45. for(int i = 1; i <= currentSize; ++i)
  46. cout << array[i] << " ";
  47. cout << endl;
  48. }
  49. /****************************************************************
  50. * 函数名称:BinaryHeap(const vector<Comparable> & items)
  51. * 功能描写叙述: 构造函数
  52. * 參数列表: items 是构造二叉堆须要的数据
  53. * 返回结果:无
  54. *****************************************************************/
  55. template<typename Comparable>
  56. BinaryHeap<Comparable>::BinaryHeap(const vector<Comparable> & items):array(items.size()+10), currentSize(items.size())
  57. {
  58. for(unsigned i = 0; i < items.size(); ++i)
  59. array[i+1] = items[i];
  60. buildHeap();
  61. }
  62. /****************************************************************
  63. * 函数名称:buildHeap()
  64. * 功能描写叙述: 将元素移动到合适的位置,满足堆序
  65. * 參数列表: 无
  66. * 返回结果:void
  67. *****************************************************************/
  68. template<typename Comparable>
  69. void BinaryHeap<Comparable>::buildHeap()
  70. {
  71. for(int i = currentSize / 2; i > 0; --i)
  72. percolateDown(i);
  73. }
  74. /****************************************************************
  75. * 函数名称:findMin()
  76. * 功能描写叙述: 查找最小元素
  77. * 參数列表: 无
  78. * 返回结果:返回最小元素的引用
  79. *****************************************************************/
  80. template<typename Comparable>
  81. const Comparable & BinaryHeap<Comparable>::findMin() const
  82. {
  83. return array[1];
  84. }
  85. /****************************************************************
  86. * 函数名称:insert(const Comparable & x)
  87. * 功能描写叙述: 删除最小元素
  88. * 參数列表: 无
  89. * 返回结果:void
  90. *****************************************************************/
  91. template<typename Comparable>
  92. void BinaryHeap<Comparable>::insert(const Comparable & x)
  93. {
  94. if(currentSize == array.size()-1)
  95. array.resize(2 * array.size());//扩大堆中数组的容量
  96. //获得空穴的位置
  97. int hole = ++currentSize;
  98. //上滤
  99. for(; hole > 1 && x < array[hole/2]; hole /= 2)
  100. array[hole] = array[hole/2];
  101. //将x插入到合适的位置
  102. array[hole] = x;
  103. }
  104. /****************************************************************
  105. * 函数名称:deleteMin()
  106. * 功能描写叙述: 删除最小元素
  107. * 參数列表: 无
  108. * 返回结果:void
  109. *****************************************************************/
  110. template<typename Comparable>
  111. void BinaryHeap<Comparable>::deleteMin()
  112. {
  113. if(isEmpty()){
  114. cout << "BinaryHeap is empty." << endl;
  115. return;
  116. }
  117. array[1] = array[currentSize];//将最后一个元素移动到最小元素的位置
  118. currentSize--;//元素总数减去1
  119. //将最后一个元素移动到合适的位置
  120. percolateDown(1);
  121. }
  122. /****************************************************************
  123. * 函数名称:percolateDown(int hole)
  124. * 功能描写叙述: 将array(hole)处的值向下移动
  125. * 參数列表: hole为堆中元素的位置标号
  126. * 返回结果:void
  127. *****************************************************************/
  128. template<typename Comparable>
  129. void BinaryHeap<Comparable>::percolateDown(int hole)
  130. {
  131. int child;
  132. //先保存array[hole]的值
  133. Comparable temp = array[hole];
  134. for(; hole * 2 <= currentSize; hole = child){
  135. child = hole * 2;
  136. //child != currentSize,表明此时空穴有右儿子
  137. //array[child] > array[child+1] 表明此时空穴有右儿子小于左儿子
  138. if(child != currentSize && array[child] > array[child+1])
  139. child++;//此时child表示为空穴的右儿子
  140. //空穴的右儿子小于array[hole]
  141. if(array[child] < temp)
  142. array[hole] = array[child];
  143. else
  144. break;
  145. }
  146. array[hole] = temp;
  147. }
  148. /****************************************************************
  149. * 函数名称:deleteMin(Comparable & minItem)
  150. * 功能描写叙述: 删除最小元素
  151. * 參数列表: minItem 将最小元素赋值给引用minItem
  152. * 返回结果:void
  153. *****************************************************************/
  154. template<typename Comparable>
  155. void BinaryHeap<Comparable>::deleteMin(Comparable & minItem)
  156. {
  157. if(isEmpty()){
  158. cout << "binaryHeap is empty." << endl;
  159. return;
  160. }
  161. minItem = array[1];
  162. array[1] = array[currentSize--];
  163. percolateDown(1);
  164. }
  165. /****************************************************************
  166. * 函数名称:makeEmpty()
  167. * 功能描写叙述: 情况二叉堆
  168. * 參数列表: 无
  169. * 返回结果:void
  170. *****************************************************************/
  171. template<typename Comparable>
  172. void BinaryHeap<Comparable>::makeEmpty()
  173. {
  174. currentSize = 0;
  175. }
  176. /****************************************************************
  177. * 函数名称:isEmpty()
  178. * 功能描写叙述: 推断二叉堆是否为空
  179. * 參数列表: 无
  180. * 返回结果:假设为空,则返回true。否则返回false
  181. *****************************************************************/
  182. template<typename Comparable>
  183. bool BinaryHeap<Comparable>::isEmpty() const
  184. {
  185. return currentSize == 0;
  186. }
  187. //測试主函数
  188. int main()
  189. {
  190. srand(unsigned(time(0)));
  191. BinaryHeap<int> binaryHeap;
  192. vector<int> v;
  193. for(int i = 0; i < 10; ++i)
  194. v.push_back(rand() % 10);
  195. cout << "v: ";
  196. for(int i = 0; i < 10; ++i)
  197. cout << v[i] << " ";
  198. cout << endl;
  199. for(int i = 0; i < 10; ++i)
  200. binaryHeap.insert(v[i]);
  201. binaryHeap.print();
  202. for(int i = 0; i < 12; i++){
  203. int minVal = 0;
  204. binaryHeap.deleteMin(minVal);
  205. cout << "删除最小元素:" << minVal << endl;
  206. binaryHeap.print();
  207. }
  208. cout << "*****************************************" << endl;
  209. cout << "測试第二个构造函数: " << endl;
  210. BinaryHeap<int> binaryHeap2(v);
  211. binaryHeap2.print();
  212. for(int i = 0; i < 12; i++){
  213. int minVal = 0;
  214. binaryHeap2.deleteMin(minVal);
  215. cout << "删除最小元素:" << minVal << endl;
  216. binaryHeap2.print();
  217. }
  218. return 0;
  219. }

以下是程序的执行结果:

v: 5 3 8 4 3 6 1 5 4 5 
二叉堆的元素: 
1 3 3 4 4 8 6 5 5 5 
删除最小元素:1
二叉堆的元素: 
3 4 3 5 4 8 6 5 5 
删除最小元素:3
二叉堆的元素: 
3 4 5 5 4 8 6 5 
删除最小元素:3
二叉堆的元素: 
4 4 5 5 5 8 6 
删除最小元素:4
二叉堆的元素: 
4 5 5 6 5 8 
删除最小元素:4
二叉堆的元素: 
5 5 5 6 8 
删除最小元素:5
二叉堆的元素: 
5 6 5 8 
删除最小元素:5
二叉堆的元素: 
5 6 8 
删除最小元素:5
二叉堆的元素: 
6 8 
删除最小元素:6
二叉堆的元素: 
8 
删除最小元素:8
二叉堆的元素: 

binaryHeap is empty.
删除最小元素:0
二叉堆的元素: 

binaryHeap is empty.
删除最小元素:0
二叉堆的元素: 

*****************************************
測试第二个构造函数: 
二叉堆的元素: 
1 3 5 4 3 6 8 5 4 5 
删除最小元素:1
二叉堆的元素: 
3 3 5 4 5 6 8 5 4 
删除最小元素:3
二叉堆的元素: 
3 4 5 4 5 6 8 5 
删除最小元素:3
二叉堆的元素: 
4 4 5 5 5 6 8 
删除最小元素:4
二叉堆的元素: 
4 5 5 8 5 6 
删除最小元素:4
二叉堆的元素: 
5 5 5 8 6 
删除最小元素:5
二叉堆的元素: 
5 6 5 8 
删除最小元素:5
二叉堆的元素: 
5 6 8 
删除最小元素:5
二叉堆的元素: 
6 8 
删除最小元素:6
二叉堆的元素: 
8 
删除最小元素:8
二叉堆的元素: 

binaryHeap is empty.
删除最小元素:0
二叉堆的元素: 

binaryHeap is empty.
删除最小元素:0
二叉堆的元素:

转载于:https://www.cnblogs.com/gccbuaa/p/7261740.html

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号