多图详解:二叉堆原理并手写一个优先队列

1 优先队列应用

队列是一种先进先出的数据结构,先放入队列的元素会先出队列。但是有这样一种场景,我们希望出队列顺序不是根据放入队列顺序,而是根据元素本身具有的优先级,例如元素优先级高则先出队列,这时就要使用优先队列。

1.1 应用一

我们设想这样一种发送消息的业务场景:消息具有优先级属性,在同一个队列中优先发送优先级高的消息,优先级定义如下:

// 优先级 P1 > P2 > p3
public enum PriorityEnum {

    P1(1, "优先级1"),

    P2(2, "优先级2"),

    P3(3, "优先级3")
    
    ;
}

消息对象定义如下:

public class MyMessage implements Comparable {

    /**
     * 消息优先级
     */
    private int priority;

    /**
     * 消息内容
     */
    private String messge;

    public MyMessage(int priority, String message) {
        this.priority = priority;
        this.messge = message;
    }

    @Override
    public int compareTo(Object obj) {
        MyMessage message = (MyMessage) obj;
        return this.priority - message.priority;
    }
}

java.util.PriorityQueue可以实现上述功能:

public class PriorityQueueTest {
    public static void main(String[] args) {
        PriorityQueue<MyMessage> messageQueue = new PriorityQueue<MyMessage>();
        MyMessage m1 = new MyMessage(PriorityEnum.P1.getCode(), "message1");
        MyMessage m2 = new MyMessage(PriorityEnum.P2.getCode(), "message2");
        MyMessage m3 = new MyMessage(PriorityEnum.P3.getCode(), "message3");
        messageQueue.offer(m3);
        messageQueue.offer(m1);
        messageQueue.offer(m2);
        while (messageQueue.size() > 0) {
            System.out.println(messageQueue.poll());
        }
    }
}

代码执行结果:

send message=MyMessage(priority=1, messge=message1)
send message=MyMessage(priority=2, messge=message2)
send message=MyMessage(priority=3, messge=message3)

PriorityQueueTest消息放入优先队列顺序:

3、1、2

PriorityQueueTest从优先队列获取消息顺序:

1、2、3

1.2 应用二

现在消息优先级进行业务变更:

// 优先级 P3 > P2 > p1
public enum PriorityEnum {

    P1(1, "优先级1"),

    P2(2, "优先级2"),

    P3(3, "优先级3")
    
    ;
}

此时预期输出顺序如下:

3、2、1

如果要达到预期输出顺序代码要进行如下变更:

public class MyMessage implements Comparable {

    @Override
    public int compareTo(Object obj) {
        MyMessage message = (MyMessage) obj;
        return message.priority - this.priority; // 比较关系变更
    }
}

2 二叉堆

在第一章节我们看到PriorityQueue可以实现按照元素优先级顺序进行输出,那么其底层原理是什么呢?答案是二叉堆。

2.1 什么是二叉堆

二叉堆分为大顶堆和小顶堆,我们首先看大顶堆,从下图可以看到整棵树中最大值在根节点,所以称为大顶堆:

我们再看小顶堆,从下图可以看到整棵树中最小值在根节点,所以称为小顶堆: 

2.2 怎么存储二叉堆

二叉堆看似复杂,其实用数组就可以表示,我们以大顶堆为例:

第一步声明一个长度为10的数组,因为二叉树总共有10个节点:

int[] array = new int[10]

第二步设置根节点100作为数组第一个元素:

array[0] = 100

第三步设置所有节点至数组相应位置:

leftChildIndex = (parentIndex * 2) + 1
rightChildIndex = (parentIndex * 2) + 2

例如设置90至

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值