哈夫曼编码(C++优先队列实现)

简介: 哈夫曼编码(C++优先队列实现)

哈夫曼编码


使用变长编码表对字符进行编码,出现频率高的字符采用较短的编码,出现频率低的采用较长的编码。以达到编码后的字符串的平均长度尽可能短,以达到无损压缩数据的目的。


图解

有一字符串string word = "abbbcccccdddddddd",字符a,b,c,d权重分别为1,3,5,8。


初始

image.png

第一次合并

image.png

第二次合并

image.png

第三次合并

image.png

字符  权重   编码
d     8     0
a     1     100
b     3     101
c     5     11


模板

按照字符串各字符的出现频率建立哈夫曼树,则每一个叶子结点对应一个字符。记每个结点的左分支为0,右分支为1,得到的编码即为哈夫曼编码。

/* 
结构中左右结点未设置为空,导致在先序遍历时进入空结点输出权值报错!
*/
#include <iostream>
#include <map>
#include <queue>
using namespace std;
struct TreeNode
{
    int weight;
    char ch = ' ';
    string code;
    // 要设为空,不然在遍历时会出错
    TreeNode *left = NULL;
    TreeNode *right = NULL;
};
//自定义排序规则
class mycomparison
{
public:
    bool operator()(const TreeNode *a, const TreeNode *b)
    {
        return a->weight > b->weight;
    }
};
// 构建哈夫曼树
TreeNode *Huffman(priority_queue<TreeNode *, vector<TreeNode *>, mycomparison> *H)
{
    TreeNode *T;
    int times = H->size();
    // 做times-1次合并
    for (int i = 1; i < times; i++)
    {
        T = new TreeNode;
        T->left = H->top();
        H->pop();
        T->right = H->top();
        H->pop();
        T->weight = T->left->weight + T->right->weight;
        H->push(T);
    }
    // T = H->top();
    // H->pop();
    return H->top();
}
// 改写先序遍历,输出叶子结点
void PreOrderTraversal(TreeNode *Huff)
{
    if (Huff)
    {
        if (Huff->ch != ' ')
        {
            cout << Huff->ch << "     " << Huff->weight << "        " << Huff->code << endl;
        }
        PreOrderTraversal(Huff->left);
        PreOrderTraversal(Huff->right);
    }
}
// 哈夫曼树编码
void GetCode(TreeNode *Huff, string code)
{
    if (Huff)
    {
        Huff->code = code;
        GetCode(Huff->left, code + "0");
        GetCode(Huff->right, code + "1");
    }
}
int main()
{
    string word = "abbbcccccdddddddd";
    map<char, int> Hash;
    for (auto ch : word)
    {
        if (!Hash.count(ch))
        {
            Hash.emplace(ch, 1);
        }
        else
        {
            Hash[ch]++;
        }
    }
    // 删除空格
    Hash.erase(' ');
    // 建堆
    priority_queue<TreeNode *, vector<TreeNode *>, mycomparison> MinHeap;
    int count = 0;
    for (auto i : Hash)
    {
        TreeNode *T = new TreeNode;
        T->weight = i.second;
        T->ch = i.first;
        MinHeap.push(T);
    }
    TreeNode *Tree = Huffman(&MinHeap);
    GetCode(Tree, "");
    cout << "Char  Weight   Code" << endl;
    PreOrderTraversal(Tree);
    system("pause");
    return 0;
}
目录
相关文章
|
1月前
|
存储 自然语言处理 Linux
探究C/C++编码世界:从字符编码到中文处理之艺(三)
探究C/C++编码世界:从字符编码到中文处理之艺
44 2
|
1月前
|
自然语言处理 C++
探究C/C++编码世界:从字符编码到中文处理之艺(二)
探究C/C++编码世界:从字符编码到中文处理之艺
37 2
|
1月前
|
存储 自然语言处理 程序员
探究C/C++编码世界:从字符编码到中文处理之艺(一)
探究C/C++编码世界:从字符编码到中文处理之艺
34 1
|
1月前
|
并行计算 Go C++
2182.构造限制重复的字符串(模拟 贪心 优先队列 C++ Go)
【2月更文挑战第19天】2182.构造限制重复的字符串(模拟 贪心 优先队列 C++ Go)
23 1
|
2月前
|
存储 算法 搜索推荐
【编码狂想】探索C++ STL:提升编程效率的强大工具集
【编码狂想】探索C++ STL:提升编程效率的强大工具集
31 0
|
1月前
|
存储 算法 C语言
【C++入门到精通】C++入门 —— priority_queue(STL)优先队列
本文介绍了C++的STL组件`std::priority_queue`,它是一个容器适配器,实现优先队列数据结构,通常基于堆实现。文章讨论了优先队列的基本概念、特点和底层堆结构,强调了其自动排序和优先级最高元素的访问。还展示了如何定义、插入、访问和移除元素,以及自定义比较函数。此外,提供了模拟实现`priority_queue`的代码示例,探讨了仿函数的作用,包括默认的`std::less`和自定义比较函数。文章鼓励读者进一步探索C++的优先队列及其应用。
26 3
|
2月前
|
机器学习/深度学习 算法 C语言
【编码狂想】深度探索C++编程之旅:“数组、字符串、函数与KMP算法解密“
【编码狂想】深度探索C++编程之旅:“数组、字符串、函数与KMP算法解密“
73 0
|
29天前
|
安全 编译器 C语言
MISRA C++ 、Google C++ 、AUTOSAR Adaptive Platform编码 C++ 规范总结
MISRA C++ 、Google C++ 、AUTOSAR Adaptive Platform编码 C++ 规范总结
88 1
|
3月前
|
测试技术 C++
c++优先队列priority_queue(自定义比较函数)
c++优先队列priority_queue(自定义比较函数)
75 0

热门文章

最新文章