接续上一篇文章《哈夫曼树与哈夫曼编码》:http://blog.csdn.net/superyang_/article/details/79276502
--------
main.cpp
--------
#include
#include "Huffman.h"
#include
#include
#include
using namespace std;
// 统计字符出现的频率
int countNum(const char &ch, char *arr)
{
int ret = 0;
char *p = arr;
while(*p != '\0')
{
if (*p == ch) ++ret;
++p;
}
return ret;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Huffman huffman;
char inputArr[512];
memset(inputArr, 0, 512);
cin >> inputArr;
for (int i = 0; i < 512 && inputArr[i] != '\0'; i++)
{
huffman.createNode(inputArr[i], countNum(inputArr[i], inputArr)); // 构造哈夫曼树所有节点
}
huffman.createHuffmanTree(); // 构造一棵哈夫曼树
huffman.printHuffmanRule(); // 输出所有字符的编码规则
huffman.encode(inputArr); // 编码
QString strAfterDecode = huffman.decode(); // 解码
qDebug() << strAfterDecode; // 输出字符与输入字符对比
return a.exec();
}
---------
Huffman.h
---------
#ifndef HUFFMAN_H
#define HUFFMAN_H
#include
#include
#include
struct HuffmanNode
{
char ch; // 字符
// unsigned short code; // 编码
int count; // 频率
HuffmanNode *lChild; // 左孩子
HuffmanNode *rChild; // 右孩子
};
class Huffman
{
public:
Huffman();
public:
void createNode(char ch, int count); // 构造一个节点
void createHuffmanTree(); // 将所有节点构造成一棵哈夫曼树
void printHuffmanRule(); // 输出所有字符的编码规则
void encode(char *str); // 编码
QString decode(); // 解码
protected:
void createCodeMap(); // 创建字符-编码关系对照表
void mapInsert(HuffmanNode *node, ushort code);
private:
QVector<HuffmanNode *> _treeNodeSet;
QMap<char, ushort> _codeMap;
HuffmanNode *_root;
QString _encodeStr;
};
#endif // HUFFMAN_H
------------
Huffman.cpp
------------
#include "Huffman.h"
#include
bool compareCallBack(HuffmanNode *n1, HuffmanNode *n2)
{
return n1->count < n2->count;
}
Huffman::Huffman()
{
_root = NULL;
}
void Huffman::createNode(char ch, int count)
{
HuffmanNode *node = new HuffmanNode;
node->ch = ch;
node->count = count;
// node->code = 0;
node->lChild = node->rChild = NULL;
// 重复节点不再添加
bool isAreadyContain = false;
for (int i = 0; i < _treeNodeSet.size(); i++)
{
if (_treeNodeSet[i]->ch == node->ch)
{
isAreadyContain = true;
}
}
if (!isAreadyContain)
{
_treeNodeSet.append(node);
}
}
void Huffman::createHuffmanTree()
{
// 对所有节点进行排序
qStableSort(_treeNodeSet.begin(), _treeNodeSet.end(), compareCallBack);
HuffmanNode *lChild = _treeNodeSet[0];
// 依次取出节点构建哈弗曼树
for (int i = 1; i < _treeNodeSet.size(); i++)
{
HuffmanNode *rChild = _treeNodeSet[i];
// 如果右节点值大于左节点,交换两个节点
if (lChild->count > rChild->count)
{
HuffmanNode *temp = lChild;
lChild = rChild;
rChild = temp;
}
// 产生一个新子树
_root = new HuffmanNode;
_root->ch = '\0';
_root->count = lChild->count + rChild->count;
_root->lChild = lChild;
_root->rChild = rChild;
// 新子树的根节点为下一次比较的左节点
lChild = _root;
}
createCodeMap();
}
void Huffman::printHuffmanRule()
{
for (QMap<char, ushort>::iterator it = _codeMap.begin(); it != _codeMap.end(); it++)
{
if (it.key() == '\0') continue;
// QString str;
qDebug() << "字符:" << it.key() << "|" << "编码为:" << QString("%1").arg(it.value(), 0, 2);
}
}
void Huffman::encode(char *str)
{
// 这里为了方便没有转换成二进制流
char *p = str;
while(*p != '\0')
{
_encodeStr += QString("%1").arg(_codeMap[*p], 0, 2);
++p;
}
qDebug() << _encodeStr;
}
QString Huffman::decode()
{
QString str;
ushort value = 0;
for (int i = 0; i < _encodeStr.size(); i++)
{
if (_encodeStr.data()[i] == '0')
{
value = value << 1 | 0;
}
else
{
value = value << 1 | 1;
}
if (_codeMap.key(value))
{
str += _codeMap.key(value);
value = 0;
}
}
return str;
}
void Huffman::createCodeMap()
{
mapInsert(_root, 0);
}
void Huffman::mapInsert(HuffmanNode *node, ushort code)
{
ushort lCode = code;
ushort rCode = code;
if (node->lChild)
{
lCode = (lCode << 1) | 0;
_codeMap[node->lChild->ch] = lCode;
}
if (node->rChild)
{
rCode = (rCode << 1) | 1;
_codeMap[node->rChild->ch] = rCode;
}
if (node->lChild && !node->lChild->ch)
{
mapInsert(node->lChild, lCode);
}
if (node->rChild && !node->rChild->ch)
{
mapInsert(node->rChild, rCode);
}
}