哈夫曼编码实现文本压缩和解压(C++)

哈弗曼树:又称最优二叉树,是带权路径长度最短的树。

哈夫曼编码:是一种前缀编码,即同一字符集中任何一个字符的编码都不是另外一个字符编码的前缀(最左子串)。

        在哈弗曼树中,若用‘0’表示左子树,‘1’表示右子树,那么每当从根遍历到一个叶子节点时都会形成一个01串,即该叶子节点的编码,由于各个叶子节点已经是树的最末梢了,因此他们之间的编码不会有包含关系,这样就生成了前缀编码集。

那么,如何构建哈弗曼树呢?

    首先,我们需要一串字符,并且得到其中每个字符出现的频次(作为权值),接着我们将这些权值放在一个vector中,并将其从小到大进行排序,之后取前两个(权值最小的两个)作为叶子节点构建一棵二叉树,将权值相加赋给新生成的根节点,之后将根节点加入到vector中,重复以上操作,直到vector中仅剩一个数据为止,该数据则是哈弗曼树最终的根节点。代码实现如下:

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
using namespace std;

typedef struct a
{
    char key = '\0';  //字符
    int weight = 0;   //权值(出现频次)
    struct a *LeftChild = nullptr;
    struct a *RightChild = nullptr;
}Node;

bool cmp(Node *data1,Node *data2)
{
    return data1 -> weight < data2 -> weight;
}

class HuffManTree
{
public:
    Node *root;
    explicit HuffManTree(map<char,int> d)  //传入一个map,其中存储了所有的字符及其出现的频次
    {
        vector<Node *> weight_order;
        // 遍历map,将其中的字符以及权值存储到各个叶子节点(node)中,将这些节点放在一个vector里面
        for(auto iter : d)
        {
            auto tmp = new Node;
            tmp -> key = iter.first;
            tmp -> weight = iter.second;
            weight_order.push_back(tmp);
        }
        // 根据先前的思想,我们至少应该同时获取两个节点的信息才能构建哈弗曼树,那么假如传入只有一个节点,就要进行特殊化处理
        if(weight_order.size() == 1)
        {
            auto tmp = new Node;
            auto t = new Node;
            tmp -> weight = weight_order[0] -> weight;
            Node_Copy(t,weight_order[0]);
            weight_order.erase(weight_order.begin());
            tmp -> LeftChild = t;
            tmp -> RightChild = nullptr;
            weight_order.push_back(tmp);
        }
        //正常情况下,节点数大于等于2,此时则需要不断地排序,建树,删除旧的两个节点,加入一个新的节点,直到最终vector中仅剩余一个节点(根节点)
        while(weight_order.size() != 1)
        {
            sort(weight_order.begin(),weight_order.end(),cmp);  //排序
            auto tmp = 
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值