题目
请设计一个算法,给一个字符串进行二进制编码,使得编码后字符串的长度最短。(哈夫曼树)
输入描述:
每组数据一行,为待编码的字符串。保证字符串长度小于等于1000。
输出描述:
一行输出最短的编码后长度。
输入例子:
MT-TECH-TEAM
输出例子:
33
解题思路
哈夫曼树
算法
public class class1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
String s = scanner.next();
System.out.println(createHuf(s));
}
}
public static int createHuf(String s){
char[] chars = s.toCharArray();
HashMap<Character,Integer> map = new HashMap<>();
for (int i = 0; i < chars.length; i++) {
if(map.containsKey(chars[i])){
map.put(chars[i],map.get(chars[i])+1);
}else {
map.put(chars[i],1);
}
}
PriorityQueue<HufNode> queue = new PriorityQueue<>(map.size(), Comparator.comparingInt(o -> o.w));
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
queue.offer(new HufNode(entry.getValue(),entry.getKey()));
}
while (queue.size()>1){
HufNode lnode = queue.poll();
HufNode rnode = queue.poll();
HufNode fatherNode = new HufNode(lnode.w+rnode.w);
fatherNode.l = lnode;
fatherNode.r = rnode;
queue.offer(fatherNode);
}
HufNode root = queue.poll();
return getLength(root,0);
}
public static int getLength(HufNode node,int depth){
if(node==null){
return 0;
}else {
return (node.ch==null?0:node.w)*depth+getLength(node.l,depth+1)+getLength(node.r,depth+1);
}
}
static class HufNode{
int w;
HufNode l;
HufNode r;
Character ch;
public HufNode(int w) {
this.w = w;
}
public HufNode(int w, Character ch) {
this.w = w;
this.ch = ch;
}
}
}
思路:
- 将字符串中所有字符出现的频率存放在HashMap中
- 对字符按照频率排序(直接将其入队到优先级队列中)
- 依次取出两个频率最低的,生成父亲节点,父亲节点权值为子节点权值和,父节点入优先级队列
- 重复步骤3 直到优先级队列中只剩下根节点。
- 根据根节点,前序遍历找到所有节点频率×层数和