哈夫曼编码c++/qt实现

接续上一篇文章《哈夫曼树与哈夫曼编码》: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);
    }
}

你可能感兴趣的:(数据结构,c++技术)