Huffman编码解压缩的通俗讲解

本文介绍了哈夫曼编码的压缩和解压缩原理。通过构建哈夫曼树,根据字符出现频率生成不同长度的编码,实现文件的高效压缩。在解压缩过程中,利用权值数组重建哈夫曼树,读取压缩文件的bit流,通过哈夫曼树还原原始数据。文章还强调了C++中以字节为单位的文件操作在处理不定长编码时的挑战,并提出解决方案。
摘要由CSDN通过智能技术生成

前言

好久没写博客了,主要是各种事缠着,难以抽出时间。这两个月以来,由于项目需要,我也逼着自己学到了很多,什么java后台,web前端,还有万恶的OpenCV图形处理……,呵呵,全栈:( 。但对Android的学习我始终不肯放下。但是今天这篇博客不是关于Android的,而是算法的相关应用–哈夫曼压缩。这是数据结构与算法实验里面的一个项目,网上关于这方面的资料很多,但大多数博客都是随便讲讲然后扔下代码。同时有同学请教我,所以就有了写一篇关于这个知识点的高质量博文的想法。

你应该知道

读这篇博客前你应该掌握如下的基本知识:

  • 最基本的常识,一个字节有8位,int一般占4个字节,即32位。
  • vector动态数组的基本用法
  • 利用FILE类对二进制文件的基本读写操作
  • fgetc(fin);方法虽然返回的是int,但实际上是由一个字节转换而来的,所以其范围也是0~255;同样地,fputc(int,fout);方法也是一样,写入一个字节到二进制文件当中,所以传入的int的范围也在0~255。
  • 计算机存储文件都是以二进制流的形式来存的,图片也不例外。
  • 值得吐槽的是,C++读写操作的最小单位是字节,要想以bit为单位读写文件只能通过读写字节然后进行移位运算。Java就很人性化啦,提供了bit流的IO操作函数。
  • 利用fwrite()、fread()方法可以将数据块读写文件,权值数组的读写就是这两个方法进行。这两个方法的使用请查阅文档。
  • -

哈夫曼编码

其实哈夫曼编码并不是本篇的重点,所以下面我只进行粗略的讲述。

压缩的原理

计算机文件是由01串组成的。那么举个栗子,有一个文件,头几个二进制串:
01000010010011010001011011011111……..
那么,C++就是每8位(bit)来读,就是以字节为单位来读取,每个字节被转化成整型int。
读取代码如下:

    int c;
    vector<int> binaryData;
    while (true) {
        c = fgetc(fin);
        if (feof(fin)) break;
        weight[c]++;
        binaryData.push_back(c);
        cout<<c<<endl;
    }

输出为:66 77 22 223 ………
这是定长的编码方式。而Huffman编码不定长的编码方式,是通过出现字节的频率的不同编程长度不同的01码字。假如,这里66这个字节出现了1万次,77这个字节出现了只5次,那我们当然想把66尽可能用短一点的码字来编,而77就用长一点的码字来编也无所谓,毕竟它出现的次数少。这样不就能有效地缩短了文件整体的bit数吗?

具体代码的实现

根据各个字节出现的频率(权值)来构建Huffman树离不开对权值进行排序。而我们发现,用最小堆来构建Huffman树是最优雅的方式了。
核心代码:

    //传入权值数组形成最小堆
    MinHeap heap(n, h);
    HuffmanTreeNode *n1 = NULL;
    HuffmanTreeNode *n2 = NULL;
    HuffmanTreeNode *parent = NULL;
    //进行n-1次操作后,堆已空,哈夫曼树构建完成
    for (int i = 0; i < n - 1; i++) {
        //从堆中取出最小两个的节点,
        n1 = heap.pop();
        n2 = heap.pop();
        //new一个父节点,父节点的值为两个子节点的值之和
        parent = new HuffmanTreeNode(n1->weight + n2->weight);
        //连接刚才取出的两个节点,
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值