【问题标题】:Determining frequencies for a Huffman compressed file确定 Huffman 压缩文件的频率
【发布时间】:2019-04-19 20:01:38
【问题描述】:

我在确定每个包含字符的节点的优先级时遇到问题,以便解压缩我的压缩文件。

所以当我压缩一个文件时,它会给我一个包含如下内容的 txt 文件:

我压缩了:Hello world,这是一个测试。

@111^a@10000^#@10001^d@10011^e@1010^H@0000^h@10110^i@1101^l@001^.@0001^o@1100^r@10010^ s@011^t@010^w@10111^%

00001010001001110011110111110010010001100111110101011011010111111101011111100001110101010011010000110001

前两行包含压缩文件中每个字符的二进制表示。

后两行是实际压缩的txt。

压缩类通过将节点的优先级设置为等于出现次数来创建树。

但是,压缩类不会将每个字符的出现次数写入输出文件。

为了确定优先级,我想我可以通过每个字符的二进制字符串的长度来做到这一点。如果字符串的长度较大,则其使用频率较低。另一方面,如果它更小,则使用更多。 然而,这似乎并没有按照我想要的方式构建树,因为它给了我错误的输出。

我能够通过编辑压缩文件写入输出文件的内容来获得正确的输出。基本上也只是传递字符频率。但我的主要问题是,如果没有这些价值观,我将如何做到这一点。

我还想我可以根据每个字符的实际二进制字符串来制作树。诸如创建一个虚拟根节点之类的东西。如果字符串中的 charAt(i) 等于 0,则向左走,否则向右走。我认为我的代码可能有点偏离,因为我在尝试遍历树时遇到空指针异常。我把代码贴在下面。

这是一个简短的简单版本,如果需要我可以发布更多内容

public class Decompress {
private static Node root;
private static HashMap<Character, String> values = new HashMap<Character, String>();
private static HashMap<Character, Integer> freq = new HashMap<Character, Integer>();

public Decompress() {
    root = null;
}

private static class Node implements Comparable {
    public Character value;
    public Integer number;
    public Node left;
    public Node right;

    // necessary in order for the priority queue to work
    // since it uses the compareTo to determine priority.
    public int compareTo(Object o) {
        Node other = (Node) o;
        if (other.number < number) {
            return 1;
        }
        if (other.number == number) {
            return 0;
        }
        return -1;
    }

public static void main(String args[]) throws IOException {
    BufferedReader fin = new BufferedReader(new FileReader("output" + ".txt"));
    String binaryDigits = insertListHelper(fin); // contains the compressed txt
    root = createTree(binaryDigits);  // Grabs the root node from method
    Node hold = root;
    // code for traversing the tree to find the character
    for (int i = 0; i < binaryDigits.length(); i++) {
        if (binaryDigits.charAt(i) == '1') {
            root = root.right;
        } else if (binaryDigits.charAt(i) == '0') {
            root = root.left;
        }
        if (root.left == null && root.right == null) {
            System.out.println(root.value);
            root = hold;
        }
    }
}

// works when I have the correct frequency
public static Node createTree(String binaryDigit) {
    PriorityQueue<Node> pq = new PriorityQueue<Node>();
    // insert all 1 node trees into pq
    Set<Character> s = values.keySet();
    for (Character c : s) {
        Node temp = new Node();
        temp.value = c;
        temp.number = values.get(c).length();
        temp.left = null;
        temp.right = null;
        pq.add(temp);
    }

    Node eof = new Node();
    eof.value = '#';
    eof.number = 1;
    eof.left = null;
    eof.right = null;
    pq.add(eof);

    while (pq.size() > 1) {
        Node left = pq.poll();
        Node right = pq.poll();
        Node temp = new Node();
        temp.value = null;
        temp.number = left.number + right.number;
        temp.left = left;
        temp.right = right;
        pq.add(temp);
    }
    return pq.peek();
}

// does not work any suggestions? 
public static Node createTree2() {
    String[] binaryRep = new String[values.size()];
    int k = 0;
    int lengthOfStr = 0;
    Set<Character> s1 = values.keySet();
    for (Character c : s1) {
        binaryRep[k] = values.get(c);
        System.out.println(c + " String : " + binaryRep[k]);

        Node root = new Node();
        root.value = 'R';
        root.left = null;
        root.right = null;
        Node hold = root;
        lengthOfStr = binaryRep[k].length();
        for (int i = 0; i < binaryRep[k].length(); i++) {
            if (binaryRep[k].charAt(i) == '1' && root.right != null) {
                root = root.right;
            } else if (binaryRep[k].charAt(i) == '0' && root.left != null) {
                root = root.left;
            } else if (binaryRep[k].charAt(i) == '1' && root.right == null && lengthOfStr == 0) {
                // found our place to insert
                Node temp = new Node();
                temp.left = null;
                temp.right = null;
                temp.number = 1;
                temp.value = c;
                root.right = temp;
                // move forward to the temp var
                root = root.right;
                root = hold;
                lengthOfStr--;
            } else if (binaryRep[k].charAt(i) == '0' && root.left == null && lengthOfStr == 0) { // should be a leaf
                                                                                                    // node
                // found our place to insert
                Node temp = new Node();
                temp.left = null;
                temp.right = null;
                temp.number = 0;
                temp.value = c;
                root.left = temp;
                // move forward to the temp var
                root = root.right;
                root = hold;
                lengthOfStr--;
            } else if (binaryRep[k].charAt(i) == '1' && root.right == null) {
                // found our place to insert
                Node temp = new Node();
                temp.left = null;
                temp.right = null;
                temp.number = 1;
                temp.value = null;
                root.right = temp;
                // move forward to the temp var
                root = root.right;
                lengthOfStr--;
            } else if (binaryRep[k].charAt(i) == '0' && root.left == null) {
                // found our place to insert
                Node temp = new Node();
                temp.left = null;
                temp.right = null;
                temp.number = 0;
                temp.value = null;
                root.left = temp;
                // move forward to the temp var
                root = root.left;
                lengthOfStr--;
            }
        }
        k++;
    }
    return root;
}


}

【问题讨论】:

    标签: java huffman-code


    【解决方案1】:

    您认为您可以通过每个字符的二进制字符串的长度来做到这一点,这是正确的。 许多执行 Huffman 压缩的程序在文件的开头(或在文件大块的开头)存储一个短标题。 通常,压缩器和解压缩器同意使用“canonical Huffman codes”。 那么头部只需要存储明文中实际使用了哪些符号,以及每个符号的霍夫曼码的长度(以位为单位)。

    仅给定明文中使用的符号及其排名,无法解码 Huffman 压缩文件。如果您有 5 个不同的符号,则霍夫曼树将包含 5 个不同的位序列 - 但是,霍夫曼算法生成的确切位序列取决于确切的频率。一个文档的符号计数可能为 { 10, 10, 20, 40, 80 },导致 Huffman 位序列 {0000 0001 001 01 1 }。另一个文档可能有 {40, 40, 79, 79, 80} 的符号计数,导致霍夫曼比特序列 {000 001 01 10 11}。尽管这两种情况都恰好有 5 个唯一符号,按相同顺序排列,但在这两个压缩文档中,最频繁符号的实际 Huffman 代码非常不同——一个文档中的 Huffman 代码“1”,Huffman 代码“ 11" 在另一个文件中。 (Maximum number of different numbers, Huffman Compression)。

    相关:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多