我尝试根据示例实现算法:
“Shannon Fano”
根据这个决定,我必须得到A = 11,B = 101,C = 100,D = 00,E = 011,F = 010.但我得到A = 11 B = 101 C = 100 D = 01 E = 001 F = 000 这是我的代码:
Input parametrs: frequencies = [50, 39, 18, 49, 35, 24] и chars = [A, B, C, D, E, F]
OnClick: SearchTree(' ',' ', 1, charCount,Memo1);
procedure SearchTree(branch:char; full_branch:string; start_pos:integer; end_pos:integer; memo:TMemo);
var
dS:real;
i, m, S:integer;
c_branch:string;
x,y,j:integer;
begin
if (branch<>' ') then c_branch := full_branch + branch
else c_branch := '';
if (start_pos = end_pos) then
begin
memo.Lines.Add(chars[start_pos]+ ' = ' + c_branch);
exit;
end;
x:=0; y:=0;
i:=start_pos-1; j:=end_pos;
repeat
Inc(i);
x:=x+frequencies[i];
while ((x>=y) and (i<>j))do
begin
y:=y+frequencies[j];
Dec(j);
end;
m:=i;
until (i=j);
SearchTree('1', c_branch, start_pos, m,memo);
SearchTree('0', c_branch, m+1, end_pos,memo);
end;
提示我是否理解算法以及我的问题是什么?
答案 0 :(得分:3)
我不会尝试破译你的代码,但是为了它的价值,你在这里所做的并不是我理解Shannon-Fano编码的方式。
我必须马上承认,我从未亲自编写过一个(选择使用霍夫曼编码,为所有输入数据提供与所有输入数据相同或更好的压缩效果)。
以下是我认为应该根据您的样本数据构建Shannon-Fano代码的方法:
给定角色频率:
A B C D E F
50, 39, 18, 49, 35, 24 = 215 (ideal distribution = 215 / 2 = 107.5 to each start bit)
现在对频率进行排序:
A D B E F C
50, 49, 39, 35, 24, 18 = 215 (ideal distribution = 215 / 2 = 107.5 to each start bit)
现在找到此列表中的分割点,提供最少量的“错误”(浪费):
50 | 49 39 35 24 18 -- error (distance to ideal 107.5) = 57.5
50 49 | 39 35 24 18 -- error (distance to ideal 107.5) = 8.5
50 49 39 | 35 24 18 -- error (distance to ideal 107.5) = 30.5
因此,第一级的最佳分割点在49(D)和39(B)之间,这反过来意味着我们在左侧分支上有AD,在右侧分支上有BEFC。
由于左侧分支上只剩下两个字符,我们直接编码:
假设left为1且right为零,A变为11,D变为10.
然后所有剩余的字符编码(BEFC)从零开始。
现在,您可以使用相同的方式递归重复此过程,直到列表中最多有两个条目,您就完成了。