1 概述
优先级队列:出队列顺序由元素的优先级决定。
堆:一棵完全二叉树,是实现优先级队列效率很高的数据结构。
(STL类priority-queue是用堆实现的优先级队列)
定义:
优先级队列:0个或多个元素的集合,每个元素具有一个优先权或值。
可完成操作:查找一个元素(top)、插入一个元素(push)、删除一个元素(pop)
分类:最小优先级队列、最大优先级队列
抽象数据类型:
最大优先级队列ADT实现:
template<class T>
class maxPriorityQueue
{
public:
virtual ~maxPriorityQueue() {}
virtual bool empty() const = 0;
// return true iff queue is empty
virtual int size() const = 0;
// return number of elements in queue
virtual const T& top() = 0;
// return reference to the max element
virtual void pop() = 0;
// remove the top element
virtual void push(const T& theElement) = 0;
// add theElement to the queue
};
#endif
2 堆
2.1 定义
大根树(小根树):每个节点的值都大于(小于)或等于其子节点的值
大根堆(小根堆):既是大根树(小根树),又是完全二叉树。
完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
2.2 操作
(1)大根堆的插入:
注:插入位置随着插入元素值大小变化,目的是不改变堆的“大根性”
(2)大根堆的删除
a为上图d删除21的结果;c为继续删除20的结果。
注:同样保证删除元素后仍是大根堆。
(3)大根堆的初始化
从最后一个有孩子的节点开始检查,直至检查到以1为根的树为止。
2.3 实现
类maxHeap:实现一个最大优先级队列。类的成员是heap(一个类型为T的一维数组)、arrayLength(数组heap的容量)、和heapSize(堆的元素个数)。
template<class T>
class maxHeap : public maxPriorityQueue<T>
{
public:
maxHeap(int initialCapacity = 10);
~maxHeap() { delete[] heap; }
bool empty() const { return heapSize == 0; }
int size() const
{
return heapSize;
}
const T& top()
{// return max element
if (heapSize == 0)
throw queueEmpty();
return heap[1];
}
void pop();
void push(const T&);
void initialize(T*, int);
void deactivateArray()
{
heap = NULL; arrayLength = heapSize = 0;
}
void output(ostream & out) const;
private:
int heapSize; // number of elements in queue
int arrayLength; // queue capacity + 1
T* heap; // element array
};
3 左高树
2.1 定义
高度优先左高树(HBLT):当且仅当其任何一个内部节点的左孩子s值都大于或等于右孩子的s值
重量优先左高树(WBLT):当且仅当任何一个内部节点的左孩子的w值都大于或等于右孩子的s值
性质:
(1)以x为根的子树节点数目至少为 2 s ( x ) − 1 2^{s(x)}-1 2s(x)−1
(2)以x为根的子树有m个节点, s ( x ) s(x) s(x)最多为 l o g 2 ( m + 1 ) log_2{(m+1)} log2(m+1)
(3)从x到外部节点的最右路径的长度为 s ( x ) s(x) s(x)
2.2 最大HBLT 操作
插入:通过合并操作来实现,先建立一颗只有待插入元素的HBLT,然后与原来的合并
删除:根 被删除时,分别以左右孩子为根的子树是两颗最大 HBLT,将其合并
合并:n个元素的HBLT,最右路径为
O
(
l
o
g
n
)
O(logn)
O(logn),故合并过程通过遍历其最右路径展开。合并策略最好通过递归实现。首先比较两个根元素,较大者为合并后的根。例如A、B进行合并时,A根最大,则用B和A的右子树合并得到C,比较C和L的s值,大者为合并后的左子树。
例子:
(1)
(2)
(3)
(4)
初始化:
首先创建n个仅含一个元素的最大HBLT,这n棵树组成一个FIFO队列,然后从队列中依次成对删除HBLT,然后将其合并后再插入队列末尾,知道队列只有一颗HBLT为止。
4 应用
堆排序
机器调度
霍夫曼编码