本代码灵感来自于百度上某篇使用sort()函数实现哈夫曼编码的文章,原文过于复杂。
于是本人按照逻辑重写过程得到下述代码,可谓思路清晰,方法简洁。由于试验的量也不是很大,所以性能或许不好?嗯……管他的呢
唯一难读的地方在于MAP函数的补全部分,但其实和哈夫曼编码最后自顶向下得到编码的过程逻辑一致。
sort()函数是MATLAB中比较方便的一个排序函数。
[A,B]=sort(C)
,其中C为乱序概率序列,可得:
1.A为C的升序序列
2.B为A对应数字在C中的原始位置
(1)由 A 我们可以得到C序列中 最小值 和 次小值 ,用于哈夫曼编码中最小值和次小值相加。
(2)由 B 可以知道两个值在原始序列中的位置,用于记录本次加法对应的“ 0 ”和“ 1 ”。
那么我们可以把它记录下来作为哈夫曼编码中加法合并的路径,记作MAP矩阵。
合并后的序列在原序列的基础上生成,两项的和统一赋值给较大值,较小值则赋一个用不到的极大值即可,此处用5。
[0.2 0.19 0.17 0.18 0.15 0.01 0.1]
--->[0.2 0.19 0.17 0.18 0.15 5 0.11]
反复操作后,即依次合并最小两项,得到合成的全路线如下:
补全所有的值后得到完整的MAP,倒着输出就可以
下面贴上完整的代码。
clc;clear;
p=[0.2 0.19 0.17 0.18 0.15 0.01 0.1];
n=length(p);
List=p;
Op_List=p;
Map=[];%Map用于进行huffman 编码,下面生成(n-1)*(n*n)的矩阵
for i=1:n-1
Map=[Map;blanks(n)];
end
for i=1:n-1
[Op_List,e]=sort(Op_List);% e 记录了原来的顺序
%e(1)e(2)就是合并的两个数,小的赋1大的赋0
Map(i,e(1))=\'1\';
Map(i,e(2))=\'0\';
%第一第二加到第二个,第一个作废
Op_List(2)=Op_List(1)+Op_List(2);
Op_List(1)=n;
%位置还原
Back_List=zeros(1,n);
for j=1:n
Back_List(e(j))=Op_List(j);
end
Op_List= Back_List;
end
x=n;y=n-1;%补全Map
for i=y:-1:1
for j=1:x
if Map(i,j)~=\' \'
for k=i-1:-1:1
if Map(k,j)~=\' \'
for b=1:x
if b~=j && Map(k,b)~=\' \'
Map(k+1:y,b)=Map(k+1:y,j);
end
end
end
end
end
end
end
Map
%输出
for j=1:n
fprintf(\' 概率:%.2f\',p(j));
fprintf(\' 哈夫曼编码: \');
for i=y:-1:1
if Map(i,j)~=\' \'
fprintf(\'%c\',Map(i,j));
end
end
fprintf(\'\n\');
end
请发表评论