从频率数组编码的霍夫曼(用Java编写)

时间:2017-05-11 11:13:12

标签: java compression huffman-code

我的霍夫曼代码有问题。在main方法中,我输入一个包含符号频率的Integer数组。它应该打印出每个符号及其霍夫曼代码,但我认为有些不对劲

主要:

int[] histo = new int[]{8, 65, 124, 55, 2, 1, 0, 1};
System.out.println("Codage de Huffman:");
String[] huffman = huffman(histo);
for (int i = 0; i < huffman.length; i++) {
    if (histo[i] > 0) {
        System.out.println(i + "] " + huffman[i]);
    }
}

现在以霍夫曼代码:

public static String[] huffman(int[] histo) {
    String[] codage = new String[histo.length];
    int valeur1;
    int valeur2;
    int index1 = 0;
    int index2 = 0;
    for (int i = 0; i < histo.length; i++) {
        codage[i] = new String();
    }

    do {
        valeur1 = Integer.MAX_VALUE;
        valeur2 = Integer.MAX_VALUE;
        for (int i = 0; i < histo.length; i++) {
            if (histo[i] > 0) {
                if (histo[i] < valeur1) {
                    valeur2 = valeur1;
                    valeur1 = histo[index1 = i];
                } else if (histo[i] < valeur2) {
                    valeur2 = histo[index2 = i];
                }
            }
        }
        histo[index1] = 0;
        histo[index2] += valeur1;
        codage[index1] = codage[index1] + "0";
        codage[index2] = codage[index2] + "1";
    } while (valeur2 != Integer.MAX_VALUE);

    return codage;

}

这是输出:

0] 0
1] 0
2] 0
3] 111101
4] 0
5] 0
7] 110

1 个答案:

答案 0 :(得分:1)

您的问题是,当您向代码添加一些内容时,只会将其添加到当前索引(而不是添加到树的所有子代中)。

我建议你使用树形结构,如下所示:(注意,我并不完全确定霍夫曼代码的正确性,但代码应该有效)

    public static String[] huffman(int[] histo){
        //build up initial list of nodes
        List<Node> tree = new ArrayList<>();
        for (int i = 0; i < histo.length; i++)
            if(histo[i] != 0)
                tree.add(new Node(histo[i], i));

        //combine lowest weights untill only the root is left
        while(tree.size() > 1){
            combine(tree);
        }

        //recursively generate code for each node in the tree
        //if the recursion finds a leaf node,
        //it sets the correct element in the array to the code of the node
        Node root = tree.get(0);
        String[] codage = new String[histo.length];
        root.generateCodes(codage);

        return codage;
    }

    /**
     * Sorts the list and combines the first two nodes in the list to a single node.
     */
    private static void combine(List<Node> list){

        if(list.size() < 2)
            return;

        Collections.sort(list);

        Node smallest = list.remove(0);
        Node secondToSmallest = list.remove(0);

        Node parent = new Node(secondToSmallest, smallest, smallest.getValue()+secondToSmallest.getValue());

        list.add(0, parent);
    }

我为树创建了一个简单的节点类。

public class Node implements Comparable<Node>{

private final Node left;
private final Node right;
private final int value;
private final int index;
private String code = "";

public Node(Node left, Node right, int value){
    this.left = left;
    this.right = right;
    this.value = value;
    this.index = -1;
}

public Node(int value, int index){
    this.index = index;
    this.value = value;
    this.left = null;
    this.right = null;
}

public void generateCodes(String[] codes){
    if(left != null && right != null){
        left.setCode("0"+getCode());
        left.generateCodes(codes);
        right.setCode("1"+getCode());
        right.generateCodes(codes);
    }else{
        codes[index] = getCode();
    }
}

private void setCode(String code){
    this.code = code;
}

public String getCode(){
    return code;
}

public Node getLeft() {
    return left;
}

public Node getRight() {
    return right;
}

public int getValue(){
    return value;
}

public int getIndex() {
    return index;
}

@Override
public int compareTo(Node other) {
    if(other == null)
        return -1;

    return Integer.compare(getValue(), other.getValue());
}

}