JAVA 堆 与 优先级队列 关系

流过昼夜 提交于 2020-02-28 20:28:22

一 : 堆
什么是堆?
堆可以理解成一个完全二叉树
在这里插入图片描述
只不过堆是以数组的形式表现出来的
满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆4. 反之,则是小堆,或者小根堆,或者最小堆。

大堆与小堆可以用于筛选数组之中最大值或是最小值,
比如在千万级别的数据中找到前五个最大的值,那么就要建立一个有五个元素的小堆,每一次筛选,如果筛选的元素比堆顶就找到堆顶最小的元素将其换下来

那么怎么进行堆的排序呢?
有向上调整和向下调整

如果是一个不规则的堆,那么就要从最后一个非叶子节点向下调整
这里以大堆举例

public static void shiftDownBig(int[] arr, int sz, int parent){
        int child = 2 * parent + 1;  // left child

        // 从parent节点开始,一直调整到叶子节点结束
        while(child < sz){
            //right child : child + 1 从两个孩子节点中选一个最大的
            if(child + 1 < sz && arr[child + 1] > arr[child]){
                ++child;
            }
            if(arr[child] > arr[parent]){
                //如果child 大于 parent, 向下调整,交换值
                swap(arr, child, parent);
                //更新,继续向下调整
                parent = child;
                child = 2 * parent + 1;
            }
            else{
                //不需要调整
                break;
            }
        }
    }

这只是一次调整,在建堆的时候要进行好几次,直到根部节点
建堆:

    public static void creatHeapBig(int[] arr){
        //从最后U一个非叶子节点开始向下调整
        for(int i = (arr.length - 2) / 2; i >= 0; --i){
            shiftDownBig(arr, arr.length, i);
        }
    }

而小堆的向下调整和建堆,只需要把条件换一下就好了

//小堆的向下调整
    public static void shiftDownSmall(int[] arr, int sz, int parent){
        int child = 2 * parent + 1;  // left child

        // 从parent节点开始,一直调整到叶子节点结束
        while(child < sz){
            //right child : child + 1 从两个孩子节点中选一个最小的
            if(child + 1 < sz && arr[child + 1] < arr[child]){
                ++child;
            }
            if(arr[child] < arr[parent]){
                //如果child 大于 parent, 向下调整,交换值
                swap(arr, chi, parent);
                //更新,继续向下调整
                parent = child;
                child = 2 * parent + 1;
            }
            else{
                //不需要调整
                break;
            }
        }
    }
    public static void creatHeapSmall(int[] arr){
        //从最后U一个非叶子节点开始向下调整
        for(int i = (arr.length - 2) / 2; i >= 0; --i){
            shiftDownSmall(arr, arr.length, i);
        }
    }

二 ,优先级队列
在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理
次高的对象。最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电
话。
在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。
这种数据结构就是优先级队列(Priority Queue)

主要还是用堆来进行完成

入队操作就是尾插到最后一个位置,然后从最后一个位置,然后向上调整

    private int[] arr = new int[10];
    private int sz;
    //入队
    public void offer(int value){
        if(sz == arr.length){
            arr = Arrays.copyOf(arr, arr.length *  2);
        }
        //  1.  尾插
        //  2.  向上调整
        arr[sz++] = value;
        MHeap.shiftUpSmall(arr, sz, sz - 1);
    }

poll的话是将根部元素与最后一个元素进行互换,然后把最后的删掉,然后再从根部往下整理堆

    //出队
    public int poll(){
        if(sz > 0){
            int peek = arr[0];
            MHeap.swap(arr, 0,  sz - 1);
            --sz;
            MHeap.shiftDownSmall(arr, sz, 0);
            return peek;
        }
        return -1;
    }

    public int peek(){
        return arr[0];
    }
    public boolean isEmpty(){
        return sz == 0;
    }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!