請設計一個算法,給一個字符串進行二進制編碼,使得編碼後字符串的長度最短。(哈夫曼樹)

請設計一個算法,給一個字符串進行二進制編碼,使得編碼後字符串的長度最短。java

輸入描述:
每組數據一行,爲待編碼的字符串。保證字符串長度小於等於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;
    }
}
相關文章
相關標籤/搜索