Huffman编码MATLAB实现

**************主函数:************************

%Huffman编码
clear;clc;close all;
[word,prob]=statistics(); %对文本中的信息进行统计
huff=Code(prob); %编码

for i=1:length(prob)
  len(i)=length(find(abs(huff(i,:))~=32));
  %检测编码长度并进行标记
end

ave=sum(prob*len')   %计算平均码长
HX=sum(prob.*(-log2(prob)))  %计算信源熵
efficiency=HX/ave  %计算编码效率
r=1-efficiency   %计算冗余度
————————————————
版权声明:本文为CSDN博主「路遇春山」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_56647551/article/details/127752235

编码主函数

输入文本文件xx.txt

*****************字符统计************************

 

function [word,prob] = statistics()  %统计文档中信源及个数
data=textread('D:\desktop\Huffman\xx.txt','%s', 'whitespace','');
x=cell2mat(data);
x=x';
tab=tabulate(x);
w=char(tab(:,1));  %字符表
dimension=size(w);
word(1:dimension(1),1)=char(tab(:,1));
word(dimension(1)+1,1)=' ';
for i=1:dimension(1)+1
    count(i)=length(find(x==word(i)));
end
prob=count/sum(count); %各字符的概率

end
————————————————
版权声明:本文为CSDN博主「路遇春山」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_56647551/article/details/127752235

 

*********************编码函数code()*********************

function huff = Code(prob)
%进行Huffman编码
n=length(prob);
p=prob
loca=zeros(n-1,n);
%loca用于记录每行最小两概率叠加后概率的排列次序
for i=1:n-1
    [p,index]=sort(p)      %进行概率值排序
    loca(i,:)=[index(1:n-i+1),zeros(1,i-1)]     %每一次排序求和后都会少一个概率值,对有值的赋予排列次序,其余赋0
    p=[p(1)+p(2),p(3:n),1]    %对经过求和处理的概率第一项赋两最小概率的和值,对3-n项概率照搬,其余概率赋1
end
for i=1:n-1   %循环生成一个N-1行、n^2列数组C,每行可看作n个段,每段长为n,记录一个码字(每个码字的长度不会超过n)
    code(i,1:n*n)=blanks(n*n)
end

code(n-1,n)='0' % 给code矩阵的N-1行的第一个段赋值0
code(n-1,2*n)='1' % 第二个段赋值1。(这两个码字对应编码中最后相加为一的两个概率)
for i=2:n-1   %主要的程序,循环N-2次
    code(n-i,1:n-1)=code(n-i+1,n*(find(loca(n-i+1,:)==1))-(n-2):n*(find(loca(n-i+1,:)==1)))
    code(n-i,n)='0' %在分支的第一个元素最后补0
    code(n-i,n+1:2*n-1)=code(n-i,1:n-1)
    code(n-i,2*n)='1' %在分支的第一个元素最后补1
                %每一行值都从下一行值得到,找到在下一行码字中相加本行最小两个概率得到的概率的对应码字,
                %本行两个最小概率对应码字分别为此码字最后加“0”,加“1”
    for j=1:i-1
        code(n-i,(j+1)*n+1:(j+2)*n)=code(n-i+1,n*(find(loca(n-i+1,:)==j+1)-1)+1:n*find(loca(n-i+1,:)==j+1))
    end
end


for i=1:n
    huff(i,1:n)=code(1,(find(loca(1,:)==i)-1)*n+1:find(loca(1,:)==i)*n)
end
end
————————————————
版权声明:本文为CSDN博主「路遇春山」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_56647551/article/details/127752235
********************* 输出码书**********************
fid=fopen('codeBook.txt','w+');
for i=1:length(prob)
    fprintf(fid,'%s',word(i));
    for j=1:length(word)
        fprintf(fid,'%s',huff(i,j));
    end
    fprintf(fid,'\n');
end
fclose(fid);
————————————————
版权声明:本文为CSDN博主「路遇春山」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_56647551/article/details/127752235

输出码书

*********************输出二进制比特流**************************
huffcode=[];
for i=1:length(x)  
    temp=huff(find(word==x(i)),:);  %temp存放当前字符对应的Huffman编码
    loc=find(abs(temp)~=32);  %找到不是空格的第一个0或者1
    new=temp(loc(1):length(word));  %取出码字
    huffcode=[huffcode,new] %拼接码字
end
fid=fopen('codeFile.txt','w+');
fprintf(fid,'%s\n',huffcode);
fclose(fid);

****************输出每个码字码长********************
lenth=[];
for i=1:length(x)  
    lenth=[lenth,len(find(word==x(i)))];
end
fid=fopen('Length.txt','w+');
for i=1:length(lenth)
    fprintf(fid,'%d',lenth(i));
end
fclose(fid);
————————————————
版权声明:本文为CSDN博主「路遇春山」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_56647551/article/details/127752235

 

编码结果

计算压缩效率:

 

读入codeFile.txt,编写霍夫曼编码的译码程序,进行译码,验证编码正确性。

 

***************Huffman译码********************

%Huffman译码
clear;clc;close all;
code=textread('codeFile.txt','%c');
book=textread('codeBook.txt','%s');
n=length(book);
book(n+1)=book(n);
% book(n)=cellstr(' ');
word_code=zeros((n+1)/2,(n+1)/2);
word_code=char(word_code);
for i=1:(n+1)/2
    word_code(i,:)=blanks((n+1)/2);
end

%存放字符字典
for i=1:(n-1)/2 
    word(i)=cell2mat(book(2*(i-1)+1));
end
word((n+1)/2)=' ';

for i=1:(n+1)/2 %存放字符码字字典
    word_code(i,1:length(cell2mat(book((2*i)))))=cell2mat(book((2*i)));
end
%开始译码
for i=1:(n+1)/2 %计算每个码字的长度
    temp=find(word_code(i,:)==32);
    len(i)=temp(1)-1;
end
unit=[]
decoding=[]
for i=1:length(code)
    unit=[unit,code(i)]
    for j=1:(n+1)/2
        if length(unit)==len(j)
              if double(sum(unit==word_code(j,1:len(j))))==length(unit)
                  decoding=[decoding,word(j)]
                  unit=[]
              end
        end
        
    end
end
%输出译码结果
fid=fopen('Decode.txt','w+');
fprintf(fid,'%s\n',decoding);
fclose(fid);
————————————————
版权声明:本文为CSDN博主「路遇春山」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_56647551/article/details/127752235

 译码代码如上

译码结果与原文本一致

接下来设计交互界面(使用MATLAB自带的Appdesigner)

在输入栏中输入所需编码的文本文件名,点击Button对.txt文件所在文件夹进行选择,即可对文件进行霍夫曼编码,码书显示于表格,编码结果(2进制比特流)保存于同一文件夹下的’AppCode.txt’。

function ButtonPushed(app, event)
            clc;
            srcDir=uigetdir('','选择需要进行编码的文本');
            loc=app.EditField_2.Value;
            location=fullfile(srcDir,[loc]);
            [word,prob]=statistics_App(location); %对文本中的信息进行统计
            huff=Code(prob); %编码
            chuff=cellstr(huff);
            cword=cellstr(word);
            xlswrite('D:\desktop\MATLAB\zyh\Huffman\Book.xlsx',[cword,chuff]);
            t=readtable('Book.xlsx');
            app.UITable.Data=[cword,chuff];
            s = uistyle('HorizontalAlignment','center');
            addStyle(app.UITable,s,'table','');
            
            data=textread(location,'%s', 'whitespace','');
            x=cell2mat(data);
            huffcode=[];
            for i=1:length(x)  
                temp=huff(find(word==x(i)),:);  %temp存放当前字符对应的Huffman编码
                loc=find(abs(temp)~=32);  %找到不是空格的第一个0或者1
                new=temp(loc(1):length(word));  %取出码字
                huffcode=[huffcode,new] %拼接码字
            end
            fid=fopen('AppCode.txt','w+');
            fprintf(fid,'%s\n',huffcode);
            fclose(fid);
        end
    end


————————————————
版权声明:本文为CSDN博主「路遇春山」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_56647551/article/details/127752235

回调函数如上 

 

输出比特流展示 

 哈夫曼编码(Huffman Coding)是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。 Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长 度最短的码字,有时称之为最佳编码,一般就叫作Huffman编码。 以哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。 在计算机信息处理中,“哈夫曼编码”是一种一致性编码法(又称"熵编码法"),用于数据的无损耗压缩。这一术语是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。这种方法是由David.A.Huffman发展起来的。 例如,在英文中,e的出现概率很高,而z的出现概率则最低。当利用哈夫曼编码对一篇英文进行压缩时,e极有可能用一个位(bit)来表示,而z则可能花去25个位(不是26)。用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个位。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值