堆(优先队列)

一、堆

什么是堆?

用完全二叉树表示的优先队列

优先队列:取出元素的顺序依据优先级的大小   处理的问题思想类似于CPU处理任务时的优先级

堆的特性:1.结构性 2.有序性

如果最小键值元素拥有最高的优先级,那么这种优先队列叫作升序优先队列(即总是先删除最小的元素),类似的,如果最大键值元素拥有最高的优先级,那么这种优先队列叫作降序优先队列(即总是先删除最大的元素)。一般默认的优先队列为升序优先队列。

1.1堆的一些基本操作

插入insert:插入元素,并以一定的顺序排序。类似队列里的入队enqueue操作

删除deleteMin/deleteMax:删除最小值或者最大值元素。类似队列里的出队dequeue操作

1.2堆的应用

  • 数据压缩:哈夫曼编码算法;
  • 最短路径算法:Dijkstra算法;
  • 最小生成树算法:Prim算法;
  • 事件驱动仿真:顾客排队算法;
  • 选择问题:查找第k个最小元素

 

二、二叉堆

二叉堆就是每个结点最多有两个孩子,所以也有d堆对应的就是最多有d个孩子

用数组表示堆是一个比较常规且方便的方法。

一个结点对应的数组索引是i,它的左子结点就是i*2,右子结点就是i*2+1,它的父节点就是i整除2

2.1向堆中添加元素和Percolate Up(上滤)

当插入一个元素到堆中时,它可能不满足堆的性质,在这种情况下,需要调整堆中元素的位置使之重新变成堆,这个过程称为堆化(heapifying);在最大堆中,要堆化一个元素,需要找到它的父亲结点,如果不满足堆的基本性质则交换两个元素的位置,重复该过程直到每个结点都满足堆的性质为止

2.2取出堆中的最大元素和Percolate Down(下沉)

取出堆中的最大元素(堆顶元素)将变得容易,不过这里运用到一个小技巧,就是用最后一个元素替换掉栈顶元素,然后把最后一个元素删除掉,这样一来元素的总个数也满足条件,然后只需要把栈顶元素依次往下调整就好了,这个操作就叫做Percolate Down(下沉)

三、Java中的PriorityQueue

在Java中也实现了自己的优先队列PriorityQueue,与我们自己写的不同之处在于,Java中内置的为最小堆,然后就是一些函数名不一样,底层还是维护了一个Object类型的数组,另外如果想要把最小堆变成最大堆可以给PriorityQueue传入自己的比较器,例如:

// 默认为最小堆
PriorityQueue<Integer> pq = new PriorityQueue<>();

pq.add(5);
pq.add(2);
pq.add(1);
pq.add(10);
pq.add(3);

while (!pq.isEmpty()) {
    System.out.println(pq.poll() + ", ");
}
System.out.println();
System.out.println("————————————————————————");

// 使用Lambda表达式传入自己的比较器转换成最大堆
PriorityQueue<Integer> pq2 = new PriorityQueue<>((a, b) -> b - a);
pq2.add(5);
pq2.add(2);
pq2.add(1);
pq2.add(10);
pq2.add(3);

while (!pq2.isEmpty()) {
    System.out.println(pq2.poll() + ", ");
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值