SSL1408【树】哈夫曼树(二)
题目
有n(n<=26)个带权结点,从a开始的n个字母分别表示这n个结点,他们分别代n个权值,试以它们为叶子结点构造一棵哈夫曼树(请按照左子树根节点的权小于等于右子树根节点的权的次序构造,若两结点相等时,按照字典顺序分别为左子树和右子树)。 最后求出该哈夫曼树的带权路径长度.
题解
哈弗曼编码,与SSL1407【树】哈夫曼树(一)相似。
不同的是排序时要对权值等字典序不等的节点进行判断。
代码
type
arr=record
data:integer;
lchild,rchild:integer;
addr:integer;
mean:char;//存对应字母
word:string;//存编码
end;
var
i,ans,t,n:longint;
c:char;
s:string;
a,f:array[0..100]of arr;
procedure sort(k:longint);
var
i,j:longint;
t:arr;
begin
for i:=1 to k-1 do
for j:=i+1 to k do
if a[i].data>a[j].data then
begin
t:=a[i];a[i]:=a[j];a[j]:=t;
end else
if (a[i].data=a[j].data)and
(a[i].mean>=a[j].mean) then
begin
t:=a[i];a[i]:=a[j];a[j]:=t;
end;
end;
procedure visit(k,d:longint;s:string);
begin
if f[k].data=0 then exit;
visit(f[k].lchild,d+1,s+'0');
inc(i);
if i mod 2=0 then
begin
f[k].word:=s;
ans:=ans+d*f[k].data;
end;
visit(f[k].rchild,d+1,s+'1');
end;
begin
readln(n);
for i:=1 to n do
read(f[i].mean,c);
a:=f;
for i:=1 to n do
begin
read(a[i].data);
f[i].data:=a[i].data;
a[i].addr:=i;
end;
t:=n+1;i:=n;
while i>1 do
begin
sort(i);
f[t].data:=a[1].data+a[2].data;
f[t].lchild:=a[1].addr;
f[t].rchild:=a[2].addr;
a[1].data:=f[t].data;
a[1].addr:=t;
a[1].mean:=chr(ord('z')+1);
a[2].data:=a[i].data;
a[2].addr:=a[i].addr;
a[2].mean:=a[i].mean;
inc(t);
dec(i);
end;
i:=1;
visit(t-1,0,s);
for i:=1 to n do
writeln(f[i].mean,':',f[i].word);
writeln(ans);
end.