哈夫曼编码与压缩文件

我们已知:1 t y p e type type=8 b i t bit bit,计算机的内存存储器的数据信号有 D 0 − D 7 D0-D7 D0D7 8个数据信号,每个数据信号都会接受 1 b i t bit bit 的数据,所以我们称 8 b i t bit bit= 1 t y p e type type (字节)。所以每接受一个英文字符,都会占用 1 t y p e type type 的内存,但是对于这种方式我们其实可以进行压缩,来减少文件对内存的占用。接下来进入正题!

哈夫曼编码

执行过程:
先统计每个字符的出现频率,然后按照出现频率从小到大排序,然后将频率低的进行和并,合并成一个新的节点,然后在对剩余的节点(包括刚合并的节点进行上次操作)最终我们可以得到一棵树,然后从树的根节点开始遍历树,得到每个叶节点的哈夫曼编码(左0右1原则)。

假设有字符串:AAAAAABBCDDEEEEEF,占用内存 17 t y p e type type= 17 ∗ * 8 bit
在这里插入图片描述
得到哈夫曼编码:

000000000000 100100 110 101101 0101010101 111

40 b i t bit bit = 40/8 = 5 t y p e type type
文件对内存的占用从17 字节到5字节,可见哈夫曼编码对文件的压缩率高的惊人

这里用c++实现哈夫曼编码:

#include <bits/stdc++.h>
using namespace std;

int ct;
struct node {
  int Node;
  int w;
  bool operator<(const node& other) const { return other.w < w; }
};
map<char, int> Hash;
int Haffman[10005][3];
priority_queue<node> q;
unordered_map<int, string> Hs;
void Haffmantree_create() {
  while (q.size() != 1) {
    int x = q.top().w;
    int ls = q.top().Node;
    q.pop();
    int y = q.top().w;
    int rs = q.top().Node;
    q.pop();
    int sum = x + y;
    ++ct;
    Haffman[ct][0] = ls;
    Haffman[ct][1] = rs;
    q.push(node{ct, sum});
  }
}
void Haffman_serach(int rt, string s) {
  if (Haffman[rt][0] == Haffman[rt][1]) {
    cout << char(Haffman[rt][2]) << ' ' << s << endl;
    Hs[Haffman[rt][2]] = s;
    return;
  }
  Haffman_serach(Haffman[rt][0], s + '0');
  Haffman_serach(Haffman[rt][1], s + '1');
}
void Haffman_chieve(string s) {
  Haffmantree_create();
  string ss = "";
  Haffman_serach(ct, ss);
  string ans = "";
  for (auto key : s) {
    ans += Hs[key];
  }
  cout << ans << endl;
  cout << ans.size() << "bit" << endl;
}
int main() {
  string s;
  cin >> s;
  for (auto x : s) {
    Hash[x]++;
  }
  for (auto it = Hash.begin(); it != Hash.end(); it++) {
    ++ct;
    q.push(node{ct, it->second});
    Haffman[ct][0] = ct;
    Haffman[ct][1] = ct;
    Haffman[ct][2] = int(it->first);
  }
  Haffman_chieve(s);
  return 0;
}

注意:

这个实现是稍有不足的,因为最后的bit数,并不一定是8的整数倍,所以有些需要补全。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值