实现一个优先队列

实现一个优先队列

实现一个优先队列,队列需要添加元素,删除元素,获得最大(小)元素等方法。要实现这样的一个队列,至少需要在添加元素,删除元素的时候维护队列元素的顺序,以保证队列头结点是最大(小)值。我考虑了两种方式:

1. 维护一个顺序的List

只要我维护一个顺序的list,很容易能取到最大(小)值。
说到list,如何实现一个list,大体上分两种:数组和链表。数组和链表各有各的优势和缺点,数组的缺点需要指定数组大小,必要时扩容(数组copy),优点是数组可以进行二分查找优化查找效率。链表缺点是无法进行二分查找以及每个Node合起来占的内存(以java来讲会多一个java对象头和引用指针大小),优点是无限扩容(不oom的前提下)。

如果是用数组实现的list

用插入排序的思路,每次插入删除元素的时候,都保证这个List是以顺序排序的。假设List以从小到大排序,插入的时候每次都插入到前一个元素比自己小后一个元素比自己大的中间,删除的时候把后面的元素index提前一位。这样插入删除的时间复杂度都是O(n),实现起来也非常简单。在插入和删除中可以进一步优化查询的操作,用二分查找这样可以稍微提升效率,但考虑到元素的前移后移,最终插入或者删除的时间复杂度还是O(n)

如果是用链表实现的list

查找上无法用到二分查找,所以无论是查找还是插入,删除都会是O(n)

优化

一种支持O(lgn)的链表结构:跳表

跳表

跳表结构大致如此,其实就是用多个链表维护了多级索引,以此达到了O(lgn)查找和插入的效率。

2. 维护一个最大(小)堆

说到保证头结点是最大(小)值,就想到了最大(小)堆,他是一种二叉结构,以最大堆为例,他要求根节点的关键字既大于或等于左子树的关键字值,又大于或等于右子树的关键字值,所以最大堆的顶堆就是最大值。这样的一个数据结构插入的时间复杂度是O(lgn),而删除的复杂度是O(n)。因为一个remove(T node)函数中首先要找到nodeindex,这一个查找的时间复杂度就是O(n)(在堆这种结构中也无法用类似二分查找的优化)。

你可能感兴趣的:(实现一个优先队列)