1 完全二叉树:若树的高度为H,那么除了H层的结点数可以小于2,其余层结点数都达到最大数。并且当H层结点数为1的时候,只能在左边。
2 堆是一个完全二叉树。分为大顶堆(max heap)和小顶堆(min heap)。
max heap:每个结点键值都不小于子结点。
min heap:每个结点键值都不大于子结点。
我们可以用数组来表示堆。
数组元素为1、2....7。很明显,第N个元素的父结点parent序号为N/2,左结点Left child序号为2N,右结点为2N+1
3 保持堆的性质(max heap)。A:用于表示堆的数组,下标从1开始,一直到n
void Heapify(int A[],int i)
{
int l=LEFT(i);
int r=RIGHT(i);
int largest;
if(l<=HEAP_SIZE(A)) largest=A[l]>A[i]?l:i;
if(r<=HEAP_SIZE(A)) largest=A[r]>A[largest]?r:largest; //从i,2*i,2*i+1中找出最大的一个
if(largest!=i) //i不是最大的
{
swap(A[i],A[largest]);
Heapify(A,largest); //交换后,子树有可能违反最大堆性质
}
}
目的是保持第i个元素的堆性质。具体做法是将第i个元素和他的左右子结点进行比较,将最大的放到位置i。这个时候被转移的子结点可能违反堆性质,所以堆子结点继续保持堆性质。
4 建堆。注意建堆并不是依次插入元素,并保持堆的性质,而是建立一个完全二叉树后,
找到最后一个非叶子结点(总数为N,第N个结点的父结点N/2),保持堆的性质。并依次往上调整子树(依次往上选择下一个非叶子结点执行保持堆的性质)。
void BuildHeap(int A[])
{
int i;
for(i = HEAP_SIZE(A)/2; i>=1; i--)
Heapify(A, i);
}
5堆排序。
先用BuildHeapo将数组A[1..n]构造成一个大顶堆。因为数组中最大元素在根A[1],则可以通过把它与A[n]交换来达到最终正确的位置。
void HeapSort(int A[])
{
BuildHeap(A);
for(i=HEAP_SIZE(A),i>1; i--)
{
swap(A[1],A[i]);
HEAP_SIZE(A)=HEAP_SIZE(A)-1;
Heapify(A,1); //交换后新的根元素可能违背了最大堆的性质
}
}
6 用途。
优先队列(c++里面的priority_queue):普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。
GETMAX:
void GetMaximum(int A[]) {
int max = A[1];
A[1] = A[n];
HEAP_SIZE--;
Heapify(A, 1);
return max;
}
7 c++使用例子。
#include<queue>
int main(int argc, const char * argv[]) {
std::priority_queue<int> que;
que.push(2);
que.push(4);
que.push(3);
que.push(1);
que.push(5);
int max = que.top();//取最大值
printf("max---------------%d\n",max);//打印5
que.pop();//移除最大值
max = que.top();
printf("max---------------%d\n",max);//打印4
return 0;
}