Java-优先级队列(堆)实现

Java-优先级队列(堆)和堆排序实现
一,优先级队列的概念
优先级队列中,数据按关键词有序排列,插入新数据的时候,会自动插入到合适的位置保证队列有序。
举个例子来说,一组整型数,如果使用优先级队列的话,不管队列之前放入的数据如何,后面添加进去的数据总会被按照升序或者降序排列,优先队列的头是基于自然排序或Comparator排序的最小元素。
如果有多个对象拥有同样的排序,那么就可能随机地取其中任意一个。当我们获取队列时,返回队列的头对象。

二,优先级队列的方法
1,优先级队列是比栈和队列更专用的结构,在多数情况下都非常有用。优先级队列像普通队列一样,有一个队头和队尾,并且也是从队头移除数据
2,优先级队列中的元素可以按照任意顺序插入, 却总是按照排序的顺序检索;也就是说, 无论何时调用 remove方法, 总会获得当前优先队列中最小的元素
最大堆基本操作

public class MaxHeap{
    //存取元素动态数组
    private ArrayList<Integer> data;
    public MaxHeap (){
        data = new ArrayList<>();
    }
    public  MaxHeap(int capacity){
        data = new ArrayList<>(capacity);
    }
    //添加元素
    public void add(int val){
        //1,向数组末尾添加元素
        data.add(val);
        //2,调整当前堆的结构,使其仍满足最大堆
        siftUp(data.size() - 1);
    }
     /**
     * 取出当前堆的最大值
     * 继续调整堆
     */
    public int extractMax() {
        if (isEmpty()) {
            System.err.println("heap is empty!");
            return -1;
        }
        int max = data.get(0);
        // 将最后一个元素顶到堆顶
        int lastVal = data.get(data.size() - 1);
        data.set(0,lastVal);
        // 移除最后一个元素
        data.remove(data.size() - 1);
        // siftDown
        siftDown(0);
        return max;
    }
    //堆化heapify
    public MaxHeap(int[] arr){
        data = new ArrayList<>(arr.length);
    }
    public boolean isEmpty(){
        return data.size() == 0;
    }
    //获取父节点索引
    private int parent(int k){
        return (k - 1)/2;
    }
    private int left(int k){
        return 2 * k + 1;
    }private int right(int k){
        return 2 * k + 2;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0;i < data.size();i++) {
            sb.append(data.get(i));
            if(i != data.size() - 1) {
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}

元素上浮操作

    /**
     * 元素上浮操作
     * @param i 上浮元素索引
     */
    private void siftUp(int i) {
        while (i > 0 && (data.get(i) > data.get(parent(i)))){
            swap(i,parent(i));
        }
        //继续向上判断交换后父节点向上的节点关系
        i = parent(i);

    }
    //交换当前数组i和parent的值
    private void swap(int i, int parent) {
        int temp = data.get(i);
        int parentVal = data.get(parent);
        data.set(i,parentVal);
        data.set(parent,temp);
    }

元素下浮操作

 private void siftDown(int i) {
        while (left(i) < data.size()) {
            int j = left(i);
            // 取出左右孩子的最大值
            if (right(i) < data.size()) {
                int leftVal = data.get(left(i));
                int rightVal = data.get(right(i));
                if (leftVal < rightVal) {
                    j = j + 1;
                }
            }
            // j一定是左右孩子最大值的索引
            // data[i] 和 data[j]
            if (data.get(i) >= data.get(j)) {
                // 当前节点已经大于左右孩子,下沉结束
                break;
            }else {
                // swap(i,j);
                swap(i,j);
                i = j;
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜羊羊zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值