使用前将建立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('概率');
标签:end,fwrite,selected,译码,length,MATLAB,shuju,huffman,txt2 From: https://www.cnblogs.com/bbhhh/p/17909000.html