霍夫曼算法的实现。
#ifndef __CHUFFMANCODE__H
#define __CHUFFMANCODE__H
#include <iostream>
#include <string>
#include <functional>
#include <queue>
//哈夫曼编码
struct TreeNode
{
std::string strName;
int nFrequence; // 出现的频率
int nWight; // 权值
TreeNode* pLeftTree; // 左子树
TreeNode* pRightTree; // 右子树
TreeNode()
{
strName = "";
nFrequence = 0;
nWight = 0;
pLeftTree = nullptr;
pRightTree = nullptr;
}
};
class cmp
{
public:
cmp(TreeNode* pNode) : m_pNode(pNode)
{}
bool operator< (const cmp& rhs) const
{
return m_pNode->nWight > rhs.m_pNode->nWight;
}
public:
TreeNode* m_pNode;
};
class CHuffmanCode
{
public:
CHuffmanCode();
~CHuffmanCode();
public:
void InsertNode(std::string strName, int nFrequence);
void Generater(); // 生成哈夫曼树
void PrintHuffmanCode(); // 打印编码
private:
void DeleteTree(TreeNode*& pNode);
void PrintHuffmanCode(TreeNode* pNode, std::queue<std::string>& strQueue);
private:
TreeNode* m_pRoot; // 最终生成的哈夫曼树
std::priority_queue<cmp> m_queue; // 最小堆
};
#endif
#include "HuffmanCode.h"
CHuffmanCode::CHuffmanCode()
{
}
CHuffmanCode::~CHuffmanCode()
{
DeleteTree(m_pRoot);
}
void CHuffmanCode::InsertNode(std::string strName, int nFrequence) // 为简单起见,由调用者保证不重复
{
TreeNode* pNode = new TreeNode;
pNode->strName = strName;
pNode->nFrequence = nFrequence;
pNode->nWight = nFrequence;
m_queue.push(pNode);
}
void CHuffmanCode::Generater()
{
TreeNode* pNode = nullptr;
while (!m_queue.empty())
{
pNode = m_queue.top().m_pNode;
m_queue.pop();
if (m_queue.empty())
break;
TreeNode* pSecond = m_queue.top().m_pNode;
m_queue.pop();
TreeNode* pNew = new TreeNode; // 生成新的节点
pNew->pLeftTree = pNode;
pNew->pRightTree = pSecond;
pNew->nWight = pNew->pLeftTree->nWight + pNew->pRightTree->nWight;
m_queue.push(pNew);
}
m_pRoot = pNode;
}
void CHuffmanCode::DeleteTree(TreeNode*& pNode)
{
if (!pNode)
return;
DeleteTree(pNode->pLeftTree);
DeleteTree(pNode->pRightTree);
delete pNode;
pNode = nullptr;
}
void CHuffmanCode::PrintHuffmanCode()
{
std::queue<std::string> strQueue;
PrintHuffmanCode(m_pRoot, strQueue);
}
void CHuffmanCode::PrintHuffmanCode(TreeNode* pNode, std::queue<std::string>& strQueue)
{
if (pNode->strName != "")
{
strQueue.push(pNode->strName);
std::queue<std::string> swapQueue;
while (!strQueue.empty())
{
std::string str = strQueue.front();
std::cout << str.c_str();
strQueue.pop();
if (!strQueue.empty()) // 最后一个不push
swapQueue.push(str);
}
swapQueue.swap(strQueue);
std::cout << std::endl;
}
if (pNode->pLeftTree)
{
strQueue.push("0"); // 左子树的边是0
PrintHuffmanCode(pNode->pLeftTree, strQueue);
strQueue.pop();
}
if (pNode->pRightTree)
{
strQueue.push("1"); // 右子树的边是1
PrintHuffmanCode(pNode->pRightTree, strQueue);
strQueue.pop();
}
}
#include "HuffmanCode.h"
int main()
{
CHuffmanCode huffman;
huffman.InsertNode("a", 10);
huffman.InsertNode("e", 15);
huffman.InsertNode("i", 12);
huffman.InsertNode("s", 3);
huffman.InsertNode("t", 4);
huffman.InsertNode("sp", 13);
huffman.InsertNode("nl", 1);
huffman.Generater();
huffman.PrintHuffmanCode();
std::cin.get();
return 0;
}
下图是哈夫曼的初始状态,及编码后的状态