实现如下
#include <iostream>
#include <cmath>
#include "BTreeArray.h"
using namespace std;
using namespace LJLib;
// 优化后的堆调整算法,赋值的次数更少
bool toHeap(BTreeArray<int>& arr)
{
bool ret = true;
try
{
int size = arr.count();
for(int i = size / 2; i >= 1; i--) // 自底向上进行调整,i 为父节点的编号,父节点的调整顺序为 从右向左 从底向上
{
int e = arr[i]; // 父节点的值
int ci = 2 * i; // 子节点编号
while(ci <= size)
{
if((ci < size) && (arr[ci]) < arr[ci + 1]) // 当前结点的左右结点都存在,选出较大值的结点编号
{
ci = ci + 1;
}
if(e < arr[ci]) // 父节点的值小于子节点的值,需要进行调整
{
arr[ci / 2] = arr[ci]; // 将子节点的值上移
ci *= 2; // 进行下一次调整
}
else // 不需要进行调整,以该结点为根节点的树构成了一个堆
{
break;
}
}
arr[ci / 2] = e; // 将父节点的值插入到调整后的位置处
}
}
catch(const Exception&) // 这棵二叉树不为完全二叉树时,会触发异常
{
ret = false;
}
return ret;
}
// 原始的堆调整算法,赋值次数更多
bool toHeapOrg(BTreeArray<int>& arr)
{
bool ret = true;
try
{
int size = arr.count();
for(int i = size / 2; i >= 1; i--) // 自底向上进行调整,i 为父节点的编号,父节点的调整顺序为 从右向左 从底向上
{
int cur = i; // 父节点的编号
int ci = 2 * cur; // 子节点编号
while(ci <= size)
{
if((ci < size) && (arr[ci]) < arr[ci + 1]) // 当前结点的左右结点都存在,选出较大值的结点编号
{
ci = ci + 1;
}
if(arr[cur] < arr[ci]) // 父节点的值小于子节点的值,需要进行调整
{
/* 将父节点的值和子节点的值进行交换 */
int tmp = arr[cur];
arr[cur] = arr[ci];
arr[ci] = tmp;
/* 进行下一次调整 */
cur = ci;
ci = cur * 2;
}
else // 不需要进行调整,以该结点为根节点的树构成了一个堆
{
break;
}
}
}
}
catch(const Exception&) // 这棵二叉树不为完全二叉树时,会触发异常
{
ret = false;
}
return ret;
}
bool isHeap(BTreeArray<int>& bt, int i)
{
bool ret = true;
if(!bt.isNull(i))
{
int left = bt.left(i);
int right = bt.right(i);
if(!bt.isNull(left) && !bt.isNull(right)) // 堆的定义: 根结点的值比其左右两个结点的值都大,并且其左右结点构成的子树也是堆
{
ret = (bt[i] >= bt[left]) &&
(bt[i] >= bt[right]) &&
isHeap(bt, left) &&
isHeap(bt, right);
}
else if(!bt.isNull(left) && bt.isNull(right))
{
ret = (bt[i] >= bt[left]) && isHeap(bt, left);
}
else if(bt.isNull(left) && !bt.isNull(right)) // 左子树为空,右子树不为空,这棵树不是完全二叉树,不可能为堆
{
ret = false;
}
else
{
ret = true;
}
}
return ret;
}
bool isHeap(BTreeArray<int>& bt)
{
return isHeap(bt, 1);
}
int main()
{
int arr[] = {2, 5, 4, 6, 1, 3};
int len = sizeof(arr) / sizeof(*arr);
BTreeArray<int> bt(log2(len) + 1);
for(int i = 1, j = 0; j < len; i++, j++)
{
bt.set(i, arr[j]);
}
if(toHeap(bt) && isHeap(bt))
{
for(int i = 1; i <= bt.count(); i++)
{
cout << bt[i] << endl;
}
}
else
{
cout << "It is not a heap\n" << endl;
}
return 0;
}