<p>通常的做法是使用哈夫曼算法只生成代码长度。然后使用规范化过程从长度中生成代码。这棵树被丢弃了。代码按从短代码到长代码的顺序分配,在代码中,符号被排序。这将给出您期望的代码,<code>a = 00</code>,<code>b = 01</code>,等等,这称为<a href="http://en.wikipedia.org/wiki/Canonical_Huffman_code" rel="nofollow">Canonical Huffman code</a>。在</p>
<p>这样做的主要原因是为了使哈夫曼代码的传输更紧凑。您只需发送每个符号的代码长度,而不必随压缩数据一起发送每个符号的代码。然后可以在另一端重建代码进行解压缩。在</p>
<p>哈夫曼树通常也不用于解码。对于规范代码,通过简单的比较来确定下一个代码的长度,使用代码值的索引将直接指向符号。或者表驱动的方法可以避免搜索长度。在</p>
<p>至于你的树,当频率相等时,会有任意的选择。具体地说,在第二步中,拉入的第一个节点是概率为0.2的<code>c</code>,被拉的第二个节点是概率为0.25的{<cd4>}。然而,同样有效的方法是拉取第一步中生成的节点,而不是<code>b</code>,其概率为<em>也</em>0.25。事实上,这就是你想要的最终状态。唉,您已经将任意选择的控制权交给了<code>heapq</code>库。在</p>
<p>(注意:由于使用的是浮点值,0.1+0.15不一定完全等于0.25。尽管事实证明是这样。作为另一个例子,0.1+0.2等于0.3。如果你想知道当频率之和等于其他频率或频率之和时会发生什么,最好对频率使用整数。E、 g.6,5,4,3,2.)</p>
<p>一些错误的顺序可以通过纠正一些错误来修复:将<code>lo.merge(high)</code>改为<code>hi.merge(lo)</code>,并将位的顺序颠倒为:<code>assign_code(node.left, code+'1')</code>,然后再<code>assign_code(node.right, code+'0')</code>。那么至少<code>a</code>被赋值为00,<code>d</code>在<code>e</code>之前,<code>b</code>在{<cd3>}之前。顺序是<code>adebc</code>。在</p>
<p>现在我想一想,即使你选择<code>(e,d)</code>而不是<code>b</code>,例如通过将<code>b</code>的概率设置为0.251,你仍然得不到你所追求的完整顺序。不管怎样,<code>(e,d)</code>(0.25)的概率大于{<cd3>}的概率(0.2)。因此,即使在这种情况下,最终的顺序也是(通过上面的修复)<code>abdec</code>,而不是您想要的<code>abcde</code>。因此,<em>不可能得到您想要的结果,假设与符号组的概率有关的树排序和位分配是一致的。E、 g.假设对于每个分支,左边的东西比右边的东西有更大或相等的概率,0总是分配给左边,1总是分配给右边。你需要做些不同的事情。在</p>
<p>我想到的另一件事是我在答案开始时说的话。使用哈夫曼算法只是为了得到代码长度。然后你可以把代码按你喜欢的顺序分配给符号,然后建立一个新的树。这比试图想出某种方案来强迫原始树成为您想要的并证明它在所有情况下都有效要容易得多。在</p>