第八节课:9.5:哈夫曼和堆

第八节课:9.5:哈夫曼和堆

一、哈夫曼

1.概念:

(1)哈夫曼树的定义:

最优二叉树,是一类带权路径长度最短树

(2)节点的带权路径的定义:(先理解路径和路径长度两个概念)

带权路径是指该节点的权重值和根节点到该节点的路径长度的乘积

例:如下图所示:节点d的带权路径是1*2 = 2

在这里插入图片描述

(3)路径的定义:

在一颗树中,从一个节点到另外一个节点,之间所经过的所有的节点称为路径;

如下图所示:a到d的路径为:a,b,d

在这里插入图片描述

(4)路径长度的定义:

在一颗树中,从一个节点到另外一个节点,之间所经过的所有的边数之和称为路径长度;

如下图所示:a到d的路径长度为2

在这里插入图片描述

(5)树的带权路径

所谓树的带权路径长度,就是树中所有的叶节点的权值乘上其到根节点的路径长度(若根节点为0层,叶节点到根节点的路径长度为叶节点的层数)。树的路径长度是从树根到每一个节点的路径长度之和

例:如下图树的带权路径WPL为:1*2 + 5*2 + 2*1 = 14

在这里插入图片描述

2.哈夫曼树的建立过程:

以后再来补上:

参考博文:哈夫曼树构建步骤和代码

3.哈夫曼树的code实现:

以后再补上:

参考博文:哈夫曼树构建步骤和代码

二、堆

1.概念:

堆本质就是完全二叉树,但是最大(小)堆的每一个节点必须要大于等于(小于等于)其任意子节点

2.特性:

(1)满足完全二叉树的特性;

(2)最大(小)堆的每一个节点必须要大于等于(小于等于)其任意子节点

3.code:

#pragma once
#include <stdio.h>

template <class T>
class CMy_heap
{
	T* pBuff;
	int len;
	int size;
public:
	CMy_heap();
	~CMy_heap();
	void clear();

public:
	bool find(T const& find_data) const;
	bool del();//删除根节点最大值(小)才有意义
	void append(T const& append_data);
	T const & GetRoot() const { return pBuff[0]; }
	bool print() const;
	bool init(T  arr[], int srcLen);
private:
	int _find(T const& find_data) const;
	void amplify_scale();
};

template <class T>
bool CMy_heap<T>::init(T  arr[], int srclen)
{
	clear();
	if (srclen == 0) return false;

	//扩容
	size = len = srclen;
	pBuff = new T[size];
	for (size_t i = 0; i < srclen; i++)
	{
		pBuff[i] = arr[i];
	}

	//pBuff赋值完成,但是还没有排序
	for (int i = ((len - 1) >> 1); i >= 0; i--)//找到最后一个有子节点的节点
	{
		int current_index = i;//待插入排序的节点的坐标
		int left_child_index = 2 * current_index + 1;
		int right_child_index = 2 * current_index + 2;
		int tempval = pBuff[current_index];//待插入排序的节点

		while (right_child_index <= len - 1)//注意:这里是len - 1待删除的节点不要比较!!!!易错
		{
			//3.3.1判断是和左节点比较还是和右节点比较:做一个开关
			int isleft = true;
			if (pBuff[left_child_index] < pBuff[right_child_index])  isleft = false;

			if (isleft)//和左节点比较:包括了只有左节点,左节点比右节点大的情况
			{
				if (tempval < pBuff[left_child_index])
				{
					pBuff[current_index] = pBuff[left_child_index];
				}
				current_index = left_child_index;
			}
			else//和右节点比较
			{
				if (tempval < pBuff[right_child_index])
				{
					pBuff[current_index] = pBuff[right_child_index];
				}
				current_index = right_child_index;
			}
			left_child_index = 2 * current_index + 1;
			right_child_index = 2 * current_index + 2;
		}

		//3.3排序完成
		pBuff[current_index] = tempval;
	}
}

template <class T>
bool CMy_heap<T>::print() const
{
	if (pBuff == nullptr) return false;
	for (size_t i = 0; i < (size_t)len; i++)
	{
		printf("%d ",pBuff[i]);
	}
	return true;
}

template <class T>
bool CMy_heap<T>::del()
{
	//1.空堆:
	if (pBuff == nullptr) return false;

	//3.2准备index坐标,左子树节点坐标和右子树节点坐标用于判断
	int current_index = 0;//待插入排序的节点的坐标
	int left_child_index = 2 * current_index + 1;
	int right_child_index = 2 * current_index + 2;

	//2.只有根节点
	if (left_child_index > len);//直接len--

	else//3.包含后面所有情况;
	{
		//3.1尾结点覆盖根节点
		pBuff[0] = pBuff[len - 1];
		int tempval = pBuff[current_index];//待插入排序的节点

		//3.2准备index坐标,左子树节点坐标和右子树节点坐标用于判断

		//3.3循环排序:
		while (right_child_index < len - 1)//注意:这里是len - 1待删除的节点不要比较!!!!易错
		{
			//3.3.1判断是和左节点比较还是和右节点比较:做一个开关
			int isleft = true;
			if (pBuff[left_child_index] < pBuff[right_child_index])  isleft = false;

			if (isleft)//和左节点比较:包括了只有左节点,左节点比右节点大的情况
			{
				if (tempval < pBuff[left_child_index])
				{
					pBuff[current_index] = pBuff[left_child_index];
				}
				current_index = left_child_index;
			}
			else//和右节点比较
			{
				if (tempval < pBuff[right_child_index])
				{
					pBuff[current_index] = pBuff[right_child_index];
				}
				current_index = right_child_index;
			}
			left_child_index = 2 * current_index + 1;
			right_child_index = 2 * current_index + 2;
		}

		//3.3排序完成
		pBuff[current_index] = tempval;
	}
	len--;
	return true;
}

template <class T>
void CMy_heap<T>::amplify_scale()
{
	if (len >= size)
	{
		size += ((size >> 1) < 1 ? 1 : (size >> 1));
		T* tempbuff = new T[size];
		for (size_t i = 0; i < (size_t)len; i++)//深拷贝
		{
			tempbuff[i] = pBuff[i];
		}
		//内存重分配
		delete[]pBuff;
		pBuff = tempbuff;
		tempbuff = nullptr;
	}
}

template <class T>
void CMy_heap<T>::append(T const& append_data)
{
	//1.没有根节点:
	if (pBuff == nullptr)
	{
		//扩容:
		if (len >= size)
		{
			size += ((size >> 1) < 1 ? 1 : (size >> 1));
			pBuff = new T[size];
		}
		pBuff[len++] = append_data;
	}

	//2.有根节点,进行插入操作
	else
	{

		//2.0扩容操作:
		amplify_scale();
		//2.1插入节点:
		pBuff[len++] = append_data;
		//2.2进行插入排序:

		//2.2.1准备当前节点的坐标和父亲节点的坐标
		int current_index = len - 1;
		int parent_index = ((current_index - 1) >> 1);
		int tempval = pBuff[current_index];//保存待插入的值

		//2.2.2插入操作-后移
		while (parent_index >= 0 && tempval > pBuff[parent_index])//一直比较到根节点
		{
			pBuff[current_index] = pBuff[parent_index];
			current_index = parent_index;
			parent_index = ((current_index - 1) >> 1);
		}

		//2.2.3插入操作-最大值归位
		pBuff[current_index] = tempval;
	}
}

template <class T>
int CMy_heap<T>::_find(T const& find_data) const
{
	for (size_t i = 0; i < (size_t)len; i++)
	{
		if (pBuff[i] == find_data)
			return i;
	}
	else
		return -1;
}

template <class T>
bool CMy_heap<T>::find(T const& find_data) const
{
	int index = _find(find_data);
	if (index != -1)
		return true;
	return  false;
}

template <class T>
void CMy_heap<T>::clear()
{
	if (pBuff)
	{
		delete[]pBuff;
		pBuff = nullptr;
		len = size = 0;
	}
}

template <class T>
CMy_heap<T>::CMy_heap()
{
	pBuff = nullptr;
	len = size = 0;
}

template <class T>
CMy_heap<T>::~CMy_heap()
{
	clear();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值