哈夫曼压缩和矩阵压缩存储

对于数组的压缩存储,一维数组主要使用哈夫曼压缩,多维数组主要采用矩阵压缩的形式,对特殊矩阵和系数矩阵进行压缩。

哈夫曼压缩

哈夫曼压缩是由哈夫曼树推广而来的,是哈夫曼编码的重要应用。哈夫曼树 ─ 即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。对于重复较大的数据,哈夫曼可以在压缩后,体现出很强的性能,但是如果数据重复量不大,哈夫曼压缩就无法展现出自己的性能,甚至可能会适得其反。
哈夫曼压缩是个无损的压缩算法,一般用来压缩文本和程序文件。哈夫曼压缩属于可变代码长度算法一族。意思是个体符号(比如,文本文件里的字符)用一个特定长度的位序列替代。
因此。在文件里出现频率高的符号,使用短的位序列。而那些非常少出现的符号。则用较长的位序列。

哈夫曼编码
哈夫曼编码是一种一致性编码法(又称“熵编码法”),用于数据的无损耗压缩。它是根据数据出现的次数进行排序,出现最多的的数字编码长度最短,从而实现压缩存储,在压缩过程中不会丢失信息熵。并且能够证明 Huffman 算法在无损压缩算法中是最优的。
在目前的数据传中,需要将传送的文字转换为由二进制字符组成的字符串,同时希望总长尽可能的短。如果对每个字符设计长度不等的编码,且让传送的字符中出现次数最多的字符串采用尽可能短的编码,就能够使得总长度降到最低。但是每个字符都有多种译法,想要得到长度不等的编码,必须满足一个条件:每个字符的编码都不是另一个字符的编码前缀,这种编码也叫做“前缀编码

哈夫曼树的构建

  1. 根据给定的n个权值{w1,w2,…,wn}构成二叉树集合F={T1,T2,…,Tn},其中每棵二叉树Ti中只有一个带权为wi的根结点,其左右子树为空.
  2. 在F中选取两棵根结点权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为左右子树根结点的权值之和.
  3. 在F中删除这两棵树,同时将新的二叉树加入F中.
  4. 重复2、3,直到F只含有一棵树为止.(得到哈夫曼树)
  5. 把这棵树上的根节点定义为 0 (可自行定义 0 或 1 )左边为 0 。右边为 1 。

这样就能够得到每个叶子节点的哈夫曼编码了。
举个栗子:如权值集合W={7,19,2,6,32,3,21,10 }构造赫夫曼树的过程。

在这里插入图片描述
选定两个最小权值的节点将他们组成二叉树
在这里插入图片描述
组成新的权值队列,继续寻找两个权值最小的组成二叉树
在这里插入图片描述
在这里插入图片描述
继续此流程,最终构建一个二叉树,再使用左0右1即得到每个节点的编码
在这里插入图片描述

  • 权值为2节点的编码为 10000 权值为3节点的编码为 10001
  • 权值为6节点的编码为 1001 权值为7节点的编码为 1010
  • 权值为10节点的编码为 1011 权值为19节点的编码为 00
  • 权值为21节点的编码为 01 权值为32节点的编码为 11

哈夫曼压缩流程

Huffman编码生成步骤

  1. 扫描要压缩的文件,对字符出现的频率进行计算。
  2. 把字符按出现的频率进行排序,组成一个队列。
  3. 把出现频率最低(权值)的两个字符作为叶子节点。它们的权值之和为根节点组成一棵树。
  4. 把上面叶子节点的两个字符从队列中移除,并把它们组成的根节点增加到队列。
  5. 把队列又一次进行排序。反复步骤 3、4、5 直到队列中仅仅有一个节点为止。
    举个栗子:有一串“caadbaaaeccdfacabaaaaca”,进行Huffman编码和解码。

编码:

  1. 频率统计 f:1 e:1 d:2 c:5 b:2 a:12
  2. f与 e作为叶子结点,其根节点为_2 。 此时,新的频率表为:_2 d:2 c:5 b:2 a:12
    d与_2作为叶子结点,其根节点为_4 。 此时,新的频率表为:c:5 b:2 _4 a:12
    b与 _4作为叶子结点,其根节点为_6 。 此时,新的频率表为:c:5 _6 a:12
    c:5与_6作为叶子结点,其根节点为_11 。 此时,新的频率表为: _11 a:12
    _11与 a:12作为叶子结点,其根节点为_23 。
    哈夫曼树构造完成, 结束。
  3. 左子树标0,右子树标1。如下图所示:
    在这里插入图片描述
    Huffman编码表
    a:0 c:11 b:100 d:1010 e:10110 f:10111
    那么“caadbaaaeccdfacabaaaaca”的编码为“1100101010000010110111110101011101101000000110”。

解码:
读取第一位‘1’,搜索Huffman表,找不到。继续读下一位“11”,找到c,此时对应字符‘c’。
清零,继续读第一位“0”,对应‘a’。
清零,继续读第一位“0”,对应‘a’。
清零,继续读第一位“1”找不到,继续读下一位“10”找不到,继续读“101”找不到,再读“1010”对应‘d’。
继续清零,继续读第一位‘0’,直至读到“101”,对应‘b’。
… …
读到最后,得“cdbedfaabca”。

矩阵压缩

特殊矩阵

对称矩阵
对称矩阵: 矩阵中以主对角线为轴进行对称,存在 a[i][j] = a[j][i] 特点的方阵称之为对称矩阵。
在这里插入图片描述
该矩阵无压缩存储时,我们需要使用n * n个存储空间,但是由于它是对称的,因此我们可以只保存矩阵的上三角或者下三角,这样我们就可以得到整个矩阵模型,而使用的存储空间也会缩小到将近一半。假设我们拥有一个n * n的对称矩阵,那么我们只需要 n(n+1)/2 个存储空间就可以将整个矩阵模型保存下来。
三角矩阵
三角矩阵分为上三角矩阵和下三角矩阵。
在这里插入图片描述
下三角矩阵的对角线右上方元素均为零。
在这里插入图片描述
上三角矩阵的对角线左下方元素均为零。
下三角矩阵的压缩方式同对称矩阵的压缩方式相同,矩阵内元素与数组元素的对应位置关系也是相同的。
所以对于下三角矩阵:当 i>=j 时,a[i][j] = arr[i*(i+1)/2+j];当 i<j 时,a[i][j] = 0;
对上三角矩阵进行压缩时:当 i<=j 时, a[i][j] = arr[i*(2*n-i+1)+j-i];当 i>j 时,a[i][j] = 0;
对角矩阵
除了主对角线元素不为零其余所有元素均为零的矩阵。
在这里插入图片描述
此类型的矩阵,只需要构建一个长度为 n 的数组 arr[] 保存对角线元素即可。
当 i==j 时,a[i][j] = arr[i];当 i != j 时,arr[i][j] = 0;
当然,这里的对角矩阵可以不符合定义,假设主对角线的上半部分值为 C,下半部分值为 D,那么可以构建一个长度为 n+2 的数组arr[] 保存对角线元素,同时最后两位保存C和D。
当i < j 时,a[i][j] = C;当 i == j 时,a[i][j] = arr[i];当 i > j 时,arr[i][j] = D;

稀疏矩阵

稀疏矩阵:稀疏矩阵是指含有大量零元素的矩阵。
在矩阵的压缩过程中,我们可以将这个条件拓宽一些,稀疏矩阵中的零元素我们也可以换做成其他的元素,但是必须满足一个条件,就是这个元素的数量必须是大量的。
三元组法
由于在稀疏矩阵中有某一个元素是大量存在的,其他元素分布并不规律,因此不但要保存下来元素的值,还要保存元素在矩阵中的位置信息。
在这里插入图片描述
三元组应该这样来表示:
A[][0] = 行坐标
A[][1] = 列坐标
A[][2] = 该位置的值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值