Please indicate the source if you want to reprint: http://blog.csdn.net/gaoxiangnumber1.
优先队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有 1) 查找;2) 插入一个新元素; 3) 删除。在最小优先队列( min priority queue)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素;对于最大优先队列(max priority queue),查找操作用来搜索优先权最大的元素,删除操作用来删除该元素。优先权队列中的元素可以有相同的优先权,查找与删除操作可根据任意优先权进行。
[最大树(最小树) ] 是每个节点的值都大于(小于)或等于其子节点(如果有的话)值的树。最大树或最小树节点的子节点个数可以大于 2。
[最大堆(最小堆) ] 是最大(最小)的完全二叉树。
完全二叉树的相关性质(设该完全二叉树共有n个节点):
设某父节点的编号为i(从1开始), 1≤i≤n。则:
1) 当i =1时,该元素为二叉树的根。若 i > 1,则该元素父节点的编号为 i /2。
2) 当2i >n时,该元素无左孩子。否则,其左孩子的编号为 2i。
3) 若2i +1>n,该元素无右孩子。否则,其右孩子编号为 2i +1。
该树的高度为深度为log2(n+1)
插入:
图9-3a 给出了一个具有 5个元素的最大堆。由于堆是完全二叉树,当加入一个元素形成6元素堆时,其结构必如 9-3b 所示。
如果插入元素的值为 1,则插入后该元素成为 2的左孩子。
若新元素的值为 5,则该元素不能成为 2的左孩子,应把2下移为左孩子(如图 9 - 3c所示),同时还得决定在最大堆中 5是否占据 2原来的位置。由于父元素 20大于等于新插入的元素 5,因此可以在原 2所在位置插入新的元素。
假设新元素的值为21而不是5,这时,同图 9-3c 一样,把 2下移为左孩子,由于 21比父元素值大,所以 21不能插入原来 2所在位置,因此把 20移到它的右孩子所在位置, 21插入堆的根节点(如图 9 - 3 d所示)。
插入策略从叶到根只有单一路径,每一层的工作需耗时O( 1 ),因此实现此策略的时间复杂性为O(height) = O (log2(n+1)), n为最大堆中的元素个数。
删除
从最大堆中删除一个元素时,该元素从堆的根部移出。
对图 9-3d 的最大堆进行删除操作即是移去元素 21,因此最大堆只剩下五个元素。此时,图 9-3d 中的二叉树需要重新构造,以便仍然为完全二叉树。为此可以移动位置 6中的元素,即2。这样就得到了正确的结构(如图9-4 a所示)。如果 2直接插入根节点,得到的二叉树不是最大树,根节点的元素应为 2、根的左孩子、根的右孩子三者中的最大值。这个值是 20,它被移到根节点,因此在位置 3形成一个空位,由于这个位置没有孩子节点, 2可以插入,最后形成的最大堆如图9-3a 所示。
现在假设要删除20,在删除之后,堆的二叉树结构如图 9-4b 所示,为得到这个结构,10从位置5移出,如果将 10放在根节点,结果并不是最大堆。把根节点的两个孩子( 15和2)中较大的一个移到根节点。假设将10插入位置2,结果仍不是最大堆。因此将14上移,10插入到位置4,最后结果如图9-4c 所示。
删除策略产生了一条从堆的根节点到叶节点的单一路径,每层工作需耗时O(1),时间复杂性为 O(height) = O (log2(n+1)), n为最大堆中的元素个数
Review:
MaxHeap.h
Test.cc
MaxHeap.h
#ifndef MAXHEAP_H_INCLUDED
#define MAXHEAP_H_INCLUDED
using std::cout;
using std::cin;
using std::endl;
template<typename T>
class MaxHeap
{
public:
MaxHeap(): current_size_(0), max_size_(0), heap_(0) {} // default constructor
~MaxHeap(); // destructor
void CreateMaxHeap(); // create a max heap
void Insert(const T &element); // insert element into max heap
void Delete(); // delete the max element from heap
void Output(); // print max heap's contents
private:
// current_size_ is the amount of elements now
// max_size_ is the max amount of all elements the heap can hold
int current_size_, max_size_;
T *heap_;
};
template<typename T>
MaxHeap<T>::~MaxHeap()
{
delete heap_;
heap_ = 0; // avoid dangling pointer
current_size_ = 0; // very important: avoid access invalid memory
max_size_ = 0;
}
template<typename T>
void MaxHeap<T>::CreateMaxHeap()
{
cout << "Please input heap's max size and current size:\n";
int max_size, current_size;
cin >> max_size >> current_size;
max_size_ = max_size;
heap_ = new T [max_size_ + 1]; // element index begin from 1, so we need one more element space
cout << "Please input " << current_size << " elements:\n";
for(int index = 1; index <= current_size; index++)
{
T element;
cin >> element;
Insert(element);
}
Output();
}
template<typename T>
void MaxHeap<T>::Insert(const T &element)
{
if(current_size_ < max_size_) // if there is free memory in heap
{
int position = ++current_size_; // we should insert element into heap[position]
// if element is bigger than it's parent node's value
// position != 1: indicate the element has parent node
while(position != 1 && element > heap_[position/2])
{
heap_[position] = heap_[position/2]; // move it's parent node down
position = position / 2; // move element to parent node's position
}
heap_[position] = element; // insert element
}
}
template<typename T>
void MaxHeap<T>::Delete()
{
if(current_size_ != 0) // if heap is not empty
{
T last_element = heap_[current_size_--]; // get the last element from heap and decrement size
// we will insert last_element into heap[empty_position]
// heap[max_child_position] is the bigger child node of parent node heap[empty_position]
int empty_position = 1, max_child_position = 2;
while(max_child_position <= current_size_)
{
// check whether heap_[max_child_position] is the bigger child node
if(max_child_position < current_size_ &&
heap_[max_child_position] < heap_[max_child_position + 1])
{
max_child_position++;
}
// if last_element is bigger than the bigger child node, then we find the right position
if(last_element > heap_[max_child_position])
{
break;
}
// else exchange child node and parent node
heap_[empty_position] = heap_[max_child_position];
empty_position = max_child_position;
max_child_position = max_child_position * 2;
}
heap_[empty_position] = last_element; // insert last_element into heap
}
}
template<typename T>
void MaxHeap<T>::Output()
{
if(current_size_ == 0)
{
cout << "Error: empty max heap.\n";
return;
}
cout << "The heap's contents are :\n";
for(int index = 1; index <= current_size_; index++)
{
cout << heap_[index] << " ";
}
cout << endl;
}
void AllOperation()
{
MaxHeap<int> object;
cout << "Please some numbers to execute the corresponding operation:\n";
cout << "0: exit.\n";
cout << "1: create a MaxHeap.\n";
cout << "2: insert element into MaxHeap.\n";
cout << "3: delete max element from MaxHeap.\n";
cout << "4: print MaxHeap's contents.\n";
cout << "5: destroy MaxHeap.\n";
int operate;
while(cin >> operate)
{
switch(operate)
{
case 0:
goto END;
case 1:
object.CreateMaxHeap();
break;
case 2:
cout << "Please input your element:\n";
int element;
cin >> element;
object.Insert(element);
object.Output();
break;
case 3:
object.Delete();
object.Output();
break;
case 4:
object.Output();
break;
case 5:
object.~MaxHeap();
cout << "You have destroy the MaxHeap. Please establish MaxHeap before executing operations.\n";
break;
default:
cout << "Input Error! Please input again!\n";
break;
}
}
END:
;
}
#endif // MAXHEAP_H_INCLUDED
Test.cc
#include<iostream>
#include"MaxHeap.h"
using namespace std;
int main()
{
AllOperation();
return 0;
}
/*
1
6 2
10 14***14 10
2 2***14 10 2
2 20***20 14 2 10
2 15***20 15 2 10 14
2 21***21 15 20 10 14 2
3***20 15 2 10 14
3***15 14 2 10
3***14 10 2
4***14 10 2
5
0
*/
Please indicate the source if you want to reprint: http://blog.csdn.net/gaoxiangnumber1.