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

接续上一篇文章《哈夫曼树与哈夫曼编码》:http://blog.csdn.net/superyang_/article/details/79276502


--------

main.cpp

--------

#include <QCoreApplication>
 
#include "Huffman.h"
 
#include <QDebug>
#include <QString>
 
#include <iostream>
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 <QByteArray>
#include <QVector>
#include <QMap>
 
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 <QDebug>
 
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);
    }
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
下面是一个用C++实现哈夫曼编码的例子,代码如下: ``` #include <iostream> #include <queue> #include <vector> #include <string> #include <map> using namespace std; class HuffmanNode { public: char data; int freq; HuffmanNode* left; HuffmanNode* right; HuffmanNode(char data, int freq) { this->data = data; this->freq = freq; left = right = NULL; } }; class Compare { public: bool operator()(HuffmanNode* a, HuffmanNode* b) { return a->freq > b->freq; } }; class Huffman { public: Huffman(string text) { for (int i = 0; i < text.length(); i++) { freq[text[i]]++; } priority_queue<HuffmanNode*, vector<HuffmanNode*>, Compare> pq; for (auto i : freq) { pq.push(new HuffmanNode(i.first, i.second)); } while (pq.size() != 1) { HuffmanNode* left = pq.top(); pq.pop(); HuffmanNode* right = pq.top(); pq.pop(); HuffmanNode* parent = new HuffmanNode('$', left->freq + right->freq); parent->left = left; parent->right = right; pq.push(parent); } root = pq.top(); encode(root, ""); } void encode(HuffmanNode* root, string str) { if (!root) { return; } if (root->data != '$') { codes[root->data] = str; } encode(root->left, str + "0"); encode(root->right, str + "1"); } string getEncodedText(string text) { string encodedText = ""; for (int i = 0; i < text.length(); i++) { encodedText += codes[text[i]]; } return encodedText; } string getDecodedText(string encodedText) { string decodedText = ""; HuffmanNode* curr = root; for (int i = 0; i < encodedText.length(); i++) { if (encodedText[i] == '0') { curr = curr->left; } else { curr = curr->right; } if (curr->data != '$') { decodedText += curr->data; curr = root; } } return decodedText; } private: map<char, int> freq; map<char, string> codes; HuffmanNode* root; }; int main() { string text = "hello world"; Huffman h(text); string encodedText = h.getEncodedText(text); string decodedText = h.getDecodedText(encodedText); cout << "Original text: " << text << endl; cout << "Encoded text: " << encodedText << endl; cout << "Decoded text: " << decodedText << endl; return 0; } ``` 这个例子中,我们定义了一个`HuffmanNode`类来表示哈夫曼树的节点,其中包含了字符数据、出现频率、左右子节点等信息。我们还定义了一个`Huffman`类来实现哈夫曼编码的功能,其中包含了计算字符频率、构建哈夫曼树、生成编码编码文本、解码文本等方法。在构建哈夫曼树时,我们使用了一个优先队列来存储节点,并按照频率从小到大排序。在生成编码时,我们使用了递归的方式遍历哈夫曼树,并记录每个字符的编码。在编码文本时,我们根据字符的编码将其转换为二进制字符串。在解码文本时,我们根据二进制字符串遍历哈夫曼树,直到找到叶子节点,然后将其对应的字符加入到解码文本中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SuperYang_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值