huffman编码

使用优先队列进行优化的haffman编码。

  1. 统计文章中的词频
  2. 使用优先队列(堆)创建haffman树
  3. 遍历Haffman树得到每一个字符的huffman编码, 保存在enc(unordered_map)中
  4. 文章进行编码
  5. 使用huffman树和haffman编码进行解码。

创建huffman树的时间复杂度O(ClogC)O(ClogC)O(ClogC)其中C是单词种类的个数。
编码的时间复杂度O(n)O(n)O(n),只需要遍历一遍字符串就行了。
解码的时间复杂度O(m)O(m)O(m),只需要遍历一遍编码后的字符串就行了。

huffman编码是现代压缩技术的基础。应该写个输入输出测试一下对文件的压缩的情况的。
char是8个bit, 而bit数组中的一位是1个bit。所以肯定会有压缩的效果。
文件最后保存的是haffman树以及对应的huaffman编码。在解码的时候先读取haffmans树,然后对二进制文件进行解码。


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <unordered_map>

using namespace std;

// Encodes a URL to a shortened URL.
struct HuffmanTree {
    HuffmanTree *l, *r;
    int cnt;
    char ch;                              // 词频和单词
    HuffmanTree(int cnt, char ch, HuffmanTree *l, HuffmanTree *r):cnt(cnt), ch(ch), l(l), r(r) {}
};
class cmp{
public:
    /* Node::priority 大的优先, 重写小于号 */
    bool operator () (HuffmanTree* &a, HuffmanTree* &b) const
    {
        return a->cnt > b->cnt;
    }
};

typedef pair<int, char>PR;
priority_queue<HuffmanTree*, vector<HuffmanTree*>, cmp>que, bakcup;
unordered_map<char, int>mp;

HuffmanTree* buildHuffman() {
    bakcup = que;
    while (!bakcup.empty()) {
        printf("%d %c\n", bakcup.top()->cnt, bakcup.top()->ch);
        bakcup.pop();
    }

    while (que.size() >= 2) {
        HuffmanTree* t1 = que.top(); que.pop();
        HuffmanTree* t2 = que.top(); que.pop();
        HuffmanTree *fa = new HuffmanTree(t1->cnt + t2->cnt, '#', t1, t2);
        que.push(fa);
    }
    return que.top();
}
HuffmanTree *root;
unordered_map<char, string>enc;
void travel(HuffmanTree *root, string s) {              // 获取每个结点的huffman编码
    if (root == NULL) return ;
    // 叶子结点, 统计编码
    if (root->l == NULL && root->r == NULL) {
        cout << root->ch << " " << s << endl;
        enc[root->ch] = s;
        return ;
    }
    travel(root->l, s + '0');
    travel(root->r, s + '1');
}
string encode(string longUrl) {
    for (char ch : longUrl) {
        mp[ch]++;
    }
    for (auto [ch, cnt] : mp) {
        que.push(new HuffmanTree(cnt, ch, NULL, NULL)); // 存放的是指针。
    }

    root = buildHuffman();
    travel(root, "");                                   // 遍历haffman树获取Huffman编码
    string ans;
    for (char ch : longUrl) {
        ans += enc[ch];
    }
    return ans;
}


string treeDecode(HuffmanTree *root, int &cur, string &s) {
    if (root == NULL) return "";
    if (root->l == NULL && root->r == NULL) {
        string ans = "";
        ans += root->ch;
        return ans;
    }
    cur++;
    if (s[cur] == '0') return treeDecode(root->l, cur, s);
    else return treeDecode(root->r, cur, s);
}
// Decodes a shortened URL to its original URL.
string decode(string shortUrl) {
    int cur = -1;
    string ans;
    int n = shortUrl.size();
    for (cur; cur < n - 1;) {
        printf("cur = %d\n", cur);
        string s = treeDecode(root, cur, shortUrl);
        cout << s << endl;
        ans += s;
    }
    return ans;
}

int main() {

    string s = "aaabbc";
    s = encode(s);
    cout << s << endl;
    cout << decode(s) << endl;
}

### Huffman 编码算法的实现与原理 #### 1. Huffman 编码的核心概念 Huffman 编码是一种基于概率统计的无损数据压缩技术,其核心思想是通过对高频字符分配较短的编码,而对低频字符分配较长的编码,从而减少整体编码长度。这种方法能够显著降低数据存储需求并提高传输效率[^1]。 #### 2. Huffman 编码的工作流程 以下是 Huffman 编码的主要工作阶段: - **构建频率表** 首先分析输入数据集中各个字符出现的次数或频率,并将其记录下来作为后续建树的基础[^4]。 - **创建霍夫曼树 (Huffman Tree)** 使用优先队列(最小堆)按字符频率从小到大排列节点。每次取出两个频率最低的节点组合成一个新的父节点,新节点的频率等于子节点之和。重复此过程直到只剩下一个根节点为止[^2]。 - **生成编码字典** 自顶向下遍历霍夫曼树,在每条路径上标记左分支为 `0` 和右分支为 `1`。最终到达叶子结点时所形成的二进制序列即为此字符对应的唯一前缀码[^3]。 - **数据压缩与解压** 利用上述生成好的编码规则替换原文档中的每一个原始符号完成压缩;相反方向则是依据同样的结构重新解析回原样内容实施解码操作。 #### 3. C语言实现示例 下面给出一段简单的C程序演示如何运用该方法来进行基本的文字串压缩处理: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { char ch; int freq; struct Node *left, *right; } Node; // 创建新的节点函数定义省略... void buildTree(Node **root){ // 构造霍夫曼树逻辑... } void generateCodes(Node* root, int arr[], int top){ // 生产具体编码方案递归调用细节忽略.. } int main(){ // 初始化变量及读取输入字符串部分跳过.. buildTree(&root); generateCodes(root, codeArr, 0); return 0; } ``` 以上仅为框架示意,实际开发需补充完整功能模块才能正常使用。 #### 4. 应用场景举例 除了常规文本文件外,Huffman 编码还广泛应用于多媒体领域比如JPEG图片标准之中,用来优化颜色采样后的量化系数表达形式以进一步缩减体积而不失真太多。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值