关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » Python »LZ77压缩算法编码Python实现原理图解

    LZ77压缩算法编码Python实现原理图解

    2014-12-02 00:00:00 出处:红脸书生
    分享

    前言

    LZ77算法是无损压缩算法,由以色列人Abraham Lempel发表于1977年。LZ77是典型的基于字典的压缩算法,现在很多压缩技术都是基于LZ77。鉴于其在数据压缩领域的地位,本篇文章将结合图片和源码详细介绍其原理。

    原理介绍:

    首先介绍几个专业术语。

    1.lookahead buffer(不知道怎么用中文表述,暂时称为待编码区):

    等待编码的区域

    2. search buffer:

    已经编码的区域,搜索缓冲区

    3.滑动窗口:

    指定大小的窗,包含“搜索缓冲区”(左) + “待编码区”(右)

    接下来,介绍具体的编码过程:

    为了编码待编码区, 编码器在滑动窗口的搜索缓冲区查找直到找到匹配的字符串。匹配字符串的开始字符串与待编码缓冲区的距离称为“偏移值”,匹配字符串的长度称为“匹配长度”。编码器在编码时,会一直在搜索区中搜索,直到找到最大匹配字符串,并输出(o, l ),其中o是偏移值, l是匹配长度。然后窗口滑动l,继续开始编码。假如没有找到匹配字符串,则输出(0, 0, c),c为待编码区下一个等待编码的字符,窗口滑动“1”。算法实现将类似下面的:

    while( lookAheadBuffer not empty )
     {
     get a pointer (position, match) to the longest match
     in the window for the lookAheadBuffer;
    output a (position, length, char());
     shift the window length+1 characters along;
     }

    主要步骤为:

    1.设置编码位置为输入流的开始

    2.在滑窗的待编码区查找搜索区中的最大匹配字符串

    3.假如找到字符串,输出(偏移值, 匹配长度), 窗口向前滑动“匹配长度”

    4.假如没有找到,输出(0, 0, 待编码区的第一个字符),窗口向前滑动一个单位

    5.假如待编码区不为空,回到步骤2

    描述实在是太复杂,还是结合实例来讲解吧

    实例:

    现在有字符串“AABCBBABC”,现在对其进行编码。

    一开始,窗口滑入如图位置

    由图可见,待编码缓冲区有“AAB”三个字符,此时搜索缓冲区还是空的。所以编码第一个字符,由于搜索区为空,故找不到匹配串,输出(0,0, A),窗口右移一个单位,如下图

    此时待编码区有“ABC”。开始编码。最先编码”A”,在搜索区找到”A”。由于没有超过待编码区,故开始编码”AB”,但在搜索区没有找到匹配字符串,故无法编码。因此只能编码”A”。

    输出(1, 1)。即为相对于待编码区,偏移一个单位,匹配长度为1。窗口右滑动匹配长度,即移动1个单位。如下图

    一样,没找到,输出(0, 0, B),右移1个单号,如下图

    输出(0, 0, C),右移1个单位,如下图

    输出(2, 1),右移1个单位,如下图

    输出(3, 1), 右移1个单位,如下图

    开始编码”A”,在搜索缓冲区查找到匹配字符串。由于待编码缓冲区没有超过,继续编码。开始编码”AB”,也搜索到。不要停止,继续编码“ABC”,找到匹配字符串。由于继续编码,则超过了窗口,故只编码“ABC”,输出(5, 3),偏移5,长度3。右移3个单位,如下图

    此时待编码缓冲区为空,停止编码。

    最终输出结果如下

    python代码实现:

    class Lz77:
        def __init__(self, inputStr):
            self.inputStr = inputStr #输入流
            self.searchSize = 5    #搜索缓冲区(已编码区)大小
            self.aheadSize = 3     #lookAhead缓冲区(待编码区)大小 
            self.windSpiltIndex = 0 #lookHead缓冲区开始的索引
            self.move = 0
            self.notFind = -1   #没有找到匹配字符串
    
        #得到滑动窗口的末端索引
        def getWinEndIndex(self):
            return self.windSpiltIndex + self.aheadSize
    
        #得到滑动窗口的始端索引
        def getWinStartIndex(self):
            return self.windSpiltIndex - self.searchSize
    
        #判断lookHead缓冲区是否为空
        def isLookHeadEmpty(self):
            return True if self.windSpiltIndex + self.move> len(self.inputStr) - 1   else False
    
        def encoding(self):
            step = 0
            print("Step   Position   Match   Output")
            while not self.isLookHeadEmpty():
                #1.滑动窗口
                self.winMove()
                #2. 得到最大匹配串的偏移值和长度
                (offset, matchLen) = self.findMaxMatch()
                #3.设置窗口下一步需要滑动的距离
                self.setMoveSteps(matchLen) 
                if matchLen == 0:
                    #匹配为0,说明无字符串匹配,输出下一个需要编码的字母
                    nextChar = self.inputStr[self.windSpiltIndex]
                    result = (step, self.windSpiltIndex, '-',  '(0,0)' + nextChar)
                else:
                    result = (step, self.windSpiltIndex, self.inputStr[self.windSpiltIndex - offset: self.windSpiltIndex - offset + matchLen], '(' + str(offset) + ',' + str(matchLen) + ')')
                #4.输出结果
                self.output(result)    
                step = step + 1        #仅用来设置第几步
    
        #滑动窗口(移动分界点)
        def winMove(self):
            self.windSpiltIndex = self.windSpiltIndex + self.move
    
        #寻找最大匹配字符并返回相对于窗口分界点的偏移值和匹配长度
        def findMaxMatch(self):
            matchLen = 0
            offset = 0
            minEdge = self.minEdge() + 1  #得到编码区域的右边界
            #遍历待编码区,寻找最大匹配串
            for i in range(self.windSpiltIndex + 1, minEdge):
                #print("i: %d" %i)
                offsetTemp = self.searchBufferOffest(i)
                if offsetTemp == self.notFind: 
                    return (offset, matchLen)
                offset = offsetTemp #偏移值
    
                matchLen = matchLen + 1  #每找到一个匹配串,加1
    
            return (offset, matchLen)
    
        #入参字符串是否存在于搜索缓冲区,假如存在,返回匹配字符串的起始索引
        def searchBufferOffest(self, i):
            searchStart = self.getWinStartIndex()
            searchEnd = self.windSpiltIndex 
            #下面几个if是处理开始时的特殊情况
            if searchEnd < 1:
                return self.notFind
            if searchStart < 0:
                searchStart = 0
                if searchEnd == 0:
                    searchEnd = 1
            searchStr = self.inputStr[searchStart : searchEnd]  #搜索区字符串
            findIndex = searchStr.find(self.inputStr[self.windSpiltIndex : i])
            if findIndex == -1:
                return -1
            return len(searchStr) - findIndex
    
        #设置下一次窗口需要滑动的步数
        def setMoveSteps(self, matchLen):
            if matchLen == 0:
                self.move = 1
            else:
                self.move = matchLen
    
        def minEdge(self):
            return len(self.inputStr)  if len(self.inputStr) - 1 < self.getWinEndIndex() else self.getWinEndIndex() + 1
    
        def output(self, touple):
            print("%d      %d           %s     %s" % touple)
    
    if __name__ == "__main__":
        lz77 = Lz77("AABCBBABC")
        lz77.encoding()

    只是简单的写了下,没有过多考虑细节,请注意,这不是最终的代码,只是用来阐述原理,仅供参考。输出结果就是上面的输出(格式由于坑爹的博客园固定样式,代码位置有偏移,请注意)

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    SQL汉字转换为拼音的函数

    windows 7系统无法运行Photoshop CS3的解决方法

    巧用MySQL加密函数对Web网站敏感数据进行保护

    MySQL基础知识简介

    Windows7和WinXP下如何实现不输密码自动登录系统的设置方法介绍

    windows 7系统ip地址冲突怎么办?windows 7系统IP地址冲突问题的

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。