数据压缩算法

概述

之前在听到数据压缩的时候, 想着肯定是某些高深莫测的算法, 能够完成数据的压缩这种事情, 最近看了看, 嗯, 至少咱还是能看懂的.

无损压缩

众所周知, 不管你是exewordtxtdmg等等, 在存储上都是以二进制进行存储的, 所以, 在讨论压缩时, 忽略文件格式即可, 只要将其看做一串数字即可.

方案一

开始了, 上数字串: 11111111111111111111.

如果让你向别人口述这个字符串, 你会如何讲, "1111...1111". 我估计就算你这么讲, 人家听半天也没听明白你说的到底是几个1. 但是, 如果你这么说的话, 就不一样了: "20个1". 人家一听就明白了.

你以为这种方式用不到? 天真, 如果是一张黑白照片, 上面的每一个像素点, 非黑即白, 连续的相同内容必然有很多, 如此处理之后, 自然也会小的多. 当然, 这也存在这一定的局限性, 重复内容中间不能被隔开.

这是一种压缩的方式, 处理重复数据.

方案二

再上一个数字串: 123456-78-123456-987-12345678

从我在这个字符串中打的波折号标记, 大概就能猜到该如何处理了吧. 后面的内容与前面的相同, 即重复数据. 那就可以去前面抄啊. 此数字串的处理方式如下: 123456 78 (返回8个, 复制6个) 987 (返回17个, 复制8个) 当然, 真正压缩后的数字串后没有这一坨中文, 以一个标志编码来表示, 咱就假设是r(return) 和 c (copy)吧. 那上面的数字串就变成了这样: 123456-78-r8c6-987-r17c8

这里有个很有意思的地方, 回忆一下方案一的20个1. 用这种copy 方式也能表示: 1r1c19. 往回数1个, 复制19个, 虽然前面只有一个数字, 但是随着复制, 长度是会变化的, 复制一个, 长度就对应变长, 就又可以复制新的一位了, 以此类推. 如何, 有意思吧.

这也是一种压缩的思路, 向前复制数据.

方案三

这里为了方便说, 需要引用一下字母了.

看这个字符串: aaaaaaaaaaaaabc.

每个字母为了存储都需要进行编码, ASCII 编码下: a(97), b(98), c(99). 每个字母两位数, 那这个长度15的字符串就需要: 15*2=30位数字表示. 想必已经发现了, 此字符串字母 a 大量出现, 如果字母 a 能够用一位数字表示, 那整体长度就小得多了. 那我用9来表示 a 不就行了?

并不是, 如果你不做特殊标志的话, 计算机并不能分辨出98 应该是 9和8, 还是98. 所以, 需要有个标志, 比如, 以7开头的, 说明是1位编码, 以2开头的都是三位编码等等.

这个就厉害了, 是不是看出了什么, 没有错, 正是大名鼎鼎的哈夫曼编码. 将使用频率更高的内容使用更短的编码表示, 代价就是用较长的编码表示频率较低的内容. 对于哈夫曼编码就不多说了, 这玩意能单独写一篇.

你以为哈夫曼编码只能用来压缩文本文档? no. 它只需要是一个二进制串即可. 毕竟文本文档写到磁盘中也不过是二进制串. 你可以将二进制文件中的每块(比如2个字节)想象为上面的字母, 就可以直接使用哈夫曼编码进行处理了.

ZIP 压缩格式

zip 压缩文件是日常使用中较为常见的压缩格式了, 它就是使用了上面的方案二方案三进行压缩处理的结果. 其压缩步骤如下:

  1. 将文件使用方案二将大部分重复内容去掉.
  2. 将步骤一的处理结果, 通过哈夫曼编码进行处理, 用较短的编码表示频率较高的内容. 当然, 在这个步骤需要生成并记录一个编码对照表, 毕竟每个文件的高频率内容是不同的.
  3. 将步骤二中的结果直接输出保存到zip文件中, 包括编码表(毕竟还要解压嘛). 完成

据说, 在步骤二上会有些优化处理, 将文件分为多个不同的小块, 针对不同的小块单独进行编码, 以此实现不同文件的高效压缩.

其他

当然, 不仅仅是文件的 zip 压缩, 包括在很多网络传输中, 为了减少传输的包体积, 也会将文件进行压缩后再发送.

有损压缩

上面的无损压缩, 在将压缩文件解压后, 能够完全恢复压缩前的文件. 虽然已经很好了, 但是有损压缩的压缩文件要比它小很多, 当然代价就是无法还原. 不要以为没有用哦. 还记得在线看视频时, 会根据当前网速, 选择标清 高清 超清 等格式, 清晰度越低, 对应消耗的流量就越少.

对于有损压缩 就需要针对不同的文件进行不同的处理了. 咱也没有看, 咱也不敢说. 就简单举个例子.

图片压缩

比如一张 1080*1080 分辨率的图片, 为了记住图片上的每个像素点, 就需要 1080*1080 个内容来保存. 这里, 如果将相邻的两个像素点, 统一使用左侧的保存, 将右侧的丢掉, 也就是每两列像素丢掉一列, 整体的大小就减少一倍了. 当然, 相对应的, 图片的清晰度也会下降.

当然, 这种直接丢弃的方式有些粗暴了, jpeg的压缩方式据说不错, 不过我还没有看. 至于其他的视频啊, 音频啊, 都有吧. 嗯, 我想.

总结

在数据的无损压缩上, 思想基本就是减少重复的数据, 不管是重复数据复制, 还是哈夫曼编码都可以说是围绕着这个思想来的.

在看过压缩编码之后, 让我想起了之前看到的纠错码. 纠错码是怎么处理的? 往原来的数据中添加内容, 通过数据冗余来进行纠错, 而压缩呢? 将源文件中的数据通过转换使得其体积减小. 有点意思, 就像一个事情的正反两面, 没有孰是孰非, 就看你怎么去用它了.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

何为真何为假

还记得第一个提出日心说的人是谁么? 没错, 哥白尼. 但是在那个年代, 所有人都认为太阳围绕着地球转的年代. 哥白尼的发现打破了大家的常识, 甚至于有过了很多年, 日心说才逐渐被大众所接受. 即使到了现在, 生活中仍然留有地心说的影子, 比如"日出" “日落” 等等, 就…

TCP 三次握手的意义

概述 在网络的传输层协议中, 存在着两大悍将: TCP 和 UDP . 从前, 我傻傻的以为自己对他们虽谈不上精通, 但还是知道的, 但是, 我错了, 我被自己问住了, 我傻了. 啥也不是. UDP (这里为了介绍简单, 就不提数据在传输过程中的失真(纠错码)等情况了. 简单介绍一下, TCP才是今天…

随机数是如何生成的

引出 在现实中, 会有抛硬币猜正反的操作, 硬币要么是正, 要么是反, 在揭晓之前, 我们谁也不知道它现在的状态. 而这, 是因为其中存在着很大的不确定因素, 如抛硬币的力度、抛硬币的角度、接硬币的力度和角度、硬币的重量、当前风速等等. 但是在计算机中, 要想生成一个随机数,…

GO 文档笔记

前言 最开始写 GO 的时候, 发现方法的注释并不支持param, return等参数, 搞得我都不知道该如何给自己的方法写文档说明了. 而且网上搜了搜也没有搜到教程, 甚是郁闷. 今天找到了GO内置的文档工具: godoc. (我用的1.14.3版本貌似不是自带工具了, 需要安装(配置代理): go get g…

长整数的乘法运算

概述 都知道, 计算机中存储整数是存在着位数限制的, 所以如果需要计算100位的数字相乘, 因为编程本身是不支持存储这么大数字的, 所以就需要自己实现, 当然了, 各个编程语言都有大数的工具包, 何必重复造轮子, 但我还是忍不住好奇他们是如何实现的, 虽然最终没有翻到他们的底层…

如何将数字转换成口语中的文本串

概述 今天突发奇想, 写一个将数字转换成中文字符串的函数. 并不是将 1234 转成 1234 , 而是将 1234 转成 一千二百三十四. 本来以为很简单, 写下来之后发现还是有些坑的. 尝试 因为我是在写完最终版本, 回过头来整理的这篇文章, 所以中间很多尝试的步骤会有所遗漏. 以下简单…

设计模式故事会

想着用讲故事的方式对各个设计模式进行一个稍微形象一些的描述. 当然, 某些因为没有想到特别好的例子, 可能比喻的并不是那么的恰当, 望赐教. 绞尽脑汁啊, 尽力贴近设计模式其本来的意图. 主要为了加强一些自己对设计模式的理解. 进入正题: 小王是一名心怀梦想的90后青年, 他独…

有了 elseif 为什么还要 switch case

引出 你有没有想过既然有了if elseif, 为什么还要设计一个switch case的语法出来呢? 按理说, 一个语言的设计角度来说, 关键词越少越好吧, 而且多出来一种选择分支也没有看出太大用处. 以下几种switch case均可以写成if else的形式(java 代码): // 形式一 switch(a){case 1:…

计算矩阵中全1子矩阵的个数

前言 最近被我大哥安利了一道算法题, 这道题说难, 还不至于我做不出来, 说简单吧, 我还想不到最优解, 等把最优解告诉我之后, 我还正好能理解. 我甚至曾经怯怯的认为, 这题就是我哥专门给我找的, 嘿嘿, 心中说不出的小欢喜. 题来了, 此题出自力扣, 原题链接: https://leetco…

GO 的方法集

前言 之前在写 GOdemo 的时候, 写了这么一段程序(大概意思): package maintype Test struct { }func (test *Test) print() {println("test fun") }func main() {Test{}.print() }结果一编译就报错了: cannot call pointer method on Test literal 差不多意思是不…

GO 切片实力踩坑

概述 GO 语言的切片这两天用了用, 可以支持切割数组的中间部分. 但今天使用中, 出了 bug, 查了半天, 发现是切片的问题, 简单写个 demo 复现当时的情况: package mainimport "fmt"func main() {a : []int{1, 2, 3, 4, 5}b : a[2:4]b[0] 9fmt.Println(a) }你以为输…

搭建本地 HTTPS 环境

前言 之前写自己的网站时, 申请过免费的https证书. 最近想在自己本地搭一个, 结果忘了当初证书是怎么来的了. 本来想着去申请个免费的证书, 但想了想, 我只需要在自己本地能使用就行了, 我自己的环境, 那当然是我说了算了. 只要能够将证书构造出来, 安装到本地就可以识别了. 搜…

《人人都是产品经理》读后感

之前读书, 一般看的都是技术、算法、数学、哲学这些方面的, 为什么突然想看这本书呢? 身为一个开发人员, 每天打交道最多的, 除了开发和测试, 就是产品了. 还记得我刚来公司的时候, 在和产品的沟通过程中, 听到最多的话估计就是: 你要懂产品, 你懂了就不会做错. 确实有很多需求…

nginx 端口转发

概述 这两天在写 go 项目, 一个 HTTP 服务器. 之前写的是 php 项目, nginx 监听80端口, 根据域名将请求分配给不同项目. 现在换了 go, 自然也想延续这个操作, 毕竟都是跑在同一台服务器上. 那么问题来了, 我的nginx 监听80端口的同时, go 服务器是无法同样监听80端口的. 这该如…

2020-08-20

前段时间有些迷茫, 有时看着自己写的代码感觉就像一坨屎, 有时写了一段逻辑总是感觉有问题, 测了一遍又一遍, 逻辑也要理好几次. 就像是进入了一种不可描述的状态, 这感觉让我很不自在. 敲代码的时间说长不长, 说短不短, 从大二开始, 到现在也小四年了, 还没有碰到过这种情况. …

beego 优雅重启

前言 最近在写 go 的项目, http 用的 beego 框架. 因为 go 不想 php, 每次代码改动都需要重启服务, 所以代码发上线之后, 如何重启服务就成了一个问题. 如果强行重启的话, 不光在重启期间的所有访问都被拒绝了, 而且在杀掉进程的时候处理中的请求也挂了. 对于一个向用户正常提…

由 go orm 引发的探索

前言 今天遇到了一个 bug, 是 golang 的orm导致的. 使用了gorm框架. 通过实现Scan与Value可以将数据库中的 json 内容解析出来, 免除了 字符串再解码的步骤. 当时报错的代码大概是这样的: type TestContent struct {Id intContent Content // 数据库中的 json 结构 }type Con…

MySQL 数据恢复

MySQL 数据恢复 前言 前两天因为没注意的误操作, 直接把某个数据表清掉了, 心慌慌. 怪自己学艺不精, 当时整了一下午也没把数据找回来. 当晚回来闭关研究, 终于在凌晨1点多整出来了, 特此记录, 以备不时之需. 对于 MySQL 数据的备份, 主要有两种: 全量备份和增量备份. 全量…

码云 Pages 搭建

因为一直在写博客, 就向着搭个 GithubPages 来展示, 一直都听说别人用它来搭建个人博客, 但一直停留在听说的阶段. 最近想着没事搞一搞, 也看看它到底是个什么东东. 不过咱一个写中文博客的, 就想着在码云上搭一个, 顺便还能被百度收录, 嘿嘿. 说干就干, 开搞. (Pages 服务只能…

crontab 指令笔记

前言 之前有个定时任务, 需要每天的9点和21点定时跑. 当时我是这么写的: 0 9 * * * XXX 0 21 * * * XXX当时经过高人指点, 发现这两条命令可以写成一条: 0 9,21 * * * XXX好羞耻… 于是, 我决定整理一篇crontab的语法. 防止下次再出现这尴尬的场景… 指令 命令行 crontab…