Huffman Tree(c++实现)

/***************************************************************************************************
名称:Huffman Tree
基本概念:给定n权值作为n个叶子节点,构造一棵二叉树,若这棵二叉树的带权路径长度达到最小,则称这样的
		  二叉树为最优二叉树,也称为Huffman树。

性质:  1:不唯一性(具有相同带权节点);左右子树可以互换
		2:带权值的节点都是叶子节点
		3:huffman tree中只有叶子节点和度为2的节点,没有度为1的节点
		4:一棵有n个叶子节点的Huffman tree共有2n−1个节点,需要n−1次合并。

实现方法:1:假设有n个节点,他们的权值分别为W1.....Wn;将所有节点的合集看成一个森林,
		  2:每次在所有的森林中取出根节点最小的两个节点作为左右节点合并(小左大右),且合并后的根节点的权值是左
			 右节点之和
		  3:把合并好的节点再次加入森林中
		  4:一直重复2,3步就可以得到Huffman tree了

意义:压缩数据
****************************************************************************************************/
#pragma once

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

template<class T>
class HuffmanTreeNode
{
	T m_val;
	HuffmanTreeNode *m_left;
	HuffmanTreeNode *m_right;
	HuffmanTreeNode *m_parent;


	template<class T>
	friend class HuffmanTree;

public:

	HuffmanTreeNode(T val = T()) ://构造函数
		m_val(val),
		m_right(nullptr),
		m_parent(nullptr),
		m_left(nullptr)
	{
	}

};

template<class T>
class HuffmanTree
{
	HuffmanTreeNode<T> *m_root;
public:
	HuffmanTree():
		m_root(nullptr)
	{}
	
	HuffmanTree(vector<T> v)
	{
		m_root = getHuffManTree(v);
	}

private:

	HuffmanTreeNode<T>* getHuffManTree(vector<int> v)
	{
		vector<HuffmanTreeNode<T>*> phf(v.size());
		for (int i = 0; i < v.size(); i++)
		{
			phf[i] = new HuffmanTreeNode<T>(v[i]);
			AdjustUp(phf, i);
		}
		
		int index = phf.size() - 1;
		int count = 2;

		while (index)
		{
			swap(phf[0], phf[index--]);//左
			AdjustDown(phf, index);
			swap(phf[0], phf[index--]);//右
			AdjustDown(phf, index);

			T add = phf[index + 1]->m_val + phf[index + 2]->m_val;
			phf.push_back(new HuffmanTreeNode<T>(add));
			index++;
			swap(phf[index], phf[index + count]);

			phf[index]->m_left = phf[index + 1];
			phf[index]->m_right = phf[index + count];
			AdjustUp(phf, index);

			count += 2;
		}
		return phf[0];
	}

	void AdjustUp(vector<HuffmanTreeNode<T>*> &v, int child)//向上调整,获得小堆
	{
		int parent = (child - 1) / 2;
		while (child)
		{
			if (v[child]->m_val < v[parent]->m_val)
			{
				swap(v[child], v[parent]);
			}
			child = parent;
			parent = (child - 1) / 2;
		}
	}

	void AdjustDown(vector<HuffmanTreeNode<T>*> &v, int index, int parent = 0)//向下调整
	{
		int child = parent * 2 + 1;
		while (child <= index)
		{
			if (child + 1 <= index && v[child + 1]->m_val < v[child]->m_val)
			{
				child++;
			}
			if (v[child]->m_val < v[parent]->m_val)
			{
				swap(v[child], v[parent]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
			{
				break;
			}
		}
	}
};

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用C++实现初始化HuffmanTree参数的示例代码: ```cpp #include<iostream> #include<vector> #include<algorithm> using namespace std; struct TreeNode{ int val; TreeNode* left; TreeNode* right; TreeNode(int x): val(x), left(NULL), right(NULL){} }; struct cmp{ bool operator()(TreeNode* a, TreeNode* b){ return a->val > b->val; } }; TreeNode* buildHuffmanTree(vector<int>& nums){ priority_queue<TreeNode*, vector<TreeNode*>, cmp> pq; for(int i=0; i<nums.size(); i++){ pq.push(new TreeNode(nums[i])); } while(pq.size()>1){ TreeNode* left = pq.top(); pq.pop(); TreeNode* right = pq.top(); pq.pop(); TreeNode* newNode = new TreeNode(left->val + right->val); newNode->left = left; newNode->right = right; pq.push(newNode); } return pq.top(); } int main(){ vector<int> nums{1,3,4,6,7,8}; TreeNode* root = buildHuffmanTree(nums); return 0; } ``` 该示例代码中,我们首先定义了一个结构体 `TreeNode` 来表示树节点,其中包含一个权值变量 `val`、左右子节点指针 `left` 和 `right`。 然后定义了一个比较结构体 `cmp`,来作为优先队列 `priority_queue` 的比较规则,这里规定了比较方式为比较节点的权值大小。 接着,我们定义了一个函数 `buildHuffmanTree` 来构建哈夫曼树,该函数接受一个整型数组 `nums` 作为参数,首先将每个元素构造成一个单独的节点,然后将所有节点加入到优先队列中。接下来,每次从队列中取出权值最小的两个节点,将它们合并成一个新的节点,并将新节点插入到优先队列中。最终,队列中只剩下一个节点,即为哈夫曼树的根节点,返回即可。 在 `main` 函数中,我们构造了一个整型数组 `nums`,包含了哈夫曼树的所有叶子节点权值,然后调用 `buildHuffmanTree` 函数来构造哈夫曼树。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值