Priority Queue

Heap(Priority Queue)

优先队列(Priority Queue)是一种非常重要的数据结构,本文将讨论对于优先队列的有效实现以及优先队列的使用。一般来说,优先队列一定具有两个基本操作:插入Insert和删除最小DeleteMin。

Basic Implementation

最简单的实现是简单链表(LinkedList),在链表头或者尾插入元素(O(1)),再遍历链表找到最小元素并删除(O(N))。或者一直保持链表排序(O(N)),这样删除最小只用花费(O(1))。

另一种实现方式是查找二叉树(Binary Search Tree)。插入是随机的,花费O(logN)的时间,删除最小则一直删除最左边的元素(O(logN)),如上时间花费都是平均时间。由于最小元素一直被删除,树的结构将被影响(最坏情况下树的深度将是其期望深度的两倍)。

Heap

堆(Heap)能够在O(logN)的时间内将如上两个操作完成。

堆具有结构性堆序性两个性质,而对于堆的任意插入(Insert)和删除最小(DeleteMin)都可能破坏这两个性质。因此,我们所有对堆的操作都要维持这两个操作。

结构性

堆的结构是一棵Complete Binary Tree,意味着堆是个完全填满的二叉树(底层由左往右插入元素,可以不满),其高(height)为logN。因为完全二叉树的规律,我们不需要使用链表实现堆,而可以用一个普通数组实现它。对于任意在i上的元素,左儿子是2i,右儿子是2i+1,母亲是i/2

堆序性

为了快速实现DeleteMin这一操作,我们应当始终确保最小元素在根(Root)的位置上。我们应当确保任意结点都小于他的孩子

Heap Operations

如上文所说,优先队列(堆)有两个基本操作:Insert和DeleteMin,我们将在下文中探讨如何实现这两个基本操作。

Insert

  1. 将插入元素插入到堆的下一个位置中(末尾指针处),如果堆的堆序性没有被破坏,那么插入完成。
  2. 如果堆的堆序性被破坏,我们交换该元素与其父节点。重复这一过程,一直到堆序性没有被破坏为止。

这一过程被称作Percolate Up。

public void insert(AnyType x) 
{
  if(currentSize == array.length - 1) 
  {
    enlargeArray(array.length * 2 + 1);
  }

  int hole = currentSize++;
  for(array[0] = x; x.compareTo(array[hole]) < 0; hole/=2) 
  {
    array[hole] = array[hole/2]; //将swap需要3步的操作化简为1步
  }
  array[hole] = x;
}

最坏情况:插入元素是最小值(O(logN))

DeleteMin

public AnyType deleteMin() 
{
  if(isEmpty()) 
    throw new UnderflowException();

  AnyType min = findMin();
  array[1] = array[currentSize--];
  percolateDown(1);

  return min;
}

public void percolateDown(int hole) 
{
  int child;
  AnyType tmp = array[hole];

  for(; hole * 2 <= currentSize; hole = child) {
    child = hole * 2;
    if(child != currentSize && array[child + 1].compareTo(array[child]) < 0) {
      child++;
    } //ensure we use smaller child for later comparison

    if(array[child].compareTo(tmp) < 0) 
    {
      array[hole] = array[child];//swap a[hole] and a[child]
    } else {
      break;
    }
  }
  array[hole] = tmp;
}

最坏情况:O(logN)从根下滤到最底层

decreaseKey

decreaseKey(p, key)降低p处的值,降低的幅度为key。降低后做一次上滤。

increaseKey

increaseKey(p, key)增加p处的值,增加的幅度为key。增加后做下滤。

delete

删除某一结点p:执行decreaseKey(p, MAX_INTEGER),再执行deleteMin。

buildHeap

执行N次Inert即可。每次Insert平均时间是O(1),最坏时间是O(logN),所以该操作平均时间是O(N)


   Reprint policy


《Priority Queue》 by Mie is licensed under a Creative Commons Attribution 4.0 International License
 Previous
周六野 + 林芊妤 健身计划 周六野 + 林芊妤 健身计划
参考豆瓣鹅组原帖:https://www.douban.com/group/topic/138221315/ Fat Burn Everyday下面是筛选出来每天一定会做的四个视频(update 2019/07/08) 矫正假胯宽(周六野
2019-06-19
Next 
Stack and Queue Stack and Queue
Stack and Queue抽象数据类型(Abstract Data Type): 带有一组操作的一些对象的集合 Stack ADT栈本质是个表 from infix to postfix 遇见操作数,放到输出队列中,遇见操作符,push
2019-06-11
  TOC