优先队列的数组、二叉堆实现

一个合适的数据结构应该支持两种操作:删除最大元素和插入元素。这种数据类型叫做优先队列

实现栈或是队列与实现优先队列的最大不同在于对性能的要求。对于栈和队列,我们的实现能够在常数时间内完成所有操作;
而对于优先队列,我们刚刚讨论过的所有初级实现中,插入元素删除最大元素这两个操作之一在最坏情况下需要线性时间来完成。

优先队列的数组、二叉堆实现_第1张图片


API

优先队列的数组、二叉堆实现_第2张图片

一个优先队列的用例

问题:输入N个字符串,每个字符串都对映着一个整数,从中找出最大的M个整数。
分析:

  • 将输入排序然后从中找出M个最大的元素(不适于输入非常大的情况)
  • 将每个新的输入和已知的M个最大元素比较(除非M较小,否则这种比较的代价非常高昂)
public class TopM
{
    public static void main(String[] args)
    {
        //打印输入流中最大的M行
        int M = Integer.parseInt(args[0]);
        MinPQ pq = new MinPQ(M+1);

        while(StdIn.hasNextLine())
        {
            //为下一行输入创建一个元素并放入优先队列中
            pq.insert(new Transation(StdIn.readLine()));
            if(pq.size() > M)
                pq.delMin(); //如果优先队列中存在M+1个元素删除其中最小的元素
        } //最大的M个元素都在优先队列中

        Stack stack = new Stack();
        while(Qpq.isEmpty()) stack.push(pq.delMin());
        for(Transaction t : stack) System.out.println(t);
        //降序打印
    }
}

初级实现

数组实现(无序)

基于数组的下压栈。

  • insert()跟push()完全一样
  • delMax()可以对pop()添加选择排序的内循环,将最大元素和边界元素交换然后删除它。

数组实现(有序)

  • insert()中添加插入排序,将所有较大的元素向右移动一格以使数组保持有序。
  • delMax()和pop()一样。

链表表示法

基于链表的下压栈,其他修改同数组实现。

二叉堆实现

堆的定义

当一颗二叉树的每个节点都大于等于它的两个子节点时,它被称为堆有序

二叉堆表示法

完全二叉树只用数组而不需要指针就可以表示。将二叉树的节点按照层级顺序放入数组中。

二叉堆是一组能够用堆有序的完全二叉树排序的元素,并在数组中按照层级储存(不使用数组的第一个位置)。
——在一个堆中,位置k的节点的父节点的位置为【k/2】,而它的两个子节点的位置分别为2k和2k+1。

堆实现的比较和交换方法
优先队列的数组、二叉堆实现_第3张图片

堆有序化(上浮)
优先队列的数组、二叉堆实现_第4张图片

堆有序化(下沉)
优先队列的数组、二叉堆实现_第5张图片

基于堆的优先队列
优先队列的数组、二叉堆实现_第6张图片

参考《Algorithm》

你可能感兴趣的:(算法)