MATLAB實現huffman編碼及譯碼


使用前將建立input.txt放在和該.m文件同一文件夾中運行即可
最后運行結果:
1.文本統計過后的信源空間
2.信源空間對應的柱狀圖
3.編碼結果
4.譯碼結果

clc;
close all;
clear all;

%數據讀取
txt=fopen('input.txt');
shuju=fscanf(txt,'%c');
%去重
selected_shuju=unique(shuju);
selected_shuju=selected_shuju';
%長度
len=length(selected_shuju);
%求出信源符號的個數
for i=1:len
    count(i)=length(strfind(shuju,selected_shuju(i)));
end
p=count./sum(count);
n=length(p);
q=p;







%構建概率矩陣
m=zeros(n-1,n);
for i=1:n-1%合並n-1次
    [q,e]=sort(q);%E是個行向量 值代表q中該位置的概率在原序列中的位置
    m(i,:)=[e(1:n-i+1),zeros(1,i-1)]; 
    %m的特點:第一行n個非零元素,逐行遞減,n-1行2個非零元素 
    q=[q(1)+q(2),q(3:n),1]; 
end







%構建編碼矩陣 
for i=1:n-1
    c(i,1:n*n)=blanks(n*n); %c矩陣特點 與m對應  每一個n塊對應一個概率的符號 第一行有n個 n-1行有2個 其余為空
end
%開始編碼 因為哈夫曼編碼不唯一 自規定概率小的賦值1 概率大的賦值0
c(n-1,n)='1'; 
c(n-1,2*n)='0'; 
for i=2:n-1
    %被合並的前兩個需要分配0和1
    index=find(m(n-i+1,:)==1);%下一行對應位置為1 則為該行較小的兩個概率合並以后的總概率
    c(n-i,1:n-1)=c(n-i+1,n*(index)-(n-2):n*index);%前綴是對應的合並后概率的編碼值 注意:1:n-1的維度和取的前綴的維度要一致
    c(n-i,n)='1'; 
    c(n-i,n+1:2*n-1)=c(n-i,1:n-1); %合並為同一個概率 前綴相同
    c(n-i,2*n)='0'; 
    
    %未合並的 從每一行第三個開始編碼 無需新分配0 1 直接繼承上一個節點的編碼
    for j=1:i-1
        index=find(m(n-i+1,:)==j+1);%從index=2開始到index=i結束 i=3 即n-3行 就是index從2到3
         c(n-i,(j+1)*n+1:(j+2)*n)=c(n-i+1,n*(index-1)+1:n*index);
    end
end 
for i=1:n
    index=find(m(1,:)==i);
    h(i,1:n)=c(1,n*(index-1)+1:index*n); %將與輸入概率對應的編碼放入h中
    is0=abs(h(i,:));%abs()將字符變為ASCII碼 空為32
    len(i)=length(find(is0~=32)); %非空符號的個數為碼長
end









disp('編碼結果');
[selected_shuju,h]
disp('平均碼長');
e=sum(p.*len)   %計算平均碼長
xinxiliang=sum(p.*log2(1./p));    %計算平均信息量
disp('平均信息量');
disp([num2str(xinxiliang),'bit/sym']);      
disp('編碼效率');
eta=(sum(p.*log2(1./p)))./e                        %計算編碼效率

%將結果寫入文件中
txt2=fopen('tongji_result.txt','w+','n','GB2312');
fwrite(txt2,"symbols:   ");
fprintf(txt2,'\n');
for i=1:length(selected_shuju)
    fwrite(txt2,selected_shuju(i));
    fwrite(txt2,':  ');
    fwrite(txt2,num2str(p(i)));
    fprintf(txt2,'\n');
end
fprintf(txt2,'\n');

fwrite(txt2,"Huffman_Result:  ");
fprintf(txt2,'\n');

for i=1:length(selected_shuju)
    fwrite(txt2,[selected_shuju(i)]);
    fwrite(txt2,':  ');
    for j=1:length(h)
        fwrite(txt2,h(i,j));
    end
    fprintf(txt2,'\n');
end
fwrite(txt2,'averge_lenth:  ');
fwrite(txt2,num2str(sum(p.*len)));
fprintf(txt2,'\n');
fwrite(txt2,'averge_bit:  ');
fwrite(txt2,[num2str(xinxiliang),'bit/sym']);
fprintf(txt2,'\n');
fwrite(txt2,'eta:  ');
fwrite(txt2,num2str(eta));
fclose(txt2);

%文本編碼和譯碼
%文本編碼結果
txt333=fopen('bianma_result.txt','w+');
RESULT=[selected_shuju,h];
for i=1:length(shuju)
    for j=1:length(selected_shuju)
        if shuju(i)==selected_shuju(j)
            for o=1:length(h)
                if h(j,o)~=' '
                    fwrite(txt333,h(j,o));
                end
            end
            fwrite(txt333,' ');
        end
    end
end
fclose(txt333);
%文本譯碼
txt444=fopen('yima_result.txt','w+');
txt333=fopen('bianma_result.txt','r');
bianma_code=fscanf(txt333,'%c');
s='';
plll=0
%開始譯碼:
for i=1:length(bianma_code)
   
    
    
    
    if bianma_code(i)==' '
        flag=1;
        for j=1:length(h)
            flag=1;
            for m=1:length(h)
                if(h(j,m)==' ')
                    plll=plll+1;
                    continue;
                end
                if(length(h)-plll~=length(s))
                    flag=0;
                    break;
                end
                for o=m:length(h)%比較每個字符串是否對應相等
                    if h(j,o)~=s(o-plll)
                            flag=0;
                    end
                end
            end
            plll=0;
            if(flag==1)
                fwrite(txt444,selected_shuju(j));
            end
        end
         s='';
    end
    
    
    
    
    if(bianma_code(i)~=' ')
        s=[s,bianma_code(i)];
    end
end
fclose(txt444);
fclose(txt333);
           





%數據可視化
x=1:length(selected_shuju);
bar(x,p)
set(gca,'XTick',1:length(selected_shuju))
%下面是x軸的刻度值
set(gca,'XTickLabel',selected_shuju(1:1:end))
title('信源符號——概率圖');
xlabel('信源符號');
ylabel('概率');


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM