PriorityQueue原理与最简实现[java]

2021-01-25  本文已影响0人  qiHuang112
import java.util.Arrays;

/**
 * 优先队列
 * 功能:
 * 1.offer - 添加,如果达到容量上限且无法自动扩容,返回false
 * 2.poll - 移除 -- 按顺序
 * 3.peek - 查看栈顶元素
 * 4.grow - 如果达到容量上限,自动扩容
 * 5.isEmpty - 检查是否为空
 * 思路:
 * 构建小顶堆
 * 每次offer,将数据放到末尾,向上调整(小数上浮)
 * 每次poll,将末尾的数放到最前,向下调整(大数下沉)
 */
public class PriorityQueue {
    int size = 0;
    int[] nums;

    public PriorityQueue() {
        nums = new int[16];
    }

    public boolean offer(int n) {
        if (size == nums.length) grow();
        if (size == nums.length) return false;
        // 小数上浮
        siftUp(n, size++);
        return true;
    }

    private void siftUp(int target, int i) {
        int child = i, parent;
        while (child > 0) {
            parent = (child - 1) >> 1;
            if (nums[parent] <= target) break;
            nums[child] = nums[parent];
            child = parent;
        }
        nums[child] = target;
    }

    public int poll() {
        if (isEmpty()) throw new IndexOutOfBoundsException("队列为空");
        int res = nums[0];
        size--;
        // 大数下沉
        siftDown(nums[size], size);
        return res;
    }

    private void siftDown(int target, int i) {
        int parent = 0, child;
        while ((child = (parent << 1) + 1) < i) {
            if (child + 1 < i && nums[child + 1] < nums[child]) child++;
            if (target <= nums[child]) break;
            nums[parent] = nums[child];
            parent = child;
        }
        nums[parent] = target;
    }

    public int peek() {
        if (isEmpty()) throw new IndexOutOfBoundsException("队列为空");
        return nums[0];
    }

    private void grow() {
        if (nums.length == Integer.MAX_VALUE) return;
        int len = nums.length << 1;
        if (len < 0) len = Integer.MAX_VALUE;
        System.out.println(String.format("完成扩容:%d -> %d", nums.length, len));
        nums = Arrays.copyOf(nums, len);
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public static void main(String[] args) {
        PriorityQueue queue = new PriorityQueue();
        int[] arr = new int[]{35, 88, 45, 37, 91, 26, 13, 66, 50, 16, 7, 3, 20, 17, 8, 67, 21};
        for (int i : arr) {
            queue.offer(i);
        }
        for (int i = 0; i < arr.length; i++) {
            arr[i] = queue.poll();
        }
        System.out.println(Arrays.toString(arr));
        System.out.println(queue.peek());
    }
}

上一篇下一篇

猜你喜欢

热点阅读