ハフマン符号化

ハフマン符号化

講義で課題が出たので、Pythonの勉強もかねてプログラム化に挑戦。

Pythonの技法:Huffman符号化の実装 - builder

ずばりな記事があったので、これのソース読むとこから始めたんだけど、
おおまかには理解できたが、heapqモジュールのheapify()で躓く。

#coding: UTF-8

from itertools import groupby
from heapq import *

#ノードの情報を扱うクラス
class Node(object):
    item = None     #格納している値
    weight = 0      #子ノードを足し合わせた重み
    right = None    #右側のノード
    left = None     #左側のノード

    def __init__(self, i, w):
        self.item = i
        self.weight = w

    def setChildren(self, ln, rn):
        self.left = ln
        self.right = rn

    #ノードの状態を表示
    #def __repr__(self):
    #    return "%s - %s -- %s _ %s" % (self.item, self.weight, self.left, self.right)

    #heapqモジュールを使うため
    def __cmp__(self, a):
        return cmp(self.weight, a.weight)


def huffman(input):
    itemqueue =  [Node(a,len(list(b))) for a,b in groupby(sorted(input))]   #inputをソートしたものを重み付け
    print(type(itemqueue))
    heapify(itemqueue)  #ヒープ化

    #
    while len(itemqueue) > 1:       #残り1つになるまで
        l = heappop(itemqueue)
        r = heappop(itemqueue)
        n = Node(None, r.weight+1)  #右側の符号を1とする
        n.setChildren(l, r)         #右、左の子要素を割り当てる
        heappush(itemqueue, n)      #足し合わせた2つをプッシュする


    codes = {}
    #ノードの値がなければ右側のノードに1,左側のノードに0で符号化する
    #再帰関数を利用し、符号を積み重ねながら枝をたどる
    def codeIt(s, node):
        if node.item:
            if not s:
                codes[node.item] = "0"
            else:
                codes[node.item] = s
        else:
            codeIt(s+"0", node.left)
            codeIt(s+"1", node.right)

    codeIt("", itemqueue[0])
    return codes, "".join(codes[a] for a in input)  #inputの値を""区切りで表示


input = "aababcabcd"
huffman(input)


読みながら自分の言葉で説明付けしたので、文字多いのは割愛。
で、以下実行結果。

$python huffman.py

<class 'list'>
Traceback (most recent call last):
  File "huffman.py", line 62, in <module>
    huffman(input)
  File "huffman.py", line 33, in huffman
    heapify(itemqueue)  #ヒープ化
TypeError: unorderable types: Node() < Node()


怒られる。
itemqueueはリストだから、heapifyでヒープ化できるはずなんだけどできない。
Node() < Node()って何?


...眠いから明日に回す。