在优先级队列中,元素出队列的顺序由元素的优先级决定。
堆是实现优先级队列效率很高的数据结构——堆,是一棵完全二叉树,用数组表示:1,1左2,1右3,2左4,2右5,3左6,3右7.
12.1 定义和应用
优先级队列是0个或多个元素的集合,每个元素都有一个优先权或值。top查找,push插入,pop删除。在最小优先级队列(min priority queue)中,查找和删除的元素都是优先级最小的元素;max priority queue中相反。优先级队列的元素可以有相同的优先级,对这样的元素,查找和删除可以按任意数序处理。
12.2 抽象数据类型(Abstract Data Type, ADT)
template<class T>
class maxPriorityQueue
{
public:
virtual ~maxPriorityQueue(){}
virtual bool empty() const = 0; //return true, when the queue is empty.
virtual int size() const = 0; //return the number of elements in the queue.
virtual const T& top() = 0; //return the reference of element with the biggest priority.
virtual void pop() = 0; //delete the head element of the queue.
virtual void push(const T& theElement) = 0;//insert element named theElement.
}
C语言的ADT形式:
struct maxPriorityQueue
{
...
...
};
12.4 堆
12.4.1 定义
一棵大根树(小跟树)是这样的一棵树,其中每个节点的值都大于(小于)或等于其子节点(如果有子节点的话)的值。不是非得是二叉树。
当大根树(小根树)以完全二叉树的形式组织起来时就是大根堆(小根堆)。即,一个大根堆(小根堆)既是大根树(小根树)也是完全二叉树。
堆是完全二叉树,用一位数组可以有效描述。
12.4.2 大根堆的插入
procedure:将新元素插入新节点(数组最后面,位置为 k),然后沿着新节点到根节点的路径(每次 k/2/2/.../2,向下取整)执行一趟气泡操作,将新元素与其父节点的元素比较交换,直到父节点大于或等于前者为止。
上述插入策略是从一个叶子到根的一趟气泡过程,每一层的比较操作需要耗时Θ(1), 因此,实现这种插入策略的时间复杂性为O(h) = O(logn)。
12.4.3 大根堆的删除
在大根堆中删除一个元素,就是删除根节点的元素。
procedure:删除堆顶元素(数组第一个元素);
将最后一个节点 m 拿到堆顶。
每层将m与这个元素左右孩子比较大小看子树是否是大根堆,每层如此,直到把m放进堆里。
删除策略形成一条从根节点到一个叶节点的路径。每一层操作(比较与替换)需耗时Θ(1),所以删除的时间复杂度为O(logn)。
12.4.5 大根堆的初始化
1.从0开始构建大根堆:
要建立n个元素的大根堆,我们需要在空堆中执行n次插入操作,每次插入O(logn),所以n次的总时间是O(nlogn)。我们也可以用不同策略在Θ(n)时间内完成堆的初始化。
2.将数组存储的二叉树转化构建成大根堆:
从最后一个有孩子的节点开始倒着确保大根堆,每当以某一个节点为根的子树不是大根堆时,就将调整为大根堆:将这个节点逐层与孩子中的最大值比较,逐层交换,直到形成大根堆。时间复杂度:O(2^h * h^2)???
12.6 应用
12.6.1 堆排序(heap sort)
堆可以用来实现n个元素的排序,所需时间为O(nlogn).先用n个待排序的元素来初始化一个大根堆( initialize O(n) ),然后从堆中逐个提取(即删除)元素。结果这些元素就是按非递增顺序排列。初始化的时间O(n), 每次删除的时间为O(logn), 因此总时间为O(n+nlogn) = O(nlogn)。
template <class T>
void HeapSort(T a[], int n)
{//Sort a using the heap sort method
//create a max heap of the elements
MaxHeap<T> H(1);
H.Initialize(a,n,n);
//extract one vy one from the max heap
T x;
for(int i = n-1; i >= 1; i--){
H.DeleteMax(x);
a[i+1] = x;
}
//save array a from heap destructor
H.Deactivate();
}