Shannon-Fano代码作为python中的最大堆

时间:2014-12-12 15:41:46

标签: python algorithm encoding heap binary-tree

我有一个霍夫曼编码的最小堆代码,你可以在这里看到:http://rosettacode.org/wiki/Huffman_coding#Python

我正在尝试制作一个类似于min-heap的最大堆Shannon-Fano代码。

这是一段代码:

from collections import defaultdict, Counter
import heapq, math

def _heappop_max(heap):
"""Maxheap version of a heappop."""
lastelt = heap.pop()    # raises appropriate IndexError if heap is empty
if heap:
    returnitem = heap[0]
    heap[0] = lastelt
    heapq._siftup_max(heap, 0)
    return returnitem
return lastelt

def _heappush_max(heap, item):
    """Push item onto heap, maintaining the heap invariant."""
    heap.append(item)
    heapq._siftdown_max(heap, 0, len(heap)-1)

def sf_encode(symb2freq):
heap = [[wt, [sym, ""]] for sym, wt in symb2freq.items()]
heapq._heapify_max(heap)
while len(heap) > 1:
    lo = _heappop_max(heap)
    hi = _heappop_max(heap)
    for pair in lo[1:]:
        pair[1] = '0' + pair[1]
    for pair in hi[1:]:
        pair[1] = '1' + pair[1]
    _heappush_max(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])
print heap
return sorted(_heappop_max(heap)[1:], key=lambda p: (len(p[1]), p))

但我有这样的输出:

Symbol  Weight  Shannon-Fano Code
!   1   1
3   1   01
:   1   001
J   1   0001
V   1   00001
z   1   000001
E   3   0000001
L   3   00000001
P   3   000000001
N   4   0000000001
O   4   00000000001

我是否正确使用heapq来实现Shannon-Fano编码?这个字符串中的问题:

_heappush_max(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])

我不明白如何解决它。

期望输出类似于霍夫曼编码

Symbol  Weight  Huffman Code
    2875    01
a   744 1001
e   1129    1110
h   606 0000
i   610 0001
n   617 0010
o   668 1000
t   842 1100
d   358 10100
l   326 00110

添加了:

好吧,我试过没有heapq这样做,但是有不可阻挡的递归:

def sf_encode(iA, iB, maxP):
global tupleList, total_sf
global mid
maxP = maxP/float(2)
sumP = 0    
for i in range(iA, iB):
    tup = tupleList[i]
    if sumP < maxP or i == iA: # top group
        sumP += tup[1]/float(total_sf)
        tupleList[i] = (tup[0], tup[1], tup[2] + '0')
        mid = i           
    else: # bottom group
        tupleList[i] = (tup[0], tup[1], tup[2] + '1')
print tupleList
if mid - 1 > iA:
    sf_encode(iA, mid - 1, maxP)
if iB - mid > 0:
    sf_encode(mid, iB, maxP)
return tupleList

1 个答案:

答案 0 :(得分:0)

在Shannon-Fano编码中,您需要以下steps

  

Shannon-Fano树是根据设计的规范建造的   定义有效的代码表。实际的算法很简单:

     
      
  1. 对于给定的符号列表,请开发相应的列表   概率或频率计数使每个符号的相对性   发生的频率是已知的。
  2.   
  3. 根据符号排列符号列表   频率,左边最常出现的符号   在右边最不常见。
  4.   
  5. 将列表分为两部分,   左侧部分的总频率计数接近   尽可能合适的权利。
  6.   
  7. 分配列表的左侧部分   二进制数字0,右边部分分配数字1.这   表示第一部分中符号的代码都将开始   0表示,第二部分的代码全部以1开头。
  8.   
  9. 递归地将步骤3和4应用于两半中的每一半,   细分组并向代码添加位,直到每个符号具有   成为树上相应的代码叶。
  10.   

所以你需要代码进行排序(你的输入看起来已经排序,所以你可以跳过这个),还有一个递归函数,它选择最好的分区,然后在列表的前半部分和后半部分进行递归。

对列表进行排序后,元素的顺序永远不会改变,因此不需要使用heapq来执行这种编码方式。