数据结构之小顶堆的添加,取出 及 创建

package com.sun.test;

import java.util.Arrays;
import java.util.Comparator;

public class HeapTestmin<E>{

   Comparator<E> comparator;
   int size;
   E[] elements;
   //取得堆中最大元素并删除
   //最大堆最大值一定是根节点,当删除根节点时需要改变堆结构,使得当前最大值称为新的根节点
   //通过对比得知,将堆中最大值删除后可将数组最后一个元素放于根节点位置,而后再将根节点与左右孩子值比较进行下沉操作
   //下沉思路:将根节点与左右孩子值对比,与较大值交换,直到叶子结点或当前节点比左右孩子值都大时停止下沉操作
   //将堆中最大值删除后返回删除的最大值
   public E getmin(){
       E e=elements[0];
       this.swrap(0, size-1);
       elements[--size]=null;
       this.minheap(0);
       return e;
   }
   
   //因数组可能出现存储满的情况,故需要扩容
   private void grow(){
       int oldCap=elements.length;
       int newCap=oldCap+(oldCap<64?oldCap:oldCap>>1);
       if(newCap>Integer.MAX_VALUE-8)
           throw new IndexOutOfBoundsException("数组太大");
       elements= Arrays.copyOf(elements,newCap);
   }
   /**
    * 一 。将节点添加在扩充数组是最后一个位置
    * 二。然后数组最后一个位置与父节点依次对比;
    * @param temp
    */
   public void add(E temp){
       if(size==elements.length){
          grow();
       }
       elements[size++]=temp;
       //进行添加
       this.siftadd(size-1);
   };
   /**
    *
    * @param index
    */
   private void siftadd(int index) {
       while(index>0&&
               this.compare(elements[index], elements[parentIndex(index)])<0){
           int parentIndex=this.parentIndex(index);
           this.swrap(index, parentIndex);
           index=parentIndex;
       }
       
   }
  /**
   * 构造方法创建小顶堆
   * @param arr
   */
@SuppressWarnings("unchecked")
   public  HeapTestmin(E[] arr){
       size=arr.length;
       elements=(E[])new Object[size];
       for(int i=0;i<size;i++){
           elements[i]=arr[i];
       }
       for(int i=(size-1-1)/2;i>=0;i--){
          this.minheap(i); 
       } 
   }

  /**
   * 小顶堆的点坐标与左右子节点进行比较,是否需要下沉
   * 实现思路从下往上一次开始
   * @param index
   */
  private void minheap(int index) {
      while(this.leftChildIndex(index)<size){
          int left=this.leftChildIndex(index);
          if(left+1<size){
              //拥有双子节点 左右
              if(this.compare(elements[left], elements[left+1])>0){
                  left++;
              }
          }
          if(this.compare(elements[index], elements[left])<0){
              break;
          }
          //交换
          swrap(index, left);
          index=left;
      }
      
  }
  public void swrap(int i,int j){
      E temp=elements[i];
      elements[i]=elements[j];
      elements[j]=temp;
      
  }
  //比较器
  public int compare(E o1,E o2){
      if(comparator==null)
          return ((Comparable<E>)o1).compareTo(o2);
      return comparator.compare(o1,o2);
  }   
  //计算左子节点 
  public int  leftChildIndex(int index){
      return 2*index+1;
  }
  //计算右子节点
  public int  rightChildIndex(int index){
      return 2*index+2;
  }
  public int   parentIndex(int index){
      return (index-1)/2;
  }
  @Override
  public String toString() {
      StringBuilder res=new StringBuilder();
      for(E e:elements){
          if(e!=null)
              res.append(e+" ");
      }
      return res.toString();
    }
  
  
  
  public static void main(String[] args) {
      Integer[] nums=new Integer[]{9,8,7,6,5,4,3,2,1,10};
      HeapTestmin<Integer> heapTestmin=new HeapTestmin<>(nums);
      System.out.println("将任意数组变为堆结构:");
      System.out.println(heapTestmin);
      heapTestmin.add(4);
      System.out.println(heapTestmin);
      System.out.println(heapTestmin.getmin());
      System.out.println(heapTestmin);
 }
}

 

posted @ 2020-08-05 11:10  sunjinwei123  阅读(398)  评论(0)    收藏  举报