我得到一个字符串,我必须编码和解码使用哈夫曼树的思想。原始字符串作为文件上传,encode方法的返回是一个新文件,依次包含翻译表和编码消息。
下面是一个输出文件将包含的内容的示例。
{0=0100, 1=0111, 2=11, 3=00, 4=10, 5=0110, =0101}
0110101100111101110100011100111000100011001011100101
我的编码方法:
Map<Character, Integer> freq = new HashMap<>(); //store char, freq in map
for (char c: message.toCharArray()) { //thank you enhanced for loop
freq.put(c, freq.getOrDefault(c, 0) + 1);
}
//queue stores nodes
PriorityQueue<Node> pq;
pq = new PriorityQueue<>(Comparator.comparingInt(l -> l.freq));
//nodes will be sorted by comparator
//using hashmap we add the nodes to the queue
for (var entry : freq.entrySet()) {
pq.add(new Node(entry.getKey(), entry.getValue()));
}
while (pq.size() != 1) //must be more than 1 node
{
//removes the two nodes of lowest freq
Node left = pq.poll();
Node right = pq.poll();
//connect new nodes
int sum = left.freq + right.freq; //summary of freq, for parent
pq.add(new Node('\0', sum, left, right)); //add back
}
//root of tree
Node root = pq.peek();
//new map for huffman codes
Map<Character, String> huffmanCode = new HashMap<>();
coding(root, "", huffmanCode);
//testing
//print the Huffman codes so we can know them (move this later)
//System.out.println("Huffman code is " + huffmanCode);
//testing
//print encoded message
StringBuilder sb = new StringBuilder();
for (char c: message.toCharArray()) {
sb.append(huffmanCode.get(c));
}
//System.out.println("Encoded string is : " + sb); //check file format
Pair<Map,StringBuilder> p = new Pair<Map,StringBuilder>(huffmanCode,sb);
return p;
我在main方法中将这一对转换成一个字符串。
为了解码这个字符串,我应该重新上传文件,并使用它所包含的信息创建一个新的文件与原始未编码的消息。如果不是因为上传的要求,我在解码信息时不会有问题。我失去了对我以前编码的哈夫曼树的访问,并且我无法将它保存在输出文件中,因为我只需要返回字符串。
我尝试过从表中拆分字符串并向后工作,但是没有树,我真的很难在没有哈夫曼树的情况下解码字符串。有没有办法在输出文件中保留树,或者有没有办法使用转换表重建树?谢谢。
1条答案
按热度按时间olqngx591#
您需要将树表示为字节序列,以便将其写入文件。这当然可以做到,一个例子是给每个节点一个标识号,并将每个节点表示为两个这样的编号和一个符号。
但是,如果您规范地构造huffman代码,则不需要树。为了解码规范的哈夫曼码,您需要发送的唯一信息是每个符号的码长(以位为单位)。这是通常的做法。
代码长度列表本身可以通过多种方式进行压缩,以减少代码描述的开销。