zoukankan      html  css  js  c++  java
  • 用模板写哈夫曼编码

        今天,我们一起使用模板来写一个哈夫曼编码类,具体如例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  运行效果

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

  • 相关阅读:
    把Windows装进U盘
    Java 潜拷贝和深拷贝(浅复制和深复制)
    《远大前程——从软件新手到行业大牛》读书笔记
    解决windows8 metro应用不能联网
    [转载]schtasks命令使用实例介绍
    程序员网址
    VS2008,vs2010 快捷键大全 转载
    题解:2018级算法第一次练习赛 妙妙趣排序
    题解:2018级算法第一次上机 C1pair
    #编译原理# 词法分析(三)第二部分
  • 原文地址:https://www.cnblogs.com/new0801/p/6176945.html
Copyright © 2011-2022 走看看