热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

最大堆MaxHeap和最小堆MinHeap的实现(转)

队列的特点是先进先出。通常都把队列比喻成排队买东西,大家都很守秩序,先排队的人就先买东西。但是优先队列有所不同,它不遵循先进先出的规则&#

       队列的特点是先进先出。通常都把队列比喻成排队买东西,大家都很守秩序,先排队的人就先买东西。

       但是优先队列有所不同,它不遵循先进先出的规则,而是根据队列中元素的优先权,优先权最大的先被取出。通常把优先队列比喻成现实生活中的打印。一个打印店里有很多打印机,每台机器的性能不一样,有的打印机打印很快,有的打印机打印速度很慢。当这些打印机陆陆续续打印完自己的任务时进入排队等候状态。如果我这个时候要打印一份文件,我选的不是第一个排队的打印机,而是性能最好,打印最快的打印机。

       优先队列的特点就是将存储的元素根据其优先权的高低,先取出优先权高的元素。所以,优先队列的实现方法有很多。

       如果优先权的范围是已知的,那么就可以尝试用一个二维数组来实现优先队列。每一行表示一个优先级别。例如用大小为a[10][10]的二维数组来实现一个优先队列,a[0]表示一个优先级别,里面存放优先级为0的元素,a[10]则存放优先级最高的元素。这样根据元素的优先级进行存储,取出元素的时候,根据优先级,先取出优先级最高的元素。

       上面的方法在优先权范围已知且比较集中可以估计的情况下可以适用,但是如果优先权的范围不清楚,或者间隔很大,就不再使用。实现优先队列也可以用一个链表队列加以实现。链表的节点数据包含两个部分,队列的数据项和该数据项的优先权。将元素存入链表,需要用时,遍历链表,查找优先权最大的数据项。

 

优先队列式分支界限法解装载问题中需要用到最大堆MazHeap,但是书上没有给出代码,所以只能我们自己写了,下面我贴出这两个数据结构的代码,以供参考。解决了这两个数据结构,那么优先队列式分支界限法就很好实现了。

最大堆MaxHeap:

 

[cpp] view plaincopy
  1. #include  
  2. using namespace std;  
  3. typedef struct Heap  
  4. {  
  5.     int capacity;  
  6.     int size;  
  7.     int *Elem;  
  8. }Heap,*HeapQueue;  
  9. #define MaxData 32767  
  10. HeapQueue init(int maxElem)  
  11. {  
  12.     HeapQueue H;  
  13.     H=(HeapQueue)malloc(sizeof(Heap));  
  14.     H->capacity=maxElem;  
  15.     H->size=0;  
  16.     H->Elem=(int *)malloc((maxElem+1)*sizeof(int));  
  17.     H->Elem[0]=MaxData;  
  18.     return H;  
  19. }  
  20. void InsertMax(int x,HeapQueue H)  
  21. {  
  22.     int i;  
  23.     for(i=++H->size;H->Elem[i/2]
  24.         H->Elem[i]=H->Elem[i/2];//此时i还没有进行i/2操作  
  25.     H->Elem[i]=x;  
  26. }  
  27. int DeleteMax(HeapQueue H)  
  28. {  
  29.     int i,child;  
  30.     int MaxElem,LastElem;           //存储最大元素和最后一个元素。  
  31.     MaxElem=H->Elem[1];              //堆是从第1号元素开始的。  
  32.     LastElem=H->Elem[ H->size-- ];    //这里自动让size减少了。  
  33.     for(i &#61; 1 ; i * 2 <&#61; H->size ; i &#61; child)  
  34.     {  
  35.         child&#61;i * 2;  
  36.         /*在节点有左右子树的时候&#xff0c;可能存在一个大一个小的情况&#xff0c;这时候我们就要找出最小的&#xff1b; 
  37.           如果Child &#61; H->Size则表明他没有右子树&#xff0c;这时候就没有必要比较了。 
  38.         */  
  39.         if(child !&#61; H->size && H->Elem[child&#43;1]>H->Elem[child])  
  40.             child&#43;&#43;;//找最大的子树  
  41. // 与 H->Elem[i]&#61;LastElem; 结合&#xff0c;将两个孩子和 lastElement 中较大的放入祖先节点
  42.         if(LastElem < H->Elem[child])  
  43.             H->Elem[i]&#61;H->Elem[child];
  44.     }  
  45.     H->Elem[i]&#61;LastElem;  
  46.     return MaxElem;  
  47. }  
  48. void MakeEmpty(HeapQueue H)  
  49. {  
  50.     H->size&#61;0;  
  51. }  
  52. int FindMax(HeapQueue H)  
  53. {  
  54.     return H->Elem[1];  
  55. }  
  56. void DestoryH(HeapQueue H)  
  57. {  
  58.     free(H->Elem);  
  59.     free(H);  
  60. }  
  61. int main()  
  62. {  
  63.       
  64.     HeapQueue H&#61;init(4);  
  65.     int i;  
  66.     for(i&#61;1;i<&#61;3;i&#43;&#43;)  
  67.         InsertMax(i,H);  
  68. /* 
  69.     cout<size< 
  70.     for(i&#61;1;i<&#61;3;i&#43;&#43;) 
  71.         cout<Elem[i]< 
  72. */  
  73.     int a&#61;DeleteMax(H);  
  74.     cout<
  75.     return 1;  
  76. }  

 

 

最小堆MinHeap&#xff1a;

 

[c-sharp] view plaincopy
  1. #include  
  2. using namespace std;  
  3. typedef struct Heap  
  4. {  
  5.     int capacity;  
  6.     int size;  
  7.     int *Elem;  
  8. }Heap,*HeapQueue;  
  9. #define MinData -32767  
  10. HeapQueue init(int maxElem)  
  11. {  
  12.     HeapQueue H;  
  13.     H&#61;(HeapQueue)malloc(sizeof(Heap));  
  14.     H->capacity&#61;maxElem;  
  15.     H->size&#61;0;  
  16.     H->Elem&#61;(int *)malloc((maxElem&#43;1)*sizeof(int));  
  17.     H->Elem[0]&#61;MinData;  
  18.     return H;  
  19. }  
  20. void Insert(int x,HeapQueue H)  
  21. {  
  22.     int i;  
  23.     for(i&#61;&#43;&#43;H->size;H->Elem[i/2]>x;i/&#61;2)  
  24.         H->Elem[i]&#61;H->Elem[i/2];//此时i还没有进行i/2操作  
  25.     H->Elem[i]&#61;x;  
  26. }  
  27. int DeleteMin(HeapQueue H)  
  28. {  
  29.     int i,child;  
  30.     int MinElem,LastElem;  
  31.     MinElem&#61;H->Elem[1];//堆是从第1号元素开始的。  
  32.     LastElem&#61;H->Elem[H->size--];//这里自动让size减少了。  
  33.     for(i &#61; 1 ; i * 2 <&#61; H->size ; i &#61; child)  
  34.     {  
  35.         child&#61;i * 2;  
  36.         /*在节点有左右子树的时候&#xff0c;可能存在一个大一个小的情况&#xff0c;这时候我们就要找出最小的&#xff1b; 
  37.           如果Child &#61; H->Size则表明他没有右子树&#xff0c;这时候就没有必要比较了。 
  38.         */  
  39.         if(child !&#61; H->size && H->Elem[child&#43;1]Elem[child])  
  40.             child&#43;&#43;;  
  41.         if(LastElem>H->Elem[child])  
  42.             H->Elem[i]&#61;H->Elem[child];  
  43.     }  
  44.     H->Elem[i]&#61;LastElem;  
  45.     return MinElem;  
  46. }  
  47. void MakeEmpty(HeapQueue H)  
  48. {  
  49.     H->size&#61;0;  
  50. }  
  51. int FindMin(HeapQueue H)  
  52. {  
  53.     return H->Elem[1];  
  54. }  
  55. void DestoryH(HeapQueue H)  
  56. {  
  57.     free(H->Elem);  
  58.     free(H);  
  59. }  
  60. int main()  
  61. {  
  62.     /* 
  63.     HeapQueue H&#61;init(4); 
  64.     int i; 
  65.     for(i&#61;1;i<&#61;4;i&#43;&#43;) 
  66.         Insert(i,H); 
  67.     int a&#61;DeleteMin(H); 
  68.     cout< 
  69.     */  
  70. }  

 

 

 

本文参考了http://blog.csdn.net/xw13106209/article/details/4942331

 



推荐阅读
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了一个程序,可以输出1000内能被3整除且个位数为6的所有整数。程序使用了循环和条件判断语句来筛选符合条件的整数,并将其输出。 ... [详细]
  • Day2列表、字典、集合操作详解
    本文详细介绍了列表、字典、集合的操作方法,包括定义列表、访问列表元素、字符串操作、字典操作、集合操作、文件操作、字符编码与转码等内容。内容详实,适合初学者参考。 ... [详细]
author-avatar
尕尕东东东_534
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有