一、概念
数据以数组的形式存储。
如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2*i+1 且 Ki<= K2*i+2(Ki >= K2*i+1 且 Ki >= K2*i+2) i = 0,1,2…,则称这个堆为最小堆(或最大堆)。
二、形式
最小堆:任一结点的关键码均小于等于它的左右孩子的关键码,位于堆顶结点的关键码最小。
最大堆:任一结点的关键码均大于等于它的左右孩子的关键码,位于堆顶结点的关键码最大。
三、特性
在堆中,所有的记录具有称之为堆序的关系。
1、具有最小堆序的结点(除没有孩子的结点)之间存在小于或等于关系,从根节点到每个结点的路径上数组元素组成的序列都是递增的。
2、具有最大堆序的结点(除没有孩子的结点)之间存在大于或等于关系,从根节点到每个结点的路径上数组元素组成的序列都是递减的。
四、性质
堆存储在下标为0开始计数的数组中,因此在堆中给定下标为i的结点时:
1、如果i=0,结点i是根节点,没有双亲节点;否则结点i的双亲结点为结点(i-1)/2
2、如果2*i+1>n-1,则结点i无左孩子,否则结点i的左孩子为结点2*i+1
3、如果2*i+2>n-1,则结点i无右孩子,否则结点i的右孩子为结点2*i+2
五、堆的创建
1、将所有的数据存储在vector中
2、放完元素之后,则可能导致结构不符合,则需要进行调整(此处先默认为小堆)
找到倒数第一个非叶子结点,标记其为双亲结点,默认其左孩子结点最大,如若另一个结点存在,则进行比较,从而找到最小的孩子,标记此孩子结点,让其与双亲进行比较,若其比双亲小,则进行交换,一直调整,直到其调整的元素超过其size的大小,则为终止。——>此处所用为向下调整的思路
代码实现如下所示:
void AdjustDown(size_t parent)
{
//标记左孩子,且默认左孩子为最小的孩子
size_t child = parent * 2 + 1;
size_t size = _array.size();
//找最小的孩子
while (child < size)
{
//Compare com;
if (child + 1 <size && Compare()(_array[child + 1], _array[child]))//在此处,因为默认左孩子最小,因此要返回true,只能是这样
{
child = child + 1;//右孩子为最小
}
//比较最小的孩子与双亲的大小----值域
if (Compare()(_array[child], _array[parent]))
{
swap(_array[parent], _array[child]);
//交换之后,可能导致孩子结点不为堆
parent = child;
child = parent * 2 + 1;