データ構造 - ハフマン木(Python実装)

さて、以前の私たちは、この記事ではない一般的なバイナリツリーの完全なバイナリツリー、完全なバイナリツリーを、ご紹介し、我々は、ハフマン木を紹介したいと思います。
ハフマンツリーはまた、実質的に同じであり、どちらも、最適なバイナリツリー、コンセプトならびにハフマン符号化に関連付けられたハフマン木と呼ばれます。ハフマン符号化は、ハフマンが1952年に提案されています。今ハフマンは、テキスト圧縮の観点でマルチアプリケーションをコーディングします。次に、我々は最終的にハフマン木を導入しなければならないものでしょうか?どのようなハフマン符号化することで、どのようにそれがテキスト圧縮に適用することができます。

ハフマン(ハフマン木)

木の重み付き経路長が最小に達した場合に、リーフノードNとして与えられたN個の重みは、バイナリツリー構造は、バイナリツリーはまた、ハフマン木(ハフマンツリー)として知られている最適なバイナリツリーと呼ばれます。ハフマンツリーは、最短経路長加重ツリー、近いルートノードから大きな重みです。

まず、我々はこのデータの一部を持っています:

sourceData = [('a', 8), ('b', 5), ('c', 3), ('d', 3), ('e', 8), ('f', 6), ('g', 2), ('h', 5), ('i', 9), ('j', 5), ('k', 7), ('l', 5), ('m', 10), ('n', 9)]

各データ項目はタプルで、第1のコンテンツデータの組は、第二のデータが正しい重量です。言い換えると、ハフマン木を構築するために使用されるデータは重みです。これらの重みのアルファベットの文字内部データが文字の出現確率が高く、大きい文字の重量の計算テキストYの発生確率に基づいていると仮定する。このような手紙8の重量の権利として。

まあ、以来、私たちは、ハフマンツリーを構築するためのデータを得ることができます。

  1. 最初の2つの要素のすべての要素の最小重量を見つけるすなわち、G(2)、C(3)、
  2. 右バイナリツリーの親ノードにバイナリツリー構築G cがあり、子供は2 + 3 = 5の重量に構成されています。
  3. およびg C残りの要素に加えて、新しく構築右ノード5重量最小重量は、2つのノードを選択し、
  4. 第1段階の動作のために2。

ように、ハフマンバイナリツリーの最終合成までの木です。

私たちは、伝説を表現するためにそれを使用します。

さて、ここで我々はハフマン木がうまく構築され、ノード番号は、アルファベットの文字以下の権利が重い示し、与えられたデータの前にあります。ここで私はそれを強調したい、ハフマン木をステップバイユニーク、ステップを作成するために、同じデータではありません、ただルールに間違いに従っていない、あなたのハフマンツリーが正しいです。

我々は今、左ノードは0として定義されているアクセスし、アクセスが現在文字が、それは0110として符号化されたアクセス権ノード1として定義され、文字nのアクセスコード111は、符号化はハフマン符号化されています。

異なる文字のためのハフマン符号化を比較することによって、あなたは何を発見しましたか?

权重越大的字母对应的哈夫曼编码越短,权重越小的字母对应的哈夫曼编码则越长。也就是说文本中出现概率大的字母编码短,出现概率小的字母编码长。通过这种编码方式来表示文本中的字母,那所得整个文本的编码长度也会缩短。

这就是哈夫曼树也就是哈夫曼编码在文本压缩中的应用。

下面我们用代码来实现:

定义一个二叉树类:

class BinaryTree:
    def __init__(self, data, weight):
        self.data = data
        self.weight = weight
        self.left = None
        self.right = None

获取节点列表中权重最小的两个节点:

# 定义获取列表中权重最大的两个节点的方法:
def min2(li):
    result = [BinaryTree(None, float('inf')), BinaryTree(None, float('inf'))]
    li2 = []
    for i in range(len(li)):
        if li[i].weight < result[0].weight:
            if result[1].weight != float('inf'):
                li2.append(result[1])
            result[0], result[1] = li[i], result[0]
        elif li[i].weight < result[1].weight:
            if result[1].weight != float('inf'):
                li2.append(result[1])
            result[1] = li[i]
        else:
            li2.append(li[i])
    return result, li2

定义生成哈夫曼树的方法:

def makeHuffman(source):
    m2, data = min2(source)
    print(m2[0].data, m2[1].data)
    left = m2[0]
    right = m2[1]

    sumLR = left.weight + right.weight
    father = BinaryTree(None, sumLR)
    father.left = left
    father.right = right
    if data == []:
        return father
    data.append(father)
    return makeHuffman(data)

定义广度优先遍历方法:

# 递归方式实现广度优先遍历
def breadthFirst(gen, index=0, nextGen=[], result=[]):

    if type(gen) == BinaryTree:
        gen = [gen]
    result.append((gen[index].data, gen[index].weight))
    if gen[index].left != None:
        nextGen.append(gen[index].left)
    if gen[index].right != None:
        nextGen.append(gen[index].right)

    if index == len(gen)-1:
        if nextGen == []:
            return
        else:
            gen = nextGen
            nextGen = []
            index = 0
    else:
        index += 1
    breadthFirst(gen, index, nextGen,result)

    return result

输入数据:

# 某篇文章中部分字母根据出现的概率规定权重
sourceData = [('a', 8), ('b', 5), ('c', 3), ('d', 3), ('e', 8), ('f', 6), ('g', 2), ('h', 5), ('i', 9), ('j', 5), ('k', 7), ('l', 5), ('m', 10), ('n', 9)]
sourceData = [BinaryTree(x[0], x[1]) for x in sourceData]

创建哈夫曼树并进行广度优先遍历:

huffman = makeHuffman(sourceData)
print(breadthFirst(huffman))

OK ,我们的哈夫曼树就介绍到这里了,你还有什么不懂的问题记得留言给我哦。

おすすめ

転載: www.cnblogs.com/dongyangblog/p/11228930.html