java Hufman:霍夫曼编码

时间:2021-04-03 12:16:04

标签: java huffman-code

我正在尝试将 Huffman 编码为一些家庭作业,但我对如何开始创建 Huffman 树感到有些困惑。我知道哈夫曼树采用两个最低频率,并将它们作为父节点的频率之和变成一棵树。

在我的主要方法中,我有符号及其概率:




import java.util.PriorityQueue;

public final class TCode {

    private CodeItem[] item = null;

    public final static class CodeItem {

        private String symbol;
        private double probability; 
        private String encoding; 

        public CodeItem(String symbol, double probability, String encoding) {
            this.symbol = symbol.trim();
            this.probability = probability;
            this.encoding = encoding;
            if (!is01() || this.symbol == null || this.symbol.length() == 0 || this.probability < 0.0)
                throw new IllegalArgumentException();
        }

        public CodeItem(String symbol, double probability) {
            this(symbol, probability, null);
        }

        public String getSymbol() {
            return symbol;
        }

        public double getProbability() {
            return probability;
        }

        public String getEncoding() {
            return encoding;
        }

        public void setEncoding(String encoding) {
            this.encoding = encoding;
        }

        public boolean is01() {

            if (encoding == null || encoding.length() == 0)
                return true;

            for (int i = 0; i < encoding.length(); ++i)
                if ("01".indexOf(encoding.charAt(i)) < 0)
                    return false;

            return true;
        }

    }

    public TCode(CodeItem[] codeItem) {

        if (codeItem == null || codeItem.length == 0)
            throw new IllegalArgumentException();

        double sum = 0.0;
        for (int i = 0; i < codeItem.length; ++i) {
            sum += codeItem[i].probability;
            if (codeItem[i].probability == 0.0)
                throw new IllegalArgumentException();
        }
        if (Math.abs(sum - 1.0) > 1e-10)
            throw new IllegalArgumentException();

        item = new CodeItem[codeItem.length];
        for (int i = 0; i < codeItem.length; ++i)
            item[i] = codeItem[i];

    }

    public boolean is01() {

        for (int i = 0; i < item.length; ++i)
            if (!item[i].is01())
                return false;

        return true;
    }

    public double entropy() {

        double result = 0.0;

        for (int i = 0; i < item.length; ++i)
            result += item[i].probability * (-Math.log(item[i].probability) / Math.log(2.0));

        return result;
    }

    public double averageWordLength() {

        double result = 0.0;

        for (int i = 0; i < item.length; ++i)
            result += item[i].encoding.length() * item[i].probability;

        return result;
    }

    public boolean isPrefixCode() {

        for (int i = 1; i < item.length; ++i)
            for (int j = 0; j < i; ++j)
                if (item[i].encoding.startsWith(item[j].encoding) || item[j].encoding.startsWith(item[i].encoding))
                    return false;
        return true;
    }

    public int size() {
        return item.length;
    }

    public CodeItem getAt(int index) {
        return item[index];
    }

    public CodeItem getBySymbol(String symbol) {

        for (int i = 0; i < item.length; ++i) {
            if (item[i].symbol.equals(symbol))
                return item[i];
        }
        return null;
    }

    
    

    }

}

1 个答案:

答案 0 :(得分:0)

如果我理解正确,您将开始形成具有两个最低频率的二叉树并将它们的值相加以创建父节点。然后,努力向上。在您的情况下,最低的两个是:

("A", 0.12) and ("D", 0.13) add to 0.25

此时您将拥有:

     (0.25)
     /    \ 
    /      \
   /        \
D(0.13)   A(0.12)

然后,由于您还有两个值频率大于 0.25 的节点,您将创建另一个具有这些值的二叉树 (B & E)

     (0.35)
     /    \ 
    /      \
   /        \
B(0.19)   E(0.16)

并且这棵树的结果父项将加入前一棵树的结果父项

     (0.60)
     /    \ 
    /      \
   /        \
B&E(0.35)   A&D(0.25)

最后,C 加入

      (1.00)
      /    \ 
     /      \
    /        \
ADBE(0.60)  C(0.40)

你的树应该是这样的:

                  (1.00)
                  /    \ 
                 /      \
                /        \
            ADBE(0.60)  C(0.40)
            /        \ 
           /          \
          /            \
   BE(0.35)          AD(0.25)
     /    \            /    \ 
    /      \          /      \
   /        \        /        \
B(0.19)  E(0.16)  D(0.13)   A(0.12)

总而言之,您形成了一个具有两个最低频率的二叉树。父项的频率是其子项的总和。结果节点只能连接一个元素以形成继续形成二叉树。因此,它的同级元素必须是频率最低的下一个元素由总和小于或等于它的元素生成的二叉树。例如,当 A&D 节点形成时,它与生成的 B&E 树连接。如果 B 或 E 的频率之一高于 0.25,则只有频率较低的元素会与 A&D 连接。

相关问题