大根堆Java实现

具体创建原理;自行百度,这里仅仅提供实现的思路
import java.util.Arrays;
//usage:
//插入:add
//删除;remove
//查找;contains
//排序:heapSort

// 大根堆建立
// 核心方法:heapInsert和heapify

/**
 * 插入元素时候:堆上升
 * 删除元素时候:堆下沉
 * 堆排序和删除相关
 */
public class BigHeap{
    // 大根堆
    private int[] heap;  // 堆结构
    private int size;   // 堆中元素数量
    private int limit;  // 当前堆容量

    public BigHeap(int limit){
        heap = new int[limit];
        this.limit = limit;
        this.size = 0;
    }
    public BigHeap(){
        heap = new int[10];
        this.limit = 10;
        this.size = 0;
    }
    // 插入
    // 真正对外暴露的插入方法   === 可以实现扩容
    public void add(int value){
        // 空间不够数组扩容  --复制 + 扩容0.75倍
        if (this.size + 1 > this.limit){
            // copyOf:将数组复制到heap中,并指定新长度,返回新数组
            heap = Arrays.copyOf(heap,(int)(this.limit<<1));
            this.limit = heap.length;
        }
        // 插入元素
        heap[this.size] = value;
        heapInsert(heap,this.size);
        this.size++;
    }
    // 每次插入一个插入元素
    // index是当前元素位置  index 范围:0~arr.length-1
    private void heapInsert(int[] arr,int index){
        while (arr[index] > arr[(index - 1) / 2]){
            swap(arr,index,(index - 1)/2);
            // 当前元素上移
            index = (index - 1) / 2;
        }
    }

    // 删除
    // 暴露在外的接口   -- 堆顶 index = 0,非堆顶index != 0
    public Integer remove(){
        if (this.size == 1){
            this.size--;
            return heap[this.size];
        }
        else if (!isEmpty()){
            swap(heap,0,this.size-1);
            this.size--;
            heapify(heap,0);
            return heap[this.size];
        }
        return null;
    }
    // 删除堆中一个堆顶元素后进行下沉调整   -- 默认删除堆顶元素
    private void heapify(int[] arr,int index){
        // 要考虑好左右孩子存在的情况,画一下就出来了
        // 3种情况
        while (index < this.size){
            int left = (index<<1 | 1);
            int right = ((index<<1) + 2);
            // 左右孩子最大元素下标,没有左右孩子返回-1
            int maxIndex = right < this.size?(arr[left] <= arr[right]?right:left):(left < this.size?left:-1);
            // 判断是否继续下沉  maxIndex == -1说明index没有左右孩子了,调整结束
            if (maxIndex == -1 || arr[index] > arr[maxIndex])
                break;
            swap(arr,index,maxIndex);
            // 坐标下沉
            index = maxIndex;
        }
    }
    // 删除堆中指定元素  -- 以待删除元素为根的树调整结构
    public boolean remove(int value){
        // indexOf:求元素下标,-1:没有
        if (isEmpty() || indexOf(value) == -1)
            return false;
        else if (heap[this.size-1] == value){
            this.size--;
        }
        // 最后一个一定不是value,所以可以这末写
        for (int i = 0;i < this.size;i++){
            if (heap[i] == value){
                // 调整结构
                swap(heap,i,this.size-1);
                this.size--;
                heapify(heap,i);
                break;
            }
        }
        return true;
    }

    // 查找
    // 查看堆顶元素  -- 只看不删
    public int peek(){
        return heap[0];
    }
    //查看堆顶元素   -- 看完删
    public int poll(){
        return remove();
    }
    // 查找元素
    public boolean contains(int value){
        // 非空情况下查找
        if (!isEmpty()){
            for (int i = 0; i < this.size; i++) {
                if (heap[i] == value)
                    return true;
            }
        }
        return false;
    }

    // 工具
    // 求指定元素的下标
    public int indexOf(int value){
        if (!isEmpty()){
            for (int i = 0; i < this.size; i++) {
                if (heap[i] == value)
                    return i;
            }
        }
        return -1;
    }
    // 交换两个元素的位置
    private void swap(int[] arr,int i,int j){
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }
    // 判断堆是否为空
    public boolean isEmpty(){
        return this.size == 0;
    }
    // 打印数组
    public void print(){
        if (this.size == 0){
            System.out.println("[]");
            return;
        }
        String str = "[";
        if (size == 1){
            str += heap[0] + "]";
            System.out.println(str);
            return;
        }
        for (int i = 0; i < size-1; i++) {
            str += heap[i]+",";
        }
        str += heap[size-1]+"]";
        System.out.println(str);
    }
    // 推排序  --- 每次将最大值删除放到新数组里面   -- 知道原理读者可以自己利用已有方法写
    public static void heapSort(int[] arr){
        BigHeap b = new BigHeap(1);
        if (arr == null || arr.length == 0)
            return;
        // 插入元素
        for (int i = 0; i < arr.length; i++) {
            b.add(arr[i]);
        }
        // 复制回arr中
        int length = b.size;
        for (int i = 0; i < length; i++) {
            arr[i] = b.remove();
        }
    }

    // test
    public static void main(String[] args) {
        BigHeap b = new BigHeap(1);
        int[] arr = new int[]{3,1,2,5,0,89,7};
        b.add(1);
        System.out.println(b.remove());
        b.heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值