• 请设计一个算法,给一个字符串进行二进制编码,使得编码后字符串的长度最短。(哈夫曼树)


    请设计一个算法,给一个字符串进行二进制编码,使得编码后字符串的长度最短。

    输入描述:
    每组数据一行,为待编码的字符串。保证字符串长度小于等于1000。
    输出描述:
    一行输出最短的编码后长度。
    输入例子:
    MT-TECH-TEAM
    输出例子:
    33
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.Map.Entry;
    import java.util.PriorityQueue;
    import java.util.Scanner;
    
    public class Main {
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNext()) {
                String s = scanner.next();
                System.out.println(createHuffman(s));
            }
        }
        public static int createHuffman(String s) {
            char[] chars = s.toCharArray();
             //hash表存放每个字符和出现的次数(出现的次数就是权重)
            HashMap<Character, Integer> map = new HashMap<Character, Integer>();
            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);
                }
            }
            //优先队列(最小推),每次能得到weigh最小的node
            PriorityQueue<HuffmanNode> queue = new PriorityQueue<>(map.size(), new Comparator<HuffmanNode>() {
                @Override
                public int compare(HuffmanNode o1, HuffmanNode o2) {
                    // TODO Auto-generated method stub
                    return o1.weight - o2.weight;
                }
            });
            //构建哈夫曼树合并两个权重最小的节点,直到只剩下根节点root
            for(Entry<Character, Integer> entry : map.entrySet()){
                queue.offer(new HuffmanNode(entry.getValue(), entry.getKey()));
            }
            while(queue.size() > 1){
                //弹出两个权重最小的,合并为一个node
                HuffmanNode leftNode = queue.poll();
                HuffmanNode rightNode = queue.poll();
                HuffmanNode fatherNode = new HuffmanNode(leftNode.weight + rightNode.weight);
                fatherNode.left = leftNode;
                fatherNode.right = rightNode;
                queue.offer(fatherNode);
            }
            HuffmanNode root = queue.poll();
            return getLength(root, 0);
    
        }
        public static int getLength(HuffmanNode node, int depth) {
            if(node == null){ //仅计算ch有值的
                return 0;
            }
            return (node.ch == null ? 0:node.weight)*depth + getLength(node.left, depth+1) + getLength(node.right, depth+1);
        }
    }
    class HuffmanNode{
        int weight;//权重(字符出现次数)
        HuffmanNode left;
        HuffmanNode right;
        Character ch; //如果是初始字符,则ch为字符,如果是合并的,则为null
        public HuffmanNode(int weight) {
            super();
            this.weight = weight;
        }
        public HuffmanNode(int weight, char ch) {
            super();
            this.weight = weight;
            this.ch = ch;
        }
    }
    

      



  • 相关阅读:
    函数数组
    编译和链接
    线程详解
    linux内核完全剖析——基于0.12内核-笔记(2)-统一编址和独立编址
    linux内核完全剖析——基于0.12内核-笔记(1)-CPU 数据通信
    input子系统事件处理层(evdev)的环形缓冲区【转】
    NFC驱动调试
    little kernel 小结
    Linux 设备树的解释
    Android中SELinux的TE简介【转】
  • 原文地址:https://www.cnblogs.com/GumpYan/p/5861605.html
Copyright © 2020-2023  润新知