2

小さなハフマン エンコーディング スクリプトを実装することにしました。小さな確率リストでテストした後、構築中にツリーを印刷すると正しい結果が得られ、そうでない場合は間違った結果が得られます。問題の原因は何ですか?

これが私のコードです:

from __future__ import division
import heapq


class LeafNode:
    def __init__(self,symbol,prob):
        self.symbol = symbol
        self.prob = prob
    def __repr__(self):
        return "(%s: %s)" % (self.symbol, self.prob)
class InternalNode:
    def __init__(self,prob,left,right):
        self.prob = prob
        self.left = left
        self.right= right
    def __repr__(self):
        return "(internal : %s)" % (self.prob)

def getDict(seq):
    d = dict()
    for symbol in seq:
        if symbol in d:
            d[symbol] += 1
        else:
            d[symbol] = 1
    return d

def returnProbList(seq):
    data = getDict(seq)
    sum_of_all = sum(data.values())
    l = sorted(data.items(), key=lambda x:x[1])
    return [LeafNode(x[0], x[1]/sum_of_all) for x in l]

def createTree(probs):
    heapq.heapify(probs)
    while len(probs) > 1:
        a = heapq.heappop(probs)
        b = heapq.heappop(probs)
        print a,b #removing this shows wrong results.
        f = InternalNode(a.prob+b.prob,a,b)
        heapq.heappush(probs,f)
    return probs[0]

def printSymbols(tree, seq = ''):    
    if isinstance(tree, InternalNode):
        printSymbols(tree.left, seq+'0')
        printSymbols(tree.right, seq+'1')
    else:
        print tree.symbol, seq

s = "This is some short text I have written. It seems that space is the most common symbol."

#l = returnProbList(s)
l = []
l.append(LeafNode('a4',0.05))
l.append(LeafNode('a3',0.2))
l.append(LeafNode('a2',0.35))
l.append(LeafNode('a1',0.4))



#print l
tree = createTree(l)
printSymbols(tree)

pdb を使用してデバッグすると、さらに異なる結果が得られました。

#Without print
a4 00
a3 01
a2 10
a1 11
#With print
a1 0
a4 100
a3 101
a2 11
#With pdb
a1 0
a2 10
a3 110
a4 111
4

1 に答える 1

2

これは印刷とはまったく関係ありません。あなたの問題はここにあります:

heapq.heappush(probs,f)

fクラスのインスタンスですInternalNodeが、クラスは順序を定義していません。そのため、Python はデフォルトでInternalNodeインスタンスをメモリ アドレスで並べ替えます。これはあなたが望むものではありません.メモリアドレスは、他に何をするかによって異なります(印刷、PDBの実行、他のオブジェクトの作成または削除...)。

最も簡単な修正は__cmp__、クラスにメソッドを追加することです。

    def __cmp__(a, b):
        return cmp(a.prob, b.prob)

その後、出力は一貫します。

LeafNode編集:うーん、インスタンスのメモリアドレスの順序も取得しているので、それに a も追加__cmp__してください。

于 2013-11-10T22:10:36.207 に答える