深度剖析优先级队列(堆)

这篇博客介绍了二叉树的顺序存储方式,特别是完全二叉树如何用数组表示。堆作为一种特殊的二叉树结构,被用于实现快速查找集合中最值的功能。文中详细阐述了大堆和小堆的概念,以及向下调整和建堆的操作。此外,还展示了堆在优先级队列中的应用,包括入队列和出队列的操作,并给出了Java实现的示例代码。最后,强调了通过实践来巩固这些知识的重要性。
摘要由CSDN通过智能技术生成
  1. 二叉树的顺序存储

1.1堆的表示:使用数组保存二叉树结构,二叉树用层序遍历方式放入数组中。(一般只适合表示完全二叉树,因为非完全二叉树会有空间的浪费。)(下图是一个完全二叉树)
在这里插入图片描述1.2.下标关系

left = 2 * parent +1
right = 2 * parent +2
parent = (child - 1)/2

2.堆(heap)

2.1概念:
堆逻辑上是一棵完全二叉树
堆物理上是保存在数组中
满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆
反之,则是小堆,或者小根堆,或者最小堆(示例如下)
堆的基本作用是,快速找集合中的最值
在这里插入图片描述
2.2向下调整操作

public static void shiftDown(int[] array,int size,int index) {
        while (true) {
            //1.判断是否为叶子节点
            int left = index * 2 + 1;
            if(left >= size) {
                return;
            }
            //2.找左右孩子中最小的孩子
            int min = left;
            int right = left + 1;
            if(right < size && array[right] < array[left]) {
                min = right;
            }
            //判断小孩子和 index 位置的值的大小
            if(array[index] <= array[min]) {
                return;
            }
            //3.交换
            int t = array[min];
            array[min] = array[index];
            array[index] = t;
            //4.继续比较
            index = min;
        }
    }

时间复杂度为O(log(n))

2.3建堆操作如下:

public static void createHeap(int[] array,int size) {
        for (int i = (size -1 - 1) / 2; i >= 0 ; i--) {
            shiftDown(array,size,i);
        }
    }

3.堆的应用——优先级队列

3.1入队列操作

    public void adjustUp(int[] array,int size,int index) {
        while (true) {
            //1.判断 index 是不是树的根
            if(index == 0) {
                break;
            }
            //2.跟父节点比较  大于父节点的值 退出
            int parent = (index - 1) / 2;
            if(array[parent] <= array[index]) {
                break;
            }
            //交换父节点和index的值
            int t = array[parent];
            array[parent] = array[index];
            array[index] = t;
            //3.把父节点视为孩子继续比价
            index = parent;
            //4.到顶,退出
        }
    }

3.2 java中的优先级队列
PriorityQueue implements Queue

抛出异常返回特殊值
add(e)offer(e)
remove()poll()
element()peek()

分别为入队列、出队列、队首元素的操作。
程序代码:

public class PriorityQueueDemo {
    public static void main(String[] args) {
        MyPriorityQueue queue = new MyPriorityQueue();
        queue.add(3);
        queue.add(5);
        queue.add(2);
        queue.add(7);
        System.out.println(queue.remove());
    }
}
public class MyPriorityQueue {
    private Integer[] array;
    private int size;

    public MyPriorityQueue() {
        array = new Integer[100];
        size = 0;
    }

    public Integer element() {
        if(size == 0) {
            throw new RuntimeException("空");
        }
        return array[0];
    }

    public Integer remove() {
        if(size == 0) {
            throw new RuntimeException("空");
        }

        int e = array[0];
        array[0] = array[size - 1];
        size--;
        adjustDown(0);
        return e;
    }
    public  void add(Integer e) {
        array[size] = e;
        size++;
        adjustUp(size-1);
    }
    public void adjustUp (int index) {
        while (true) {
            //1.判断 index 是不是树的根
            if(index == 0) {
                break;
            }
            //2.跟父节点比较  大于父节点的值 退出
            int parent = (index - 1) / 2;
            if(array[parent] <= array[index]) {
                break;
            }
            //交换父节点和index的值
            int t = array[parent];
            array[parent] = array[index];
            array[index] = t;
            //3.把父节点视为孩子继续比价
            index = parent;
            //4.到顶,退出
        }
    }

    private void adjustDown(int index) {
        while (true) {
            int left = index * 2 + 1;
            if(left >= size) {
                return;
            }
            int right = left + 1;
            int min = left;
            if(right < size && array[right] < array[left]) {
                min = right;
            }
            if(array[index] <= array[min]) {
                return;
            }
            int t = array[index];
            array[index] = array[min];
            array[min] = t;
            index = min;
        }
    }
}

总之还是要多练习的呀!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值