二叉堆(JAVA实现)

定义

二叉堆(简称堆,当然还有别的堆),是一种具有特定规则的树形结构,二叉堆规定:父节点的值必定大于(小于)其孩子节点,因此可以称其为最大堆(最小堆),堆是维护极值的非常快速的一种数据结构。

实现思路

堆一般都是数组实现的(不明白用数组怎么写树的,请自己脑补,很容易想的)。
拿最小堆来说,堆的根节点一定是最小的,堆只可以从根节点取值,所以堆的调整是最重要的工作。
比如对数列: 10 1 11 9 6 建最小堆
开始,堆是空的,把10放进去(下标是1),再把1放进去(下标是2),1就是10的左孩子,但是由于1比10小,需要调正,把1和10对调。这样根节点变成了1,10是1的左孩子。接着把11放进去(下标是3),那11就是1的右孩子,11比1大,因此无需调整,接着把9放进去(下标是4),那9是10的左孩子,9比10小,调整,9比1大,无需调整,则树就变成了这样:
1
、、、、、好吧,图片有点大了。图片大人也大=。=
接着把6放进去(下标是5),那6是9的右孩子,6比9小,调整,1比6小,无需调整,树又变了个样:
2
以此类推,每次插入都是在数组最后,插入一次就要调整一次,递归去和父节点比,符合规则就调整。
取数同样需要调整,上面的例子,取出根节点1,把末尾的数(9)放到根节点,然后向下作出相应的调整。

代码(JAVA实现)

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * Created by Lee Y on 2016/4/2.
 * 最小堆JAVA实现
 */
public class CompleteTree {
  /*
   我这里用的是vector 已经过时了,建议使用arraylist
  */
    private Vector<Integer> list = new Vector<>();
    private  static final int start = 1;
    private int end = start;
    public CompleteTree(){
        addLength();
    }
    /*
    插入
     */
    public void insert(Integer item){
        if(end == list.size()){
            addLength();
        }
        list.set(end, item);
        insert_adapt();
        end++;
    }
    /*
     增加vector的长度,并初始化,vector虽然是动态的,但set方法不是动态的(add方法可以动态增加长度)
     对于某些情况叶子节点可能会取空,所以应该手动增加长度。
     */
    private void addLength(){
        for (int i=0;i<100;i++){
            list.add(0xfffffff);
        }
    }
    /*
    插入调整
     */
    private void insert_adapt(){
        int pos = end;
        Integer a,b;
        while(pos != 1){
            a = list.get(pos);
            b = list.get(pos>>1);
            if(a.intValue() < b.intValue()){
                list.set(pos>>1, a);
                list.set(pos, b);
            }
            pos >>= 1;
        }
    }
    /*
    取数调整
     */
    private void adapt(int c, int deep, int maxDeep){
        if(deep == maxDeep) return;
        else{
            int front = c<<1;
            int back = (c<<1)+1;
            Integer a = list.get(front);
            Integer b = list.get(back);
            Integer t = list.get(c);
            int i=a.intValue(),j=b.intValue(),k=t.intValue();
            if (k > i || k > j){
                if(i > j){
                    list.set(c, b);
                    list.set(back, t);
                    adapt(back,deep+1,maxDeep);
                }else{
                    list.set(c, a);
                    list.set(front, t);
                    adapt(front,deep+1,maxDeep);
                }
            }
            return;

        }
    }

    /*
    计算当前堆的深度
     */
    private int getDeep(){
        int i=0,c;
        while(true){
            c = 1<<i;
            i++;
            if(end <= c+c-1){
                break;
            }
        }
        return i;
    }

    /*
    取出堆顶
     */
    public Integer top(){
        Integer t = list.get(start);
        list.set(start, list.get(--end));
        list.set(end,0xfffffff);
        int c = getDeep();
        adapt(start,1,c);
        return t;
    }

    /*
     打印整个树,从上至下
     */
    public void print(){
        int hh = 1,weight = 0;
        for(int i=1;i<end;i++){
            System.out.print(list.get(i) + " ");
            if(i == hh){
                System.out.println();
                hh += (2<<weight);
                weight++;
            }
        }
        System.out.println();
    }

    public static void main(String[] args) {
        CompleteTree heap = new CompleteTree();
        int[] q = {1,10,11,9,6,7,15,2,3,16};
        int[] qq = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
        int[] qqq = {10,2,5,12,6,7,1,9,9,10,1,15,19,25,3,5,8};
        for(int i : qqq){
            heap.insert(i);
        }
        heap.print();
        System.out.println("#############################");
        System.out.println(heap.top());
        System.out.println("#############################");
        heap.print();
        System.out.println(heap.top());
        System.out.println("#############################");
        heap.print();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值