什么是堆?

①、它是完全二叉树,除了树的最后一层节点不需要是满的,其它的每一层从左到右都是满的。注意下面两种情况,第二种最后一层从左到右中间有断隔,那么也是不完全二叉树。

  

  ②、它通常用数组来实现。

  

  这种用数组实现的二叉树,假设节点的索引值为index,那么:

  节点的左子节点是 2*index+1,

  节点的右子节点是 2*index+2,

  节点的父节点是 (index-1)/2。

  ③、堆中的每一个节点的关键字都大于(或等于)这个节点的子节点的关键字。

  这里要注意堆和前面说的二叉搜索树的区别,二叉搜索树中所有节点的左子节点关键字都小于右子节点关键字,在二叉搜索树中通过一个简单的算法就可以按序遍历节点。但是在堆中,按序遍历节点是很困难的,如上图所示,堆只有沿着从根节点到叶子节点的每一条路径是降序排列的,指定节点的左边节点或者右边节点,以及上层节点或者下层节点由于不在同一条路径上,他们的关键字可能比指定节点大或者小。所以相对于二叉搜索树,堆是弱序的。

package alorgrithm;

public class HeapNode {
    private   int iData;
    public  HeapNode(int key){
        iData=key;
    }
    public int getKey(){
        return  iData;
    }
    public void setKey(int key){
        iData=key;
    }
}
package alorgrithm;

/***
 * 数组表示堆:若节点的索引是index
 * 节点的左节点:2*index+1
 * 节点的右节点:2*index+2
 * 节点的父节点:(index-1)/2
 * 堆中每一个节点的关键字都大于或者等于这个节点子节点的关键字
 * 堆遍历困难,每一条路径 ,只有从根节点到叶子节点是降序
 *
 *适合快速移除最大节点的操作以及快速插入新的节点的操作。
 *
 * 移除:删除关键字最大或者最小也就是根节点
 * 根节点在数组中的索引值总是0既maxNode=heapArray[0];
 * 移除后根节点空位填上:
 * 1.移走根
 * 2.把最后一个结点移动到根的位置上。
 * 3.一直向下筛选这个节点直到在一个大于它的节点之下,小于它的节点之上。
 * heapArray[0]=heapArray[N-1];
 *N--
 *向下筛选需要检查哪一个子节点更大,然后目标节点和较大的子节点交换位置。
 * 如果目标节点和较小的交换会违背堆的条件。
 * 插入:
 * 插入是向上筛选,初始时插入到数组最后一个空着的单元。
 * 数组容量大小增1.
 * heapArray[N]=newNode;
 * N++;
 * 向上筛选直到在一个大于它的节点之下,在一个小于它的节点之上。
 *向上筛选的算法比向下刷选的算法相对简单
 * 使用临时存储区减少复制次数。
 */
public class Heap {
   private  int maxSize;
   private int currentSize;
    private  HeapNode heapArray[];
    public  Heap(int maxSize)
    {
        this.maxSize=maxSize;
        heapArray=new HeapNode[maxSize];
    }

    /***
     * 移除:
     * 1.最后一个元素放入根节点
     * 2.向下筛选
     * 3.
     * @return   返回删除结点
     */
    public HeapNode remove(){
        HeapNode root=heapArray[0];
      heapArray[0]=heapArray[--currentSize];
      //currentSize--;

      trickDown(0);
      return  root;
    }
    /**
     * 1.先判断是否满,满则退出。
     * 2.插入到最后位置
     * 3.调用trickleUp(int  index ) 向上筛选
     * @return
     */
    public  boolean  insert(int iData){
      if(currentSize==maxSize){
          return  false ;
      }
      HeapNode newNode =new HeapNode(iData);
      heapArray[currentSize]=newNode;
      trickUp(currentSize++);
       return true;
    }

    /***
     * 临时存储区  HeapNode  bottpm
     * @param index
     */
    public  void trickUp(int  index){
        HeapNode bottoom = heapArray[index];
        int parent = (index - 1) / 2;
        while (index > 0 && (heapArray[parent].getKey()<bottoom.getKey())) {
            heapArray[index] = heapArray[parent];
            index = parent;
            parent = (parent - 1) / 2;
        }
        heapArray[index] = bottoom;
    }

    /***
     * 1.
     * @param index  向下筛选
     */
   public  void  trickDown(int  index){
      HeapNode   top= heapArray[index];//save   root
      int  lagerChild=0;

       while (index<currentSize/2) {//至少还有一个子节点    while  node has  at least one  child
           int leftChild =2*index+1;//leftChild
           int rightChild =leftChild+1;//rightChild
          System.out.println(" ----"+index);
           if(rightChild < currentSize && heapArray[leftChild].getKey()<heapArray[rightChild].getKey()){
               lagerChild=rightChild;
           }else {
               lagerChild=leftChild;
           }
           if (heapArray[lagerChild].getKey()<=top.getKey()) {
               break;
           }
           heapArray[index]=heapArray[lagerChild];//
           index=lagerChild;
       }
           heapArray[index]=top;
       }

       public   boolean  change(int index,int newValue){
         if(index<0||index>=currentSize){//合法性
             return false;
         }
         HeapNode  node =heapArray[index];

         if(newValue< node.getKey() ){
             trickUp(index);
         }else {
             trickDown(index);
         }
          return true;
       }

       public   void  show(){
          for(int i=0;i<currentSize;i++){
              System.out.print(heapArray[i].getKey() +   " |" );
          }
          System.out.println(" ---------------");
       }

       public   int getCurrentSize(){
       return   currentSize;
       }
       public   boolean isEmpty(){
       return   currentSize==0;
       }
   }

 

package alorgrithm;

public class HeapApp {

    public static void main(String[] args) {
        Heap  heap =new Heap(10);
        heap.insert(70);
        heap.insert(40);
        heap.insert(50);
        heap.insert(20);
        heap.insert(60);
        heap.insert(100);
        heap.insert(80);
        heap.insert(30);
        heap.insert(10);
        heap.insert(90);
        heap.show();
        System.out.println("currrent="+heap.getCurrentSize());
        heap.remove();
        heap.show();

    }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值