最近在学习集合框架整理下感觉有用的东西。
我们知道优先队列其实内部实现就是一个堆的数据结构,java默认的是一个小跟堆,每次取出最小的元素,因为堆的性质他可以做到O(logn)级别的插入和删除操作。
我们知道堆的性质是有:
1.堆中某个结点的值总是不大于(或不小于)其父结点的值;
2.堆总是一棵完全二叉树。
将根结点最大的堆叫做大根堆,根结点最小的堆叫做小根堆。常见的堆有二叉堆、斐波那契堆等
插入:向堆中插入一个新元素;在数组的最末尾插入新结点。然后自下而上调整子结点与父结点:比较当前结点与父结点,不满足堆性质则交换,使得当前子树满足二叉堆的性质。时间复杂度为 O(logn)。
弹出:删除堆顶元素,再把堆存储的最后那个结点填在根结点处。再从上而下调整父结点与它的子结点。时间复杂度为 O(logn)。
删除:使该元素与堆尾元素交换,调整堆容量,再由原堆尾元素的当前位置自顶向下调整。时间复杂度为 O(logn)。
如果经常需要合并两个堆的操作,那么使用二项堆、斜堆、左偏树等数据结构会更好。
可并堆支持合并操作,使得合并后的堆也能保持堆的性质。左偏树是可并堆的一种,保证左子树的深度大于右子树的深度,再用右子树与另一个堆合并。
因此,堆支持查询最值、插入、删除操作。
堆排序,通过堆维护最值,对最值逐个弹出,使得得到的序列有序。
下面看下一般的堆我们都直接用优先队列实现如下
import java.io.BufferedInputStream;
import java.util.Comparator;
impor