数据压缩算法实现
来源:互联网 发布:c语言定义二维数组 编辑:程序博客网 时间:2024/05/22 10:47
实验目的
利用香农-费诺编码、霍夫曼编码、LZ编码、算术编码实现数据压缩
实验原理
1、香农-费诺编码
首先,将信源符号以概率递减的次序排列进来,将排列好的信源符号划分为两大组,使两组的概率和近于相同,并各赋予一个二元码符号“0”和“1”。然后将每一大组的信源符号再分成两组,使同一组的两个小组的概率和近于相同,并又分别赋予一个二元码符号。依次下去,直至每一个小组只剩下一个信源符号为止。这样,信源符号所对应的码符号序列则为编得的码字。译码原理,按照编码的二叉树从树根开始,按译码序列进行逐个的向其叶子结点走,直到找到相应的信源符号为止。之后再把指示标记回调到树根,按照同样的方式进行下一序列的译码到序列结束。如果整个译码序列能够完整的译出则返回成功,否则则返回译码失败。2、霍夫曼编码
霍夫曼编码属于码词长度可变的编码类,是霍夫曼在1952年提出的一种编码方法,即从下到上的编码方法。同其他码词长度可变的编码一样,可区别的不同码词的生成是基于不同符号出现的不同概率。生成霍夫曼编码算法基于一种称为“编码树”(coding tree)的技术。算法步骤如下:
(1)初始化,根据符号概率的大小按由大到小顺序对符号进行排序;
(2)把概率最小的两个符号组成一个新符号(节点),即新符号的概率等 于这两个符号概率之和;
(3)重复第2步,直到形成一个符号为止(树),其概率最后等于1;
(4)从编码树的根开始回溯到原始的符号,并将每一下分枝赋值为1,上 分枝赋值为0。3、LZ编码
在LZ算法中,离散信源的输出序列分解成长度可变的分组,码段(phrases)。每当信源输出字符组在最后位置加上一个字符后,与前面的一有已有码段都不相同时,把它作为一种新的码段引入。将这些码段列入一个位置词典,用来记载有码段的位置。在对一个新的码段编码时只要指出字典中现有码段的位置,把新的字符附在后面即可。4、算术编码
算术编码的编码对象是一则消息或一个字符序列,其编码思路是将消息或字符序列表示成0和1之间的一个间隔上的一个浮点小数。 在进行算术编码之前,需要对字符序列中每个字符的出现概率进行统计,根据各字符出现概率的大小,将每个字符映射到[0 ,1]区间上的某个子区间中。然后,在利用递归算法,将整个字符序列映射到[0,1]区间上的某个间隔中。在进行编码时,只需从该间隔中任选一个小数,将其转化为二进制数。 符号序列越长,编码表示他的间隔就越小,表示这个间隔所需的二进制位数就越多,编码输出的码字就越长。
在进行编码过程中,随着信息的不断出现,子区间按下列规律减小:
a.新子区间左端=前子区间左端+当前子区间左端×前子区间长度
b.新子区间长度=前子区间长度×当前子区间长度实验内容
1、对于给定的信源的概率分布,用香农-费诺编码实现压缩
2、对于给定的信源的概率分布,用霍夫曼编码实现压缩
3、对于给定的信源的概率分布,用LZ编码实现压缩
4、对于给定的信源的概率分布,用算术编码实现压缩实验过程
1、香农-费诺编码
function c=shannon(p)[p,index]=sort(p) p=fliplr(p) n=length(p) pa=0 for i=2:n pa(i)= pa(i-1)+p(i-1)end k=ceil(-log2(p)) c=cell(1,n) for i=1:n c{i}='' tmp=pa(i) for j=1:k(i) tmp=tmp*2 if tmp>=1 tmp=tmp-1 c{i}(j)='1' else c{i}(j)='0' end endend c = fliplr(c) c(index)=c
2、霍夫曼编码
function c=huffman(p)n=size(p,2)if n==1 c=cell(1,1) c{1}='' returnend[p1,i1]=min(p)index=[(1:i1-1),(i1+1:n)]p=p(index)n=n-1[p2,i2]=min(p)index2=[(1:i2-1),(i2+1:n)]p=p(index2);i2=index(i2)index=index(index2)p(n)=p1+p2c=huffman(p)c{n+1}=strcat(c{n},'1')c{n}=strcat(c{n},'0')index=[index,i1,i2]c(index)=c
3、LZ编码
function LZmain()clc;fid=fopen('source.txt','r');seq=fread(fid);fclose(fid);seq=reshape(seq,1,length(seq));if ~isempty(seq) [entropy]=Entropy(seq); [dictionary codelength]=LZcode(seq); avglength=((codelength*length(dictionary))/length(seq)); disp(strcat('Entropy = ',num2str(entropy))); disp(strcat('Code length = ',num2str(codelength))); disp(strcat('Average length = ',num2str(avglength))); display('Encoded Sequence : Look encode.txt.'); enseq=LZencode(dictionary); fiden=fopen('encode.txt','w'); en=fwrite(fiden,enseq); fclose(fiden); display('Decoded Sequence : Look decode.txt.'); deseq=LZdecode(dictionary); fidde=fopen('decode.txt','w'); de=fwrite(fidde,deseq); fclose(fiden); else display('Empty Sequence....');endendfunction [dictionary codelength]=LZcode(seq)l=length(seq);dictionary(1).sym=seq(1);k=2;index=0;str='';for i=2:l str=[str seq(i)]; for j=1:(k-1) index=0; if strcmp(dictionary(j).sym,str) index=1; break; end end if (index==0) dictionary(k).sym=str; k=k+1; str=''; endend codelength=fix(log2(k-1))+1;for i=1:(k-1) dictionary(i).code=dec2bin((i-1),codelength); endendfunction decode=LZdecode(dictionary)ld=length(dictionary);decode='';for i=1:ld decode=[decode dictionary(i).sym];endendfunction encode=LZencode(dictionary)ld=length(dictionary);encode='';for i=1:ld encode=[encode dictionary(i).code];endendfunction [entropy]=Entropy(seq)alpha(1)=seq(1);prob(1)=1;l=length(seq);k=2;for i=2:l idx=find(alpha==seq(i)); if isempty(idx) alpha(k)=seq(i); prob(k)=1; k=k+1; else prob(idx)=prob(idx)+1; endendprob=prob./l;entropy=-prob.*log2(prob);entropy=sum(entropy(:));end
4、算术编码
function arithmeticS = input('请输入信源符号='); P = input('请输入信源概率向量P=');str = input('输入编码的字符串=');l = 0;r = 1;d = 1;n = length(str);n_S = length(P);%**********处理第一个字符***********%for i=1:n flag = 0; for k = 1:n_S if str(i)==S(k) m=k; flag =1; break; end end if flag ==0 error('非信源字符'); end %*********当前单个字符的左、右端以及长度处理**************% pl = 0; pr = 0; for j = 1:m-1 pl = pl + P(j); %左端 end pr = pl+P(m); %右端 pd = pr-pl; %子区间长度 %*********新子区间的左、右边界以及长度处理**************% if i == 1 %首字符 l = pl; r = pr; d = pd; else %算术编码规则 l = l+d*pl; d = d*pd; r = l+d; end strl = strcat('第',int2str(i),'个符号的间隔左右边界:'); disp(strl); format long; disp(l);disp(r);endstrl = strcat('符号的间隔左右边界:');disp(strl);format long;disp(l);disp(r);end
- 实验结果
>> clear; clc;>> P=[0.3 0.25 0.16 0.14 0.1 0.05];>> c1=shannon(P);c1 = '00' '01' '100' '101' '1101' '11110'>> c2=huffman(P);c2= '11' '01' '00' '100' '1011' '1010'>> clear; clc;>> arithmetic请输入信源符号='abcdef'请输入信源概率向量P=[0.3 0.25 0.16 0.14 0.1 0.05]输入编码的字符串='adbecf'第1个符号的间隔左右边界: 0 0.300000000000000第2个符号的间隔左右边界: 0.213000000000000 0.255000000000000第3个符号的间隔左右边界: 0.225600000000000 0.236100000000000第4个符号的间隔左右边界: 0.234525000000000 0.235575000000000第5个符号的间隔左右边界: 0.235102500000000 0.235270500000000第6个符号的间隔左右边界: 0.235262100000000 0.235270500000000符号的间隔左右边界: 0.235262100000000 0.235270500000000>> clear; clc;>> LZmainEntropy =5.8172Code length =8Average length =4.6126Encoded Sequence : Look encode.txt.Decoded Sequence : Look decode.txt.
- 数据压缩算法实现
- 一种整数数据压缩存储的算法实现
- 【数据压缩】LZ78算法原理及实现
- 一种整数数据压缩存储的算法实现
- 数据压缩算法
- 数据压缩算法
- 数据压缩算法:旋转门算法(SDT)的C#实现
- (转)GPS定位数据压缩算法的设计与实现
- java实现数据压缩的哈夫曼(Huffman)算法
- 数据压缩实验三——霍夫曼编解码算法实现
- 无损数据压缩LZW算法——C++实现
- 【转】数据压缩算法-LZ77
- BWT数据压缩算法
- 通用数据压缩算法简介
- java数据压缩小算法
- 数据压缩算法综述
- 深入解析数据压缩算法
- LZW数据压缩算法
- kubernetes容器启动详解
- 最全HTTPS扫肓贴
- URAL 1277 网络流最小割 解题报告
- sublime text3 的插件下载及汉化
- Java线程同步工具-CyclicBarrier
- 数据压缩算法实现
- request.getRequestURI()的使用
- maven
- JSP内置对象的使用:request,cookie,session
- Android启动流程(一)
- 看雪ctf2017第一题详解
- Properties配置文件数据加密
- Java抽象类
- shell-grammar