Java 允许更改密钥的最大堆数

Java 允许更改密钥的最大堆数,java,key,max,heap,Java,Key,Max,Heap,有人知道Java中的max heap实现吗?它允许您添加具有特定键的元素,然后以某种方式将它们保留在堆中,以便在恒定时间内获得max key元素。它还允许您在O(logn)时间内更改某些元素的键。我认为这意味着堆会跟踪堆中每个元素的位置。如果您计划执行大量递增键操作,那么您可能需要查看斐波那契堆或布罗达尔队列,因为它们为递增键操作提供了更好的渐近复杂性。谷歌搜索那些带有Java关键字的特定名称可能会找到您所需要的 我发现了一个: 这里是一个简单的实现,它实现了堆上的所有操作,时间复杂度在注释中给

有人知道Java中的max heap实现吗?它允许您添加具有特定键的元素,然后以某种方式将它们保留在堆中,以便在恒定时间内获得max key元素。它还允许您在O(logn)时间内更改某些元素的键。我认为这意味着堆会跟踪堆中每个元素的位置。

如果您计划执行大量递增键操作,那么您可能需要查看斐波那契堆或布罗达尔队列,因为它们为递增键操作提供了更好的渐近复杂性。谷歌搜索那些带有Java关键字的特定名称可能会找到您所需要的

我发现了一个:


这里是一个简单的实现,它实现了堆上的所有操作,时间复杂度在注释中给出,并给出了一些解释。您可以删除main方法中的注释字符以 请参阅其他操作的工作原理。随时欢迎您提出任何疑问

/*ALL DISCUSSION IS IN CONTEXT OF MAX HEAP.EXTRACTING THE MAX OR MIN TAKES O(LOG N) TIME. FIRST WE REMOVE THE VERY FIRST ELEMENT WHICH IS THE MAXIMUM (OR THE MINIMUM.
     * (IN CASE OF MIN HEAP)THEN WE PUT THE LAST ELEMENT IN FRONT POSITION. THIS TAKES CONSTANT TIME.THEN WE INITIATE HEAPIFY AT POSITION 1, WHICH WILL
     * TAKE TIME O(LOGN) BECAUSE HEIGHT AT POSITION 1 IS H AND HEAPIFY INITIATED AT HEIGHT H TAKES O(H) TIME.SO THE TIME COMPLEXITY 
     * OF THIS ALGO IS O(LOG N) WHERE HEIGHT OF HEAP=H=LOG N. 
     */


import java.util.*;
class HEAP
{
 private LinkedList<Integer> heap;

 public static void main(String []args)
 {
     Scanner s=new Scanner(System.in);

     System.out.println("enter the number elements in the heap");
     int n=s.nextInt();
     HEAP o = new HEAP();
     o.heap=new LinkedList<Integer>();
     for(int i=0;i<n;++i)
      o.heap.add(s.nextInt());


     o.build_heap();
     o.heapsort();
     System.out.println("the sorted elements are");
     for(int e:o.heap)
      System.out.println(e);
     /*   
     //int max=o.extract_max();
     System.out.println();
     o.insert(300);
     System.out.println("Max Heap is");
     for(int e:o.heap)
      System.out.print(e+" ");
     o.increase_key(3,900);
     System.out.println();
     System.out.println("Max Heap is");
     for(int e:o.heap)
      System.out.print(e+" ");*/
 }
 public void build_heap()
 {
     for(int i=heap.size()/2;i>=1;--i)
      heapify(i,heap.size());
 }
 public int extract_max()
 {
     int max=heap.remove(0);
     int last=heap.remove(heap.size()-1);
     heap.add(0,last);
     heapify(1,heap.size());
     return max;
 }
 public void heapify(int i,int size)
 {
     int l=2*i,r=l+1;
     int largest;
     if(l<=size&&heap.get(l-1)>heap.get(i-1))
      largest=l;
     else largest=i;

     if(r<=size&&heap.get(r-1)>heap.get(largest-1))
      largest=r;
     if(largest!=i)
     {
         int temp=heap.get(i-1);
         heap.set(i-1,heap.get(largest-1));
         heap.set(largest-1,temp);
         heapify(largest,size);
     }    
 }   


 /*ITS PRETTY STRAIGHT FORWARD ALGORITHM FIRST U INCREASE THE KEY AND THEN YOU BEGIN THE COMPARISON WITH THE PARENT BECAUSE U HAVE
  * INCREASED SO THE CHILD SUBTREES WOULD BE ALRIGHT ALL U HAVE TO DO IS BEGIN COMPARISON WITH THE PARENT AND GO ON TILL ROOT IF
  * U HAVE TO. TIME TAKEN IS O(LOG N). WORST CASE OCCURS WHEN FROM LEAF YOU TRAVEL ALL THE WAY UP TO ROOT.
  */
 public void increase_key(int i,int k)
 {
     if(k<= heap.get(i-1))
      System.out.println("The increase_key did not go all the way through");
     int temp;
     heap.set(i-1,k);
     /*Now the left and right subtrees are fine but its parent may be upset so get to it and do this till root if you have to*/
     while(i>1&&heap.get(i-1)> heap.get(i/2-1))
     {
        temp=heap.get(i-1);
        heap.set(i-1,heap.get(i/2-1));
        heap.set(i/2-1,temp);
        i=i/2;
     }
 }
 /*IT IS ALSO A PRETTY STRAIGHT FORWARD ALGORITHM. YOU DECREASE THE KEY NOW CAUSE ITS MAX HEAP THE PARENT IS ALL FINE BUT THE 
  * CHILD MAY BE UPSET SO BEST THING TO DO IS TO CALL THE HEAPIFY ALGORITHM FROM THE INDICATED POSITION.WORST CASE TIME TAKEN IS
  * OR SIMPLY THE TIME TAKEN IS O(LOG N). WORST CASE OCCURS WHEN FROM ROOT YOU GO ALL THE WAY TO LEAF.
  */
 public void decrease_key(int i,int k)
 {
     if(k>=heap.get(i-1))
      System.out.println("The increase_key did not go all the way through");
     heap.set(i-1,k);
     /*Now after decreasing the key the parent is fine but the child may be upset so why not call heapify*/
     heapify(i,heap.size());
 }
 /*INSERT IS ALSO PRETTY MUCH STRAIGHT FORWORD BECAUSE . SIMPLY INSERT AT LAST POSITION. THEN START THE COMPARISON FROM ITS PARENT
  * AND THIS BUSINESS MAY CONTINUE ALL THE WAY UP TO THE ROOT. HENCE THE TIME TAKEN IS O(LOG N) AND THE WORST CASE OCCURS WHEN
  * THE BUSINESS DOES REALLY GO UP TO THE ROOT. REMEMBER WHEN WE MENTION THAT TIME TAKEN IS O(LOG N), IT ALSO MEANS THAT THIS IS
  * THE WORST TIME BECAUSE IT MEANS THAT IN NO CASE THE TIME TAKEN CAN BE GREATER THAN CLOG N , C>0. BUT THIS DOES NOT NECESSARILY
  * MEAN IT IS ALWAYS THE TIME.
  */
 public void insert(int k)
 {
     /*element inserted at last position and from its parent work begins of comparing and will go on till root if it has to*/     
     heap.add(k);     
     int temp;
     int i=heap.size();
     while(i>1&&heap.get(i/2-1)<heap.get(i-1))
     {
        temp=heap.get(i-1);
        heap.set(i-1,heap.get(i/2-1));
        heap.set(i/2-1,temp);
        i=i/2;
     }
 }
 /*HEAPSORT IS VERY CLEVER ALGORITHM THAT TAKES NLOG(N) TIME IN ALL CASES AND IS IN PLACE. MERGESORT IS AN ALGORITHM HAS TIME
  * PERFORMANCE EQUIVALENT TO HEAPSORT BUT ITS SPACE COMPLEXITY IS ALWAYS LINEAR. QUICKSORT IS INPLACE BUT IN WORST CASE IT TAKES
  * TIME QUADRATIC. HEAPSORT IS A WIN WIN SITUATION, IT SEEMS TO BE BECAUSE IT WINS OVER BOTH QUICKSORT AND MERGESORT.HEAPSORT
  * DOES NOT MAKE USE OF CACHE MEMORY BECAUSE THERE IS NO LOCALITY OF REFERENCE AND THE REFERECES ARE SPREAD OUT IN MEMORY. 
  * TECHNIQUE IS VERY SIMPLE. THE LARGEST ELEMENT IS FIRST ONE SO WE SWAP IT WITH THE LAST ELEMENT AND DECREASE THE HEAP SIZE BY
  * ONE AND THEN CALL HEAPIFY(1) SO THAT IT DOES NOT EFFECT THE LAST ELEMENT AS WE HAVE DECREMENTED THE SIZE BY ONE.ALSO THE LAST
  * ELEMENT IS AT ITS CORRECT POSITION, THAT IS WHY WE DO NOT WANT TO DISTURB IT AND THEREFORE WE DECREASE THE SIZE BY ONE. WE WILL
  * REPEAT THIS STEP N-1 TIMES BECAUSE THE SMALLEST ELEMENT WILL AUTOMATICALLY BE IN ITS APPROPRIATE PLACE.
  * 
  * HEAPSORT HOWEVER IS NOT PREFERRED.THE REASON IS:
  * 
  * HEAPSORT IS NOT A STABLE SORTING ALGORITHM. THE REASON IS BECAUSE IT DOES NOT PRESERVE THE RELATIVE ORDER OF THE ELEMENTS WITH
  * SAME KEY. SAY THE HEAP IN STARTING OF THE ALGO IS A C ..... D D ......S. SO WHEN THE SORTING WILL BE DONE, THE D ON THE LEFT 
  * WILL BE REMOVED FIRST AND THEN THE D ON RIGHT WILL BE REMOVED, THIS IS KIND OF SWAPPING OF THE POSITIONS AND THIS IS THE REASON
  * WHY HEAPSORT IS NOT STABLE.
  * SECONDLY HEAPSORT IS NOT CACHE FRIENDLY DUE TO LACK OF LOCALITY OF REFERENCE. THE REFERENCES IN THE ARRAY ARE MADE IN SUCH WAY
  * THAT THE CACHE MISS ARE MORE THAN IN THE CASE OF QUICKSORT.
  */
 public void heapsort()
 {
     LinkedList<Integer> sorted=new LinkedList<Integer>();
     int k=heap.size();
     for(int i=1;i<heap.size();++i)
     {
      int temp=heap.get(0);
      heap.set(0,heap.get(k-1));
      heap.set(k-1,temp);
      heapify(1,--k);
      System.out.println();
      for(int e:heap)
       System.out.print(e+" ");
     }      
 } 
}
/*所有讨论都是在MAX HEAP的上下文中进行的。提取MAX或MIN需要O(LOG N)时间。首先,我们删除第一个元素,它是最大值(或最小值)。
*(在最小堆的情况下)然后我们把最后一个元素放在前面的位置。这需要固定的时间。然后我们在位置1启动HEAPIFY,它将
*需要时间O(LOGN),因为位置1处的高度是H,而在高度H处启动HEAPIFY需要O(H)时间
*这个算法的最大值是O(logn),其中堆的高度=H=logn。
*/
导入java.util.*;
类堆
{
私有链接列表堆;
公共静态void main(字符串[]args)
{
扫描仪s=新的扫描仪(System.in);
System.out.println(“在堆中输入数字元素”);
int n=s.nextInt();
HEAP o=新堆();
o、 heap=newlinkedlist();
对于(int i=0;i=1;--i)
heapify(i,heap.size());
}
公共整数提取_max()
{
int max=heap.remove(0);
int last=heap.remove(heap.size()-1);
添加(0,最后一个);
heapify(1,heap.size());
返回最大值;
}
公共void heapify(整数i,整数大小)
{
int l=2*i,r=l+1;
int最大;
if(lheap.get(i-1))
最大=l;
else=i;
if(rheap.get(最大-1))
最大=r;
如果(最大!=i)
{
int temp=heap.get(i-1);
heap.set(i-1,heap.get(max-1));
堆集(最大-1,温度);
heapify(最大,尺寸);
}    
}   
/*它的算法非常简单,首先增加密钥,然后开始与父级进行比较,因为
*增加子子树,这样子子树就可以了,你所要做的就是开始与父子树进行比较,如果
*你必须这样做。所花的时间是O(logn)。最坏的情况发生在你从叶子一直到根的时候。
*/
公共无效增加密钥(int i,int k)
{
if(k1&&heap.get(i-1)>heap.get(i/2-1))
{
temp=堆获取(i-1);
heap.set(i-1,heap.get(i/2-1));
堆集(i/2-1,温度);
i=i/2;
}
}
/*这也是一个非常直截了当的算法。你现在减少密钥,因为它的最大堆。父级都很好,但是
*孩子可能会心烦意乱,所以最好的办法是从指定的位置调用HEAPIFY算法。最坏的情况是
*或者简单地说,所花费的时间是O(logn)。最坏的情况发生在从根到叶的过程中。
*/
公共密钥(int i,int k)
{
if(k>=heap.get(i-1))
System.out.println(“增加键没有完全通过”);
堆集(i-1,k);
/*现在,在减少关键点后,家长很好,但孩子可能会不高兴,那么为什么不打电话给heapify呢*/
heapify(i,heap.size());
}
/*INSERT也是非常直接的FORWORD,因为。只需在最后一个位置插入。然后从其父级开始比较
*这种业务可能会一直持续到根目录,因此所花费的时间是O(logn),最坏的情况发生在
*业务确实是深入到了根本。记住,当我们提到耗时是O(logn)时,也意味着这是
*最糟糕的时间,因为这意味着在任何情况下所花费的时间都不能超过阻塞N,C>0。但这并不一定
*我的意思是,时间总是有的。
*/
公共空白插入(int k)
{
/*在最后一个位置插入的元素,从其父工作开始比较,如果必须的话,将一直到根*/
heap.add(k);
内部温度;
int i=heap.size();

while(i>1&&heap.get(i/2-1)这对我来说真的不起作用,因为我需要一个最大堆,所以我可以使用最小堆,将所有值设为负值,但我需要一个递增键,而这个键只有一个递减键。对于最小堆,通常只能递减键,而对于最大堆,通常只能递增键。子树上的heapify操作是等效的要增加密钥,将有O(logn)时间。