第二章 2.4优先队列

来源:互联网 发布:goto是java关键字吗 编辑:程序博客网 时间:2024/06/04 19:57
优先队列定义

     一种常见的数据结构,需要支持两种6+ 操作:删除最大(最小)元素和插入元素,这种数据结构类型叫做优先队列。
优先队列的实现
  • 数组实现(无序):删的时候才找出最大的元素
  • 有序数组实现:insert的之后就排序
  • 链表表示法:基于链表的下压栈,可以选择修改Push或者Pop来实现功能对比
        


      原因:许多应用程序都需要处理有序的元素,但不一定要求它们全部有序,或是不一定要一次就将它们排序。很多情况下,我们会收集一些元素,处理当前键值最大的元素,然后再收集更多的元素,再处理当前键值最大的元素,如此这般。如有一台能够运行多个应用程序的电脑,通过为每个应用程序分配一个优先级,并总是处理下一个优先级最高的事件来实现。

操作:删除最大元素和插入元素。

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

索引优先队列

       在很多应用中,允许用例引用已经进入优先队列中的元素是有必要的。做到这一点的一种简单方法是给每个元素一个索引。比如,一种常见的情况是用例已经有了总量为N的多个元素,而且可能还同时使用了多个(平行)数组来存储这些元素的信息。

       理解这种数组结构的较好方法是将它看成能够快速访问其中最小元素的数组。事实上,它能够快速访问数组的一个特定子集中的最小元素(指所有被插入的元素)。





API

优先队列是一种抽象数据类型,它表示了一组值和这些值的操作,他的抽象层使我们能够方便地将应用程序(用例)和我们将在本节中学习的各种具体实现隔离开来。

优先队列是队列的一种,不过它可以按照自定义的一种方式(数据优先级)来对队列中的数据进行动态的排序。



堆的定义

数据结构二叉堆能够实现优先队列的基本操作。在二叉堆的数组中,每个元素都要保证大于等于另两个而定位置的元素
定义:叉当一颗二叉树的每个结点都大于等于它的两个子结点时,它被称为堆有序。

二叉堆定义:就是堆有序的完全二叉树,元素再数组中按照层级存储
用指针表示堆有序的二叉树。
      二叉堆是一组能够用堆有序的完全二叉树排序的元素,在一个堆中,位置k的结点的父结点的位置为【k/2】朝下的,而它的两个子结点的位置分别为2k和2k+1。因为结点是在数组中按照层级储存。由此,我们通过计算数组的索引在书中上下移动:从a[k]向上一层就令k等于k/2,向下一层则令k等于2k或2k+1。
      用数组(堆)实现的完全二叉树的结构是很严格的,但它的灵活性足以让我们实现优先队列。用它们我们将能实现对数级别的插入元素和删除最大元素的操作。
      
命题P:一棵大小为N的完全二叉树的高度为【lgN】取底下
证明:通过归纳可以证明且当N达到2的幂时树的高度会加1.

命题Q:对于一个含有N个元素的基于堆的优先队列,插入元素操作只需不超过(lgN+1)次比较,删除最大元素的操作需要不超过2lgN次比较。
证明:由命题P可知,两种操作都需要在根结点和堆底之间移动元素,而路径的长度不超过lgN。对于路径上的每个结点,删除最大元素需要两次比较(除了堆底元素),一次用来找出较大的子结点,一次用来确定子结点是否需要上浮。



索引优先队列

在很多应用中,允许用例引用优先队列中的元素是很有必要的。做到这一点的一种简单方法就是给每一个元素一个索引。另外,一种常见的情况是用例已经有了总量为N的多个元素,而且可能还同时使用了多个(平行)数组来存储这些元素的信息。

      理解这种数据结构的一个较好方法是将它看成一个能够快速访问其中最小元素的数组。事实上,它能够快速访问数组的一个特定子集中的最小元素。

命题Q:在一个大小为N 的索引优先队列中,插入元素、改变优先级、删除和删除最小元素操作所需的比较次数和logN成正比
证明:已知堆中所有路径最长~lgN......。



堆排序

我们可以把任意优先队列变成一种排序方法。
  • 将所有元素插入一个查找最小元素的优先队列,然后再重复调用删除最小元素的操作来将它们按顺序删除。
用无序数组实现的优先队列这么做相当于进行一次插入排序。
用基于堆的优先队列这样做等同于哪种排序???堆排序
堆排序(利用堆的构造来对元素进行排序)
堆排序分为两个阶段。
  • 在堆的构造过程中,我们将原始数组重新组织安排进一个堆中;
  • 然后在下沉排序阶段,我们从堆中按递减顺序取出所有元素并得到排序结果。