哈夫曼树
最优二叉树 带权路径长度最短的树
堆
最大(小)堆
特性:
1.是完全二叉树
2.堆中任意节点的值都必须大于或等于其中最大的子节点的值
实现
框架
template <typename T>
class CMy_heap
{
private:
T * pBuff;//指针域
size_t len;//数据域
size_t MaxSize;
public :
CMy_heap();
~CMy_heap();
public:
void clear(); //清除
//添加清除初始化
void AppendNode(T const & srcData);
void DeletNode();
void initHeap(T arr[], size_t srcLen);
//演示
T *Output(){ return pBuff; }
};
template <typename T>
class CMy_heap
{
private:
T * pBuff;//指针域
size_t len;//数据域
size_t MaxSize;
public :
CMy_heap();
~CMy_heap();
public:
void clear(); //清除
//添加清除初始化
void AppendNode(T const & srcData);
void DeletNode();
void initHeap(T arr[], size_t srcLen);
//演示
T *Output(){ return pBuff; }
};
添加:自下而上
template <typename T>
void CMy_heap<T>::AppendNode(T const & srcData)
{
//扩容
if (len >= MaxSize)
{
MaxSize += ((MaxSize >> 1) > 1 ? (MaxSize >> 1) : 1);
T *pTemp = new T[pTemp];
for (size_t i = 0; i < len; i++)
{
pTemp[i] = pBuff[i];
}
if (pBuff)
delete[] pBuff;
pBuff = pTemp;
}
//扩容完成
pBuff[len++] = srcData;
//调整位置 - 一次插入的过程
int tempIndex = len - 1; //保存下表
T tempData = pBuff[tempIndex]; //保存值
while (tempIndex)
{
//获取父节点的下表
int parerntIndex = (tempIndex - 1) >> 1;
if (pBuff[parerntIndex] < tempData) //父节点小,数据后移
pBuff[tempIndex] = pBuff[parerntIndex];
else
break;
//循环步长改变 下标跟上
tempIndex = parerntIndex;
}
//结果 : 到根节点 | 比不过了
pBuff[tempIndex] = tempData;
}
删除:
删除规则:1.每次只删除根节点 2.把最后一个节点覆盖到根节点 元素量减一 3.调整结构,使其再次符合堆特性
template <typename T>
void CMy_heap<T>::DeletNode()
{
//1.空堆
if (len == 0)
return;
//2.元素大于1
if (len > 1)
//覆盖
pBuff[0] = pBuff[len - 1];
//不管如何
len--;
//调整结构
int index = 0;
T tempData = pBuff[index];
while (true)//不知道调整多少次
{
//获取左右子树下标
size_t left = 2 * index + 1;
size_t right = 2 * index + 2;
//如果左子树下标越界,说明没有子树
if (left > (len - 1)) //结束循环
break;
//设置开关 用来判断谁大和谁交换
bool isLeft = true;
//判断存在右子树且与左子树比
if (right < len)
{
if (pBuff[left] < pBuff[right])
{
isLeft = false;
}
}
//跟较大者比较
if (isLeft)
{
//跟左边比 判断是否比左子树小
if (tempData<pBuff[left])
{
pBuff[index] = pBuff[left]; //左子树上位
index = left;
}
else break;
}
else
{
//右子树比
if (tempData < pBuff[right])
{
pBuff[index] = pBuff[right]
index = right;
}
else break;
}
}
//到循环结束
//1.到叶节点
//2.找到了
pBuff[index] = tempData;
}
初始化
初始化规则:1.一次在堆中加入所有元素 2.从最后一个有子树的节点开始调整直到根节点的位置
//初始化
template <typename T>
void CMy_heap<T>::initHeap(T arr[], size_t srcLen)
{
//全部插入 先清除
clear();
//插入的内容为空
if (srcLen == 0)
return;
//数据入堆
len = MaxSize = srcLen;
pBuff = new T[MaxSize];
for (size_t i = 0; i < len; i++)
{
pBuff[i] = arr[i];
}
//调整位置
for (int i = (int)((len - 1) - 1) >> 1; i >= 0; --i)
{
//保存
int index = i;
T tempData = pBuff[index];
//调整 和删除一样
while (true)//不知道调整多少次
{
//获取左右子树下标
size_t left = 2 * index + 1;
size_t right = 2 * index + 2;
//如果左子树下标越界,说明没有子树
if (left > (len - 1)) //结束循环
break;
//设置开关 用来判断谁大和谁交换
bool isLeft = true;
//判断存在右子树且与左子树比
if (right < len)
{
if (pBuff[left] < pBuff[right])
{
isLeft = false;
}
}
//跟较大者比较
if (isLeft)
{
//跟左边比 判断是否比左子树小
if (tempData<pBuff[left])
{
pBuff[index] = pBuff[left]; //左子树上位
index = left;
}
else break;
}
else
{
//右子树比
if (tempData < pBuff[right])
{
pBuff[index] = pBuff[right];
index = right;
}
else break;
}
}
//到循环结束
//1.到叶节点
//2.找到了
pBuff[index] = tempData;
}
}