算法原理
霍夫曼编码字长就是其对应二叉树叶子节点的路径长度。显然根节点的长度为0,子节点的编码长度比父母节点的长度大1。因此建立霍夫曼树的过程中保存指向父母节点的地址即可,然后从叶子节点往上搜寻,每次长度加1,直到根节点为止。实现的方法分为如下几步:
初始化最小堆
实现过程中开辟2倍空间的节点,实际排序建立二叉树只用一半,后面一半保存叶子节点的所指的父母节点。
代码如下:
leaf_name=['A','B','C','D','E','F','G','H','A','B','C','D','E','F','G','H'];
leaf_data=[10,1,1,11,1,1,8,5,0,0,0,0,0,0,0,0];
leaf_addr=[9,10,11,12,13,14,15,16,0,0,0,0,0,0,0,0];
my_heap=heap();
my_heap.min_heap_create(leaf_name,leaf_data,leaf_addr);
my_heap.heap_set_size(8) ;
my_heap.min_heap_adjust();
my_heap.heap_set_size(16) ;
my_heap.min_heap_print();
my_heap.heap_set_size(8) ;
运行结果如下:
node 01–>addr 10–>name B–>data 1
node 02–>addr 13–>name E–>data 1
node 03–>addr 11–>name C–>data 1
node 04–>addr 16–>name H–>data 5
node 05–>addr 09–>name A–>data 10
node 06–>addr 14–>name F–>data 1
node 07–>addr 15–>name G–>data 8
node 08–>addr 12–>name D–>data 11
node 09–>addr 00–>name A–>data 0
node 10–>addr 00–>name B–>data 0
node 11–>addr 00–>name C–>data 0
node 12–>addr 00–>name D–>data 0
node 13–>addr 00–>name E–>data 0
node 14–>addr 00–>name F–>data 0
node 15–>addr 00–>name G–>data 0
node 16–>addr 00–>name H–>data 0
依次从堆里取最小的两个节点构建二叉树
构建过程中保存子节点指向父母节点的地址,保存在data字段,同时父母节点的data字段为二者之和,addr字段为当前堆长度加一个单位。循环直到堆只有一个元素位置。代码如下:
while(my_heap.size >1)
my_heap.min_heap_popup();
temp_data1=my_heap.data(my_heap.size+1);
temp_addr1=my_heap.addr(my_heap.size+1);
my_heap.min_heap_popup();
temp_data2=my_heap.data(my_heap.size+1);
temp_addr2=my_heap.addr(my_heap.size+1);
my_heap.data(temp_addr1)=my_heap.size+1;
my_heap.data(temp_addr2)=my_heap.size+1;
my_heap.min_heap_insert('X',(temp_data1+temp_data2),my_heap.size+1);
temp_size =my_heap.size;
my_heap.heap_set_size(16) ;%方便查看打印有意将堆长度设置到最大值
my_heap.min_heap_print();
my_heap.heap_set_size(temp_size) ;%设置成实际
end
依次循环的显示结果如下:
node 01–>addr 11–>name C–>data 1
node 02–>addr 16–>name H–>data 5
node 03–>addr 14–>name F–>data 1
node 04–>addr 12–>name D–>data 11
node 05–>addr 09–>name A–>data 10
node 06–>addr 15–>name G–>data 8
node 07–>addr 07–>name X–>data 2
node 08–>addr 10–>name B–>data 1
node 09–>addr 00–>name A–>data 0
node 10–>addr 00–>name B–>data 7
node 11–>addr 00–>name C–>data 0
node 12–>addr 00–>name D–>data 0
node 13–>addr 00–>name E–>data 7
node 14–>addr 00–>name F–>data 0
node 15–>addr 00–>name G–>data 0
node 16–>addr 00–>name H–>data 0
node 01–>addr 07–>name X–>data 2
node 02–>addr 16–>name H–>data 5
node 03–>addr 06–>name X–>data 2
node 04–>addr 12–>name D–>data 11
node 05–>addr 09–>name A–>data 10
node 06–>addr 15–>name G–>data 8
node 07–>addr 11–>name C–>data 1
node 08–>addr 10–>name B–>data 1
node 09–>addr 00–>name A–>data 0
node 10–>addr 00–>name B–>data 7
node 11–>addr 00–>name C–>data 6
node 12–>addr 00–>name D–>data 0
node 13–>addr 00–>name E–>data 7
node 14–>addr 00–>name F–>data 6
node 15–>addr 00–>name G–>data 0
node 16–>addr 00–>name H–>data 0
node 01–>addr 05–>name X–>data 4
node 02–>addr 16–>name H–>data 5
node 03–>addr 15–>name G–>data 8
node 04–>addr 12–>name D–>data 11
node 05–>addr 09–>name A–>data 10
node 06–>addr 07–>name X–>data 5
node 07–>addr 11–>name C–>data 5
node 08–>addr 10–>name B–>data 1
node 09–>addr 00–>name A–>data 0
node 10–>addr 00–>name B–>data 7
node 11–>addr 00–>name C–>data 6
node 12–>addr 00–>name D–>data 0
node 13–>addr 00–>name E–>data 7
node 14–>addr 00–>name F–>data 6
node 15–>addr 00–>name G–>data 0
node 16–>addr 00–>name H–>data 0
node 01–>addr 15–>name G–>data 8
node 02–>addr 04–>name X–>data 9
node 03–>addr 12–>name D–>data 11
node 04–>addr 09–>name A–>data 10
node 05–>addr 05–>name X–>data 4
node 06–>addr 07–>name X–>data 5
node 07–>addr 11–>name C–>data 5
node 08–>addr 10–>name B–>data 1
node 09–>addr 00–>name A–>data 0
node 10–>addr 00–>name B–>data 7
node 11–>addr 00–>name C–>data 6
node 12–>addr 00–>name D–>data 0
node 13–>addr 00–>name E–>data 7
node 14–>addr 00–>name F–>data 6
node 15–>addr 00–>name G–>data 0
node 16–>addr 00–>name H–>data 4
node 01–>addr 09–>name A–>data 10
node 02–>addr 12–>name D–>data 11
node 03–>addr 03–>name X–>data 17
node 04–>addr 15–>name G–>data 3
node 05–>addr 05–>name X–>data 4
node 06–>addr 07–>name X–>data 5
node 07–>addr 11–>name C–>data 5
node 08–>addr 10–>name B–>data 1
node 09–>addr 00–>name A–>data 0
node 10–>addr 00–>name B–>data 7
node 11–>addr 00–>name C–>data 6
node 12–>addr 00–>name D–>data 0
node 13–>addr 00–>name E–>data 7
node 14–>addr 00–>name F–>data 6
node 15–>addr 00–>name G–>data 3
node 16–>addr 00–>name H–>data 4
node 01–>addr 03–>name X–>data 17
node 02–>addr 02–>name X–>data 21
node 03–>addr 09–>name A–>data 10
node 04–>addr 15–>name G–>data 3
node 05–>addr 05–>name X–>data 4
node 06–>addr 07–>name X–>data 5
node 07–>addr 11–>name C–>data 5
node 08–>addr 10–>name B–>data 1
node 09–>addr 00–>name A–>data 2
node 10–>addr 00–>name B–>data 7
node 11–>addr 00–>name C–>data 6
node 12–>addr 00–>name D–>data 2
node 13–>addr 00–>name E–>data 7
node 14–>addr 00–>name F–>data 6
node 15–>addr 00–>name G–>data 3
node 16–>addr 00–>name H–>data 4
node 01–>addr 01–>name X–>data 38
node 02–>addr 03–>name X–>data 1
node 03–>addr 09–>name A–>data 1
node 04–>addr 15–>name G–>data 3
node 05–>addr 05–>name X–>data 4
node 06–>addr 07–>name X–>data 5
node 07–>addr 11–>name C–>data 5
node 08–>addr 10–>name B–>data 1
node 09–>addr 00–>name A–>data 2
node 10–>addr 00–>name B–>data 7
node 11–>addr 00–>name C–>data 6
node 12–>addr 00–>name D–>data 2
node 13–>addr 00–>name E–>data 7
node 14–>addr 00–>name F–>data 6
node 15–>addr 00–>name G–>data 3
node 16–>addr 00–>name H–>data 4
node 01–>addr 01–>name X–>data 38
node 02–>addr 03–>name X–>data 1
node 03–>addr 09–>name A–>data 1
node 04–>addr 15–>name G–>data 3
node 05–>addr 05–>name X–>data 4
node 06–>addr 07–>name X–>data 5
node 07–>addr 11–>name C–>data 5
node 08–>addr 10–>name B–>data 1
node 09–>addr 00–>name A–>data 2
node 10–>addr 00–>name B–>data 7
node 11–>addr 00–>name C–>data 6
node 12–>addr 00–>name D–>data 2
node 13–>addr 00–>name E–>data 7
node 14–>addr 00–>name F–>data 6
node 15–>addr 00–>name G–>data 3
node 16–>addr 00–>name H–>data 4
对建立的二叉树进行结果分析
从最后一次显示结果来看,节点09~16的data字段保存了父节点的地址,利用代码求取各自的编码字长,然后保存在addr字段里面。执行my_heap.heap_len_encode(len+1)如下:
function heap_len_encode(heap,n)
for i=n:heap.size
heap.addr(i)=1;
while(heap.data(i) >1)
heap.data(i)=heap.data(heap.data(i));
heap.addr(i)=heap.addr(i) +1;
end
end
end
运行结果如下:
node 01–>addr 01–>name X–>data 38
node 02–>addr 03–>name X–>data 1
node 03–>addr 09–>name A–>data 1
node 04–>addr 15–>name G–>data 3
node 05–>addr 05–>name X–>data 4
node 06–>addr 07–>name X–>data 5
node 07–>addr 11–>name C–>data 5
node 08–>addr 10–>name B–>data 1
node 09–>addr 02–>name A–>data 1
node 10–>addr 05–>name B–>data 1
node 11–>addr 05–>name C–>data 1
node 12–>addr 02–>name D–>data 1
node 13–>addr 05–>name E–>data 1
node 14–>addr 05–>name F–>data 1
node 15–>addr 02–>name G–>data 1
node 16–>addr 03–>name H–>data 1
统计字符A~H的码长
字符 | A | B | C | D | E | F | G | H |
---|---|---|---|---|---|---|---|---|
码长 | 2 | 5 | 5 | 2 | 5 | 5 | 2 | 3 |