LZW的编码和解码

    不同于哈弗曼编码针对于每个元素编码,LZW主要针对字符串的编码优化,也就是把出现频率高的字符串压缩成一个字符表示,这也是大名鼎鼎的GIF采用的压缩格式。下面我将从三个角度谈谈我的一些理解,文章主要参考了这位大佬:LZW编解码详解_lzw编码-CSDN博客。

思想简述

    LZW主要针对字符串压缩。比如对于字符串ABAB,首先对于每个会出现的字符都有一个默认编码,也就是A-0,B-1,因为LZW的压缩要求解压时不需要压缩编码表,因此是要求不需要编码表重建的,所以第一个A和第二个B不能连在一起压缩,分别编码为0和1;然后因为AB出现过了,记录在字典中,即AB-2,所以后面的AB就直接编码为2,编码后的字符串为012。

    可以想象,如果直接把两个AB都变成2,那么压缩后是22,一上来就是一个2,那么无法重建字典了,因为这个2怎么来的无从得知。

如何压缩

    压缩的过程相比解压要简单,简单来说就是维护两个字符串,分别是未编码P和当前字符C,这里的P是当前最长的可编码字符串,C就是当前指向的字符,比如xyabcdef,假设此时P起点为的a,终点是d(加粗处),此时C指向的e,假设abcd+e在字典中出现了,那么P更新为P+C也就是abcde,相当于此时还可能继续往下找到更长的编进字典;如果abcd+e没有出现在字典中,那么最长的可编码字符串就是abcd,此时为这个字符串编码,并且在字典中增加一个新的编码对应abcde,同时更新P为e(更新为指针C指向的字符),继续找下面的最长可编码字符串。

    这个过程简单来说就是找最长可编码字符串,一直找到无法编码了,为字符串编码,把无法编码的加入字典

算法步骤如下:

  1. 初始状态,字典里只有所有的默认项,例如0->a,1->b,2->c。此时P和C都是空的。

  2. 读入新的字符C,与P合并形成字符串P+C。

  3. 在字典里查找P+C,如果:

    • P+C在字典里,P=P+C。

    • P+C不在字典里,将P的记号输出;在字典中为P+C建立一个记号映射;更新P=C。

  4. 返回步骤2重复,直至读完原字符串中所有字符。

    下面是对于ababcababac的编码过程,可以对照,编码后的结果是0132372

如何解码

    解码略复杂。可以想想编码的过程,编码的过程实际上就是找到P和C,然后把P编码,把P+C放入字符串,解码就反过来,将当前码值解码,并且把当前码值的解码(P)和下一个码值对应的解码的首字符(C)加入字典。

    具体实现还是维护P和C,只不过P代表当前编码对应字符串,C代表下一个位置的编码对应字符串的首字符

算法流程如下:

  1. 初始状态,字典里只有所有的默认项,例如0->a,1->b,2->c。此时pW和cW都是空的。

  2. 读入第一个的符号cW,解码输出。注意第一个cW肯定是能直接解码的,而且一定是单个字符。

  3. 赋值pW=cW。

  4. 读入下一个符号cW。

  5. 在字典里查找cW,如果: a. cW在字典里: (1) 解码cW,即输出 Str(cW)。 (2) 令P=Str(pW),C=Str(cW)的第一个字符。 (3) 在字典中为P+C添加新的记号映射。 b. cW不在字典里: (1) 令P=Str(pW),C=Str(pW)的第一个字符。 (2) 在字典中为P+C添加新的记号映射,这个新的记号一定就是cW。 (3) 输出P+C。

  6. 返回步骤3重复,直至读完所有记号。

下面是推导的过程,可以参考对照一下:

 

下面是具体的过程解析:

    在解码时,我们面对的实际上是一串数字,就像是0132372这样 ,我们一开始知道的是默认的编码规则,也是就是a-0,b-1,c-2...,假设对于编码后的字符串0132372,编码是把最长可编码字符串P+C编为新的字典元素,P实际就是这里的其中一个元素,比如0,而C就是P的后一个元素,也就是0后面的1串解码后的第一个字符(这个第一个很关键,后面的我都不管,我就要第一个,这是由编码决定的),解码过程就呼之欲出了,P指向一个元素,C是下一个元素,分两种情况讨论(建议先写一遍上面的过程,然后再看):

  1. 如果C对应的解码可以直接从字典中找到,比如P对应0,C对应1,此时0解码为a,1解码为b,P=a,C=b(1解码后的第一个字符),把P+C加入字典,也就是ab-2。

  2. 如果C对应的解码不能直接从字典中找到,就比如到了这里的37部分,p=3解码为ab,C=7,但是字典中还未出现7对应的元素,这时就要想想是什么导致了这种情况?

    先看7是怎么来的,在编码时,ca编码为6之后,P更新为a,然后找到P=ab发现ab字典中也有,所以保留,再往后此时C指向a,aba字典中没有,于是给aba编码为7,更新P为a。

    回到解码,此时37的P=3解码为ab,C对应7,7在字典中找不到,就说明编码7一定同时用到了3和7的首字符,看下图:

 

         不考虑前后的细节,用...代替,这里的P=3=ab,C+y对应的是7对应的解码字符串,目前还不知道 7的编码规则,无法解码。假如 7的编码没有用到P,那么两种情况:一种是7在P之前就编码好了,那么此时7应该在字典中,矛盾;一种是7的编码在C+y+...中编好,这与编码时寻找可编码字符串矛盾,因为还没放入字典就被用了,所以唯一可能性就是7的编码用到了前面的P,而由于7还未解码,因此对应的解码规则也还没被推导出来,而我们关心的放入字典的就是7的首字符,那么其实也就是这里P的首字符a,所以新的规则P+C(P的第一个)=aba-7加入字典,解码7。

    最后这段解析比较绕,我自己也绕来绕去感觉有点乱,有不足和错误可以直接指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/211011.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL server 2016安装

1、关系数据库的基本概念。 行:每行成为一条“记录”或“元组”,用于描述一个对象的信息。 列:每列称为一个“字段”或“属性”,用于描述对象的一个属性。 2、主键与外键。 主键:键,即关键字。主键由一个或…

[传智杯 #2 决赛] 补刀

题目描述 UIM 在写程序的空闲玩一款 MOBA 游戏。 当敌方的小兵进入到我方防御塔的范围内,就会持续受到防御塔造成的伤害;当然我方英雄也可以对它造成伤害。当小兵的血量降到了 0 或者更低,就会被击杀。为了获得经验,UIM 希望在防…

C语言中的格式化输出符号:%d %c %p %x等

文章目录 概览%d%c%d和%c的区别%p%x %X输出浮点数参考 概览 C语言中的格式化输出符号有很多,以下是一些常见的: %d 或 %i:用于输出十进制整数。 %u:用于输出无符号十进制整数。 %f:用于输出浮点数。 %s:用…

Linux - 进程间通信

进程通信 初步理解进程通信 所谓进程之间的通信,就是两个进程之间的 数据层面的交互。 我们之前说过,父子进程之间是有一些数据通信的,子进程可以看到一些父进程 允许 子进程访问的数据,比如 父进程的 环境变量,子…

来CSDN一周年啦!!!

各位CSDN的uu们你们好呀,今天是小雅兰来到CSDN创作的一周年啦,时间,说长不长,说短也不短,在这一年中,我认为我也收获了一些很有价值的东西吧!! 一周年了,该创作的还得继续…

Android 应用资源概览

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。 目录 一、导读二、概览三、资源类型分组四、配置限定符名称表…

【Unity入门】声音组件AudioSource简介及实现声音的近大远小

AudioSource组件 将需要播放声音的物体挂载Audio Listener组件,实现声音的播放 AudioSource组件属性 (1)AudioClip(音频剪辑):指定播放的音频文件。 (2)Output(音频输…

Paxos 算法

Paxos 算法 介绍 Paxos 算法是第一个被证明完备的分布式系统共识算法。共识算法的作用是让分布式系统中的多个节点之间对某个提案(Proposal)达成一致的看法。提案的含义在分布式系统中十分宽泛,像哪一个节点是 Leader 节点、多个事件发生的…

使用mybatis-plus框架:@Autowired报错Could not autowire. No beans of ‘XXX‘ type found

使用mybatis-plus框架,使用xxmapper报错: 解决办法是:在mapper中添加注解: Repository Mapper 也可以使用 AutowiredSysRoleMenuService sysRoleMenuService;替代 AutowiredSysRoleMenuMapper sysRoleMenuMapper;方法名不同,但…

RHCE学习笔记(RHEL8) - RH294

Chapter Ⅰ 介绍Ansible ansible ansible是一款开源自动化平台 ansible围绕一种无代理架构构建,在控制节点上安装ansible,且客户端不需要任何特殊的代理软件;ansible使用SSH等标准协议连接受管主机,并在受管主机上运行代码或命令来…

【嵌入式-51单片机】常见位运算和数据类型

51单片机中 数据类型如下&#xff1a; 位运算符如下&#xff1a; 按位左移<<&#xff1a;低位补零&#xff0c;高位移出 按位右移>>&#xff1a;高位补零&#xff0c;低位移出 按位与&&#xff1a;对应位上的值必须同时为1才为1&#xff0c;可以用来对指定位…

鸿蒙学习之TypeScript 语法理解笔记

1、变量及数据类型 // string&#xff1a;字符串&#xff0c;单引号或双引号 let msg : string hello wprld console.log(msg:msg)// number&#xff1a;数值、整数、浮点let num :number 21console.log(num:num)//boolean&#xff1a;布尔let finished: boolean truecons…

HarmonyOS 开发案例分享:万能卡片也能用来玩游戏

一、前言 作为一名开发爱好者&#xff0c;从大了讲&#xff0c;我学习并进行 HarmonyOS 相关开发是为了能为鸿蒙生态建设尽一份绵薄之力&#xff0c;从小了讲&#xff0c;就是为了自己的兴趣。而万能卡片是一个让我非常感兴趣的东西。 很多时候我跟别人解释什么是万能卡片&…

Redis SDS 源码

底层数据结构的好处&#xff1a; 杜绝缓冲区溢出。减少修改字符串长度时所需的内存重分配次数。二进制安全。兼容部分C字符串函数。 常用命令&#xff1a; set key value、get key 等 应用场景&#xff1a;共享 session、分布式锁&#xff0c;计数器、限流。 1、给char*定义…

【排序】直接插入排序和希尔排序

目录 一、排序思想 1、直接插入排序 2、希尔排序 二、代码实现 三、性能比较 四、排序总结 1、直接插入排序 2、希尔排序 一、排序思想 1、直接插入排序 基本思想&#xff1a;把待排序的序列选取一个整数逐个插入到已经排好的有序序列中&#xff0c;直到所有整数都插入…

Unity 下载网络图片的方法,并把图片赋值给UI和物体的方法

Unity 下载网络图片的方法&#xff0c;可使用WWW类或UnityWebRequest类&#xff0c;其中UnityWebRequest是新版的方法。 通常我们下载图片都会转成Texture&#xff0c;然后赋值给UI或者物体。 具体实现方法&#xff1a; using System.Collections; using System.Collections…

P1 什么是链表 C语言简单易懂

目录 前言 01 什么是链表 02 数组的特点 03 数组的缺点 3.1 删除数组其中一个元素 3.2 数组增加某个节点 04 链表 前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《 C 》✨✨✨ &#x1f525; 推荐专栏2: 《 Linux C应用编程&#xff08;概念…

国际语音群呼系统

随着海外电话营销的发展&#xff0c;越来越多的出海企业通过国际语音群呼系统打开出海营销之路。企业出海营销运营&#xff0c;选择一个安全、高效、便捷的国际语音群呼系统非常重要。 一、什么是国际语音群呼系统&#xff1f; 国际语音群呼是指通过语音的方式批量向海外用户传…

【设计模式-4.1】行为型——策略模式

说明&#xff1a;本文介绍设计模式中的行为型设计模式中的&#xff0c;策略模式&#xff1b; 计算器 策略模式属于行为型设计模式&#xff0c;关注对象的行为。例如&#xff0c;目前有一个计算器类&#xff0c;可对两个数进行加减计算&#xff0c;如下&#xff1a; &#xf…

中国湖泊面积-水位长时序数据产品(2000-2020)

今天我们分享中国湖泊面积-水位长时序数据产品&#xff08;2000-2020&#xff09; 该数据集包含中国典型湖泊2000-2020年最大水体面积、多年平均面积、水位变化速率及空间分布矢量。 数据溯源信息 「数据来源描述」Landsat、HJ、ZY、Jason、ENVISAT、Cryosat、ICESat和HY 「数…