引入:
一些按照重要性或优先级来组织的对象称为优先队列。
在普通队列数据结构中查找具有最高优先级元素的时间代价为O(n),因而普通队列不能有效地实现优先队列。
在有序表或无序表中插入和删除的时间代价都是O(n)。
可以考虑使用把记录按优先级组织的BST,其平均情况下插入和删除操作的总时间代价为O(nlogn),平均时间代价为O(logn)。但是BST可能会变得不平衡,这将导致BST性能变得很差。(若是完全二叉树就很好)
堆可以解决上述问题。
关于堆:
1. 它是一棵完全二叉树,常用数组来实现。
2. 对中存储的数据是局部有序的,包括最大堆和最小堆(无论最小堆还是最大堆,任何一个结点与其兄弟结点之间都没有必然联系)
堆元素父节点与子节点映射于数组的关系:
1. 父节点下标为i,则左子节点为2i+1,右子节点为2i+2。
2. 子节点小标为i,则父节点为i-1/2。
2. 叶子节点下标大于等于数组长度/2。
性能分析:
1. 建堆 O(n),远比建立BST的平均时间复杂度O(nlogn)和最差时间复杂度O(n*n)要好得多。
2. 删除对优先级最高的元素O(logn)
C++实现代码:
#include <iostream>
#include <string>
using namespace std;
// Heap class
template <class E> class heap{
private:
E* Heap; // Pointer to the heap array
int maxsize; // Maximum size of the heap
int n; // Number of elements now in the heap
bool Prior(E x, E y){
return x > y;
}
void swap(E* source, int x, int y){
E temp = source[x];
source[x] = source[y];
source[y] = temp;
}
void Assert(bool test, string error){
if (!test){
cout << error << endl;
exit(1);
}
}
// Helper function to put element in its correct place
void siftdown(int pos){
while (!isLeaf(pos)){ // Stop if pos is a leaf
int j = leftchild(pos);
int rc = rightchild(pos);
if ((rc < n) && Prior(Heap[rc], Heap[j]))
j = rc; // Set j to greater child's value
if (Prior(Heap[pos], Heap[j]))
return; //Done
swap(Heap, pos, j);
pos = j; //Move down
}
}
public:
heap(E* h, int num, int max) // Constructor
{
Heap = h;
n = num;
maxsize = max;
buildHeap();
}
int size() const{
return n;
}
bool isLeaf(int pos) const{
return (pos >= n / 2) && (pos < n);
}
int leftchild(int pos) const{
return pos * 2 + 1;
}
int rightchild(int pos) const{
return pos * 2 + 2;
}
int parent(int pos) const{
return (pos - 1) / 2;
}
void buildHeap(){ //从暂时的堆的最底层父节点开始往上层调整
for (int i = n / 2 - 1; i >= 0; i--)
siftdown(i);
}
// Insert "it" into the heap
void insert(const E& it){
Assert(n < maxsize, "Heap is full");
int cur = n++;
Heap[curr] = it; // Start at end of heap
// Now sift up until curr's parnt>curr
while ((curr != 0) && (Prior(Heap[curr], Heap[parent(curr)]))){ //只跟踪插入元素进行追踪调整
swap(Heap, curr, parent(curr));
curr = parent(curr);
}
}
// Remove first value
E removefirst(){
Assert(n > 0, "Heap is empty");
swap(Heap, 0, --n);
if (n != 0)
siftdown(0); // Siftdown new root val
return Heap[n]; // Return deleted value
}
// Remove and return element at specified position
E remove(int pos){
Assert((pos >= 0) && (pos < n), "Bad position");
if (pos == (n - 1))
n--; // Last element, no work to do
else{
swap(Heap, pos, --n); //Swap with last value
while ((pos != 0) && (Prior(Heap[pos], Heap[parent(pos)]))){ // Push up large key
swap(Heap, pos, parent(pos));
pos = parent(pos);
}
if (n != 0)
siftdown(pos); // Push down small key
}
return Heap[n];
}
};
int main(){
int source[7] = { 7, 4, 6, 1, 2, 3, 5 };
heap<int> test(source, 7, 100);
cout << test.removefirst() << endl;
cout << test.removefirst() << endl;
cout << test.removefirst() << endl;
cout << test.removefirst() << endl;
return 0;
}
感觉别人写得好多了=_=,附上网址:http://blog.csdn.net/morewindows/article/details/6709644/