用模板写哈夫曼编码

    今天,我们一起使用模板来写一个哈夫曼编码类,具体如例1所示。

例1 对下面字符进行编码,使其总体长度最短。

字母={A,B,C,D,E},频率={15,7,6,6,5},字母和频率一一对应。

分析:解决这道题目的方法是使用哈夫曼编码,哈夫曼编码利用哈夫曼树构造前缀编码,使文本总体长度最短。

具体实现如下:

Huffman.hpp内容:

#ifndef _HUFFMAN_H_
#define _HUFFMAN_H_
#include <vector>
#include <string>
#include <iostream>
using namespace std;
template<typename T>
struct Node
{
	T m_Data;
	string m_strName;
};
template<typename T>
struct TreeNode
{
	Node<T> m_Info;
	TreeNode * m_pParent;
	TreeNode * m_pLeft;
	TreeNode * m_pRight;
};

template<typename T>
class CHuffmanTree
{
public:
	CHuffmanTree();
	~CHuffmanTree();
	//初始化哈夫曼树
	bool InitForest(vector<Node<T> > & v);
	//构建哈夫曼树
	bool BuildHuffman();
	//销毁
	void Clear();
	//打印huffman编码
	void PrintEncode();
private:
	//销毁树
	void ClearTree(TreeNode<T> * pRoot);
	//中序遍历
	void InOrderTree(TreeNode<T> * pRoot);
private:	
	vector<TreeNode<T> *> m_vForest;
	TreeNode<T> * m_pRoot;
};

template<typename T>
CHuffmanTree<T>::CHuffmanTree()
{
	m_pRoot = NULL;
}
template<typename T>
CHuffmanTree<T>::~CHuffmanTree()
{
	vector<TreeNode<T> *>::iterator it;
	for (it = m_vForest.begin(); it != m_vForest.end(); it++)
	{
		if (*it)
			ClearTree(*it);
	}
	m_vForest.clear();
	if (m_pRoot)
	{
		ClearTree(m_pRoot);
		m_pRoot = NULL;
	}
}
template<typename T>
bool CHuffmanTree<T>::InitForest(vector<Node<T> > & vWeights)
{
	TreeNode<T> * pNewNode = NULL;
	vector<Node<T> >::iterator it;
	for (it = vWeights.begin(); it != vWeights.end(); it++)
	{
		pNewNode = new TreeNode<T>;
		if (!pNewNode)
		{
			return false;
		}
		pNewNode->m_Info.m_Data = it->m_Data;
		pNewNode->m_Info.m_strName = it->m_strName;
		pNewNode->m_pParent = NULL;
		pNewNode->m_pLeft = NULL;
		pNewNode->m_pRight = NULL;
		m_vForest.push_back(pNewNode);
	}
	return true;
}
//构建哈夫曼树
template<typename T>
bool CHuffmanTree<T>::BuildHuffman()
{
	TreeNode<T> * pMin = NULL;
	TreeNode<T> * pMin2 = NULL;
	TreeNode<T> * pNewNode = NULL;
	vector<TreeNode<T> *>::iterator it;
	vector<TreeNode<T> *>::iterator itMin;
	vector<TreeNode<T> *>::iterator itMin2;
	while (m_vForest.size() > 1)
	{
		pNewNode = new TreeNode<T>;
		if (!pNewNode)
			return false;
		pMin = m_vForest[0];
		itMin = m_vForest.begin();
		for (it = m_vForest.begin(); it != m_vForest.end(); it++)
		{
			if ((*it)->m_Info.m_Data < pMin->m_Info.m_Data)
			{
				pMin = *it;
				itMin = it;
			}
		}
		m_vForest.erase(itMin);
		pMin2 = m_vForest[0];
		itMin2 = m_vForest.begin();
		for (it = m_vForest.begin(); it != m_vForest.end(); it++)
		{
			if (((*it)->m_Info.m_Data < pMin2->m_Info.m_Data) && (*it != pMin))
			{
				pMin2 = *it;
				itMin2 = it;
			}
		}
		m_vForest.erase(itMin2);
		pNewNode->m_pLeft = pMin;
		pNewNode->m_pRight = pMin2;
		pNewNode->m_pParent = NULL;
		pNewNode->m_Info.m_Data = (pMin)->m_Info.m_Data + (pMin2)->m_Info.m_Data;
		pNewNode->m_Info.m_strName = (pMin)->m_Info.m_strName + (pMin2)->m_Info.m_strName;		
		m_vForest.push_back(pNewNode);
	}
	m_pRoot = m_vForest[0];
	m_vForest.clear();
	return true;
}
template<typename T>
void CHuffmanTree<T>::Clear()
{
	vector<TreeNode<T> *>::iterator it;
	for (it = m_vForest.begin(); it != m_vForest.end(); it++)
	{
		if (*it)
			ClearTree(*it);
	}
	m_vForest.clear();
	if (m_pRoot)
	{
		ClearTree(m_pRoot);
		m_pRoot = NULL;
	}
}

template<typename T>
void CHuffmanTree<T>::InOrderTree(TreeNode<T> * pRoot)
{
	vector<int>::iterator it;
	static vector<int> vPath;
	if (!pRoot)
		return;
	if (pRoot->m_pLeft)
	{
		vPath.push_back(0);
		InOrderTree(pRoot->m_pLeft);
	}
	if ((pRoot->m_pLeft == NULL) && (pRoot->m_pRight == NULL))
	{
		cout << pRoot->m_Info.m_strName << "编码:";
		for (it = vPath.begin(); it != vPath.end(); it++)
		{
			cout << *it;
		}
		cout << endl;
	}
	if (pRoot->m_pRight)
	{
		vPath.push_back(1);
		InOrderTree(pRoot->m_pRight);
	}
	if (!vPath.empty())
		vPath.pop_back();
	return;
}

template<typename T>
void CHuffmanTree<T>::PrintEncode()
{
	if (m_pRoot)
		InOrderTree(m_pRoot);
	else
		cout << "Huffman Tree is empty." << endl;
}
template<typename T>
void CHuffmanTree<T>::ClearTree(TreeNode<T> * pRoot)
{
	if (!pRoot)
		return;
	if (pRoot->m_pLeft)
		ClearTree(pRoot->m_pLeft);
	if (pRoot->m_pRight)
		ClearTree(pRoot->m_pRight);
	delete pRoot;
	return;
}
#endif
main.cpp内容:

#include "Huffman.hpp"
void main()
{
	CHuffmanTree<int> HuffmanTree;
	vector<Node<int>> v;
	Node<int> tmp;
	tmp.m_strName = "A";
	tmp.m_Data = 15;
	v.push_back(tmp);
	tmp.m_strName = "B";
	tmp.m_Data = 7;
	v.push_back(tmp);
	tmp.m_strName = "C";
	tmp.m_Data = 6;
	v.push_back(tmp);
	tmp.m_strName = "D";
	tmp.m_Data = 6;
	v.push_back(tmp);
	tmp.m_strName = "E";
	tmp.m_Data = 5;
	v.push_back(tmp);
	HuffmanTree.InitForest(v);
	HuffmanTree.BuildHuffman();
	HuffmanTree.PrintEncode();
	HuffmanTree.Clear();
	system("pause");
}
运行效果如图1所示:

图1  运行效果

    今天,我们共同使用模板完成了哈夫曼编码,希望大家回去多实践,熟练模板的使用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尹成

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值