1

I have a problem with my Huffman tree code. In the main method I input a String of Symbols and I also input an Integer array containing the frequency of the Symbols. It should print out each Symbol and its Huffman code, but I think its wrong...

Here is the code:

 package huffman;

import java.util.*;

abstract class HuffmanTree implements Comparable<HuffmanTree> {
    public final int frequency; // the frequency of this tree
    public HuffmanTree(int freq) { frequency = freq; }

    // compares on the frequency
    public int compareTo(HuffmanTree tree) {
        return frequency - tree.frequency;
    }
}

class HuffmanLeaf extends HuffmanTree {
    public final char value; // the character this leaf represents

    public HuffmanLeaf(int freq, char val) {
        super(freq);
        value = val;
    }
}

class HuffmanNode extends HuffmanTree {
    public final HuffmanTree left, right; // subtrees

    public HuffmanNode(HuffmanTree l, HuffmanTree r) {
        super(l.frequency + r.frequency);
        left = l;
        right = r;
    }
}

public class Huffman {
    // input is an array of frequencies, indexed by character code
    public static HuffmanTree buildTree(int[] charFreqs, char[] test2) {
        PriorityQueue<HuffmanTree> trees = new PriorityQueue<HuffmanTree>();
        // initially, we have a forest of leaves
        // one for each non-empty character
        for (int i = 0; i < charFreqs.length; i++)
            if (charFreqs[i] > 0)
                trees.offer(new HuffmanLeaf(charFreqs[i], test2[i]));

        assert trees.size() > 0;
        // loop until there is only one tree left
        while (trees.size() > 1) {
            // two trees with least frequency
            HuffmanTree a = trees.poll();
            HuffmanTree b = trees.poll();

            // put into new node and re-insert into queue
            trees.offer(new HuffmanNode(a, b));
        }
        return trees.poll();
    }

    public static void printCodes(HuffmanTree tree, StringBuffer prefix) {
        assert tree != null;
        if (tree instanceof HuffmanLeaf) {
            HuffmanLeaf leaf = (HuffmanLeaf)tree;

            // print out character, frequency, and code for this leaf (which is just the prefix)
            System.out.println(leaf.value + "\t" + leaf.frequency + "\t" + prefix);

        } else if (tree instanceof HuffmanNode) {
            HuffmanNode node = (HuffmanNode)tree;

            // traverse left
            prefix.append('0');
            printCodes(node.left, prefix);
            prefix.deleteCharAt(prefix.length()-1);

            // traverse right
            prefix.append('1');
            printCodes(node.right, prefix);
            prefix.deleteCharAt(prefix.length()-1);
        }
    }

    public static void main(String[] args) {
        //Symbols:
        String str = "12345678"; 
        char[] test2 = str.toCharArray();
        //Frequency (of the symbols above):
        int[] charFreqs = {36,18,12,9,7,6,5,4};


        // build tree
        HuffmanTree tree = buildTree(charFreqs,test2);

        // print out results
        System.out.println("SYMBOL\tFREQ\tHUFFMAN CODE");
        printCodes(tree, new StringBuffer());
    }
}

The output I get is:

SYMBOL  FREQ    HUFFMAN CODE
1           36          0
3           12          100
6           6           1010
5           7           1011
2           18          110
4           9           1110
8           4           11110
7           5           11111

Thats weird, for example Symbol 7 should be: 11110 and Symbol 8 should be: 11111

Can you help me please?

4

4 に答える 4

0

回答のコメントから質問に回答するには:

ねえマーク、助けてくれてありがとう、でもどうやってそれらのコードを手に入れたのかよくわからないの? コードを大幅に変更する必要がありますか?<

マークは、すべてのシンボルの全体的なエンコーディング (周波数[シンボル] * すべてのシンボルのコード長[シンボル]) が最小化されるように、各シンボルの最も効率的な深さ (ビット数) を見つけるというハフマン コーディングの目標を単に参照しています。

したがって、実際に行う必要があるのは、各シンボルの葉の深さ (レベル) を決定することだけです。これを各シンボルの深さで並べ替え、数え始めます。

これで、パターンを数え上げるだけです。そのような単純な:

Example:
2x2: 00, 01  (next is 10)
4x3: 10 + (00, 01, 10) = 1000, 1001, 1010 (next is 1011)
5x3: 1011 + (0, 1, 0 + 10) = 10110, 10111, 10110 + 10 = 11000 (next would be 11001)...

最後の部分は、要素の数が両方のグループ間で利用可能なビット差よりも大きい場合に何が起こるかを示しています。プレフィックスに追加されるだけです。

このようにして、最小量のスペースを使用するハフマン コードが作成されます。これは 1 つのツリーにすぎないため、11111 から開始して 1 を削除し、ビット数に関して同等に効率的な別のコード システムを取得することもできます。

追加できることの 1 つは、1 (または 0) の数を 0 (または 1) と比較して増やす変更があるため、メッセージをさらに圧縮するために使用されるビット パターンを圧縮する別の機会があることです。


要約: シンボルを頻度ツリー内の深さで並べ替えます。1 を加算 (減算) してコードを作成します。次のフリー コードは、次のグループの開始プレフィックスです。新しいメンバーごとに加算 (減算) するだけです。そして、コード内で 0 (1) を埋めることから始めます。

このようなツリーを保存するには、同じシンボル グループに対して同じアルゴリズムを使用して、次の情報のみを保存する必要があります。

グループ数 n, n * { +bitDepth, シンボル数 i, s1,s2...si}. n、+bitDepth、シンボル数の保存自体が圧縮の対象であるため、可変ビット形式を使用するか、ハフマン ツリーを発行することもできます。これは、圧縮が行われていることを確認できる主な理由である統計的に不均一な分布を見つけるためです。ハフマンの木で。

于 2015-03-02T08:56:38.147 に答える
0

終了ビットを理解するために、もう 1 つ 0 を追加するだけです。(3 ビット以上の読み取り)

1 36 0 3 12 100 6 6 1010 5 7 1011'0 2 18 110 4 9 1110 8 4 11110 7 5 11111'0

于 2014-01-20T10:55:33.843 に答える