1257: 哈夫曼压缩
时间限制: 1 Sec 内存限制: 128 MB
提交: 1052 解决: 711
[提交] [状态] [讨论版] [命题人:外部导入]
题目描述
相信大家都对哈夫曼编码有所了解,通常利用哈夫曼编码来压缩数据。现在给你一个字符串,你需要统计其中字符出现的次数然后以出现次数为权值构建一棵哈夫曼树,例如字符串为ABBCCC,其中一种可能的编码是A = 00,B = 01,C = 1,那么这个字符串所对应的哈夫曼编码就是000101111,你的任务是求出字符串最终形成的哈夫曼编码的长度。
输入
一行由大写字母组成的字符串,且字符串长度不超过10000,该字符串最少包含一种字符。
输出
字符串的哈夫曼编码长度。
样例输入 Copy
ABBCCC
样例输出 Copy
9
来源/分类
import java.util.*;
//1257
// 定义哈夫曼树节点类
abstract class HuffmanTree implements Comparable<HuffmanTree> {
public final int frequency; // 节点权值
public HuffmanTree(int frequency) {
this.frequency = frequency;
}
// 比较节点的权值
public int compareTo(HuffmanTree tree) {
return frequency - tree.frequency;
}
}
// 内部节点类,表示非叶子节点
class InternalNode extends HuffmanTree {
public final HuffmanTree left, right; // 左右子树
public InternalNode(HuffmanTree left, HuffmanTree right) {
super(left.frequency + right.frequency);
this.left = left;
this.right = right;
}
}
// 叶子节点类,表示字符及其权值
class LeafNode extends HuffmanTree {
public final char character; // 字符
public LeafNode(char character, int frequency) {
super(frequency);
this.character = character;
}
}
public class Main {
// 构建哈夫曼树
public static HuffmanTree buildHuffmanTree(String input) {
// 统计字符出现的次数
Map<Character, Integer> frequencyMap = new HashMap<>();
for (char c : input.toCharArray()) {
frequencyMap.put(c, frequencyMap.getOrDefault(c, 0) + 1);
}
// 使用优先队列构建哈夫曼树
PriorityQueue<HuffmanTree> priorityQueue = new PriorityQueue<>();
for (Map.Entry<Character, Integer> entry : frequencyMap.entrySet()) {
priorityQueue.offer(new LeafNode(entry.getKey(), entry.getValue()));
}
// 合并节点直到只剩下一个根节点
while (priorityQueue.size() > 1) {
HuffmanTree left = priorityQueue.poll();
HuffmanTree right = priorityQueue.poll();
priorityQueue.offer(new InternalNode(left, right));
}
return priorityQueue.poll();
}
// 计算哈夫曼编码的长度
public static int calculateHuffmanLength(HuffmanTree tree) {
return calculateHuffmanLength(tree, 0);
}
private static int calculateHuffmanLength(HuffmanTree tree, int depth) {
if (tree instanceof LeafNode) {
return depth * ((LeafNode) tree).frequency;
} else if (tree instanceof InternalNode) {
InternalNode node = (InternalNode) tree;
return calculateHuffmanLength(node.left, depth + 1) + calculateHuffmanLength(node.right, depth + 1);
}
return 0;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine().trim();
HuffmanTree tree = buildHuffmanTree(input);
int huffmanLength = calculateHuffmanLength(tree);
System.out.println(huffmanLength);
}
}