重新做:Java编写哈夫曼编码,要求输入待编码的个数、输入符号、输入各符号的概率
时间: 2024-03-07 15:47:35 浏览: 41
好的,我可以帮你回答这个问题。
Java中实现哈夫曼编码的过程主要分为两个步骤:
1. 生成哈夫曼树
输入待编码的个数、输入符号、输入各符号的概率,可以通过创建一个符号类来实现。符号类包含两个属性:符号和概率。然后,我们可以使用一个优先队列来存储所有的符号类对象,并按照概率从小到大排序。接下来,我们可以循环遍历优先队列,每次取出两个概率最小的符号类,将它们合并成一个新的符号类,并将新符号类的概率设置为两个原始符号类概率的和。将新符号类加入优先队列中,直到队列中只有一个符号类为止,这个符号类就是哈夫曼树的根节点。
2. 编码
哈夫曼树构建完成后,我们可以根据哈夫曼树生成编码表。从根节点开始,遍历哈夫曼树,将左子树标记为0,右子树标记为1,直到叶子节点。叶子节点的编码就是从根节点到叶子节点路径上的所有标记的拼接。将每个符号的编码存储在一个哈希表中,符号作为键,编码作为值。
最后,我们可以使用编码表将输入的符号编码成二进制字符串。
下面是一个简单的Java代码示例,可以帮助你更好地理解上述过程:
```
import java.util.*;
public class Huffman {
private static class Symbol implements Comparable<Symbol> {
char symbol;
double freq;
Node node;
public Symbol(char symbol, double freq) {
this.symbol = symbol;
this.freq = freq;
this.node = new Node(symbol, freq);
}
@Override
public int compareTo(Symbol o) {
return Double.compare(this.freq, o.freq);
}
}
private static class Node {
char symbol;
double freq;
Node left;
Node right;
public Node(char symbol, double freq) {
this.symbol = symbol;
this.freq = freq;
}
public Node(Node left, Node right) {
this.freq = left.freq + right.freq;
this.left = left;
this.right = right;
}
public boolean isLeaf() {
return left == null && right == null;
}
}
public static Map<Character, String> encode(List<Symbol> symbols) {
PriorityQueue<Node> pq = new PriorityQueue<>(Comparator.comparingDouble(n -> n.freq));
for (Symbol symbol : symbols) {
pq.offer(symbol.node);
}
while (pq.size() > 1) {
Node left = pq.poll();
Node right = pq.poll();
Node parent = new Node(left, right);
pq.offer(parent);
}
Node root = pq.poll();
Map<Character, String> encodingTable = new HashMap<>();
encodeHelper(root, "", encodingTable);
return encodingTable;
}
private static void encodeHelper(Node node, String code, Map<Character, String> encodingTable) {
if (node.isLeaf()) {
encodingTable.put(node.symbol, code);
return;
}
encodeHelper(node.left, code + "0", encodingTable);
encodeHelper(node.right, code + "1", encodingTable);
}
public static void main(String[] args) {
List<Symbol> symbols = new ArrayList<>();
symbols.add(new Symbol('A', 0.5));
symbols.add(new Symbol('B', 0.25));
symbols.add(new Symbol('C', 0.125));
symbols.add(new Symbol('D', 0.125));
Map<Character, String> encodingTable = encode(symbols);
System.out.println(encodingTable);
}
}
```
在这个示例中,我们首先定义了一个符号类,其中包含符号和概率两个属性。然后,我们使用优先队列来存储所有的符号类对象,并按照概率从小到大排序。接着,我们循环遍历优先队列,每次取出两个概率最小的符号类,将它们合并成一个新的符号类,并将新符号类的概率设置为两个原始符号类概率的和。将新符号类加入优先队列中,直到队列中只有一个符号类为止,这个符号类就是哈夫曼树的根节点。
在哈夫曼树构建完成后,我们可以根据哈夫曼树生成编码表。从根节点开始,遍历哈夫曼树,将左子树标记为0,右子树标记为1,直到叶子节点。叶子节点的编码就是从根节点到叶子节点路径上的所有标记的拼接。将每个符号的编码存储在一个哈希表中,符号作为键,编码作为值。
最后,我们可以使用编码表将输入的符号编码成二进制字符串。在这个示例中,我们使用了一个简单的符号集合,包含4个符号,分别是'A'、'B'、'C'和'D',并为每个符号设置了一个简单的频率。我们将符号集合传递给`encode`方法,该方法将返回一个编码表,其中包含每个符号的哈夫曼编码。最后,我们使用`System.out.println`将编码表打印到控制台。