1. 程式人生 > 實用技巧 >哈夫曼樹及哈夫曼編碼

哈夫曼樹及哈夫曼編碼

哈夫曼樹及哈夫曼編碼

哈夫曼樹

基本介紹

  1. 給定n個葉子結點 ,構造一棵二叉樹。若該樹的帶權路徑長度(wpl)達到最值,則稱這棵樹為最有二叉樹,也稱為哈夫曼樹。
  2. 哈夫曼樹是帶權路徑長度最短的樹,權值較大點根本較近
  3. 路徑個路徑長度:在一棵樹中,從一個節點往下可以達到的孩子節點或孫子節點之間的通路。成為路徑,通路中分支的數目成為路徑長度,若規定根節點的層數為1,則從根節點到第L層的節點的路徑長度為L-1
  4. 結點的權及帶權路徑長度:若將樹中結點賦予一個有某種含義的數值,則這個數值稱為該節點的權,結點的帶權路徑長度為:從根節點到該結點之間的路經長度與該節點的權的乘積。
  5. 樹的帶權路徑長度:所有葉子節點的帶權路徑長度之和。記作WPL,權值越大的結點越靠近根節點,這棵樹的WPL越小。
  6. WPL最小的是哈夫曼樹

哈夫曼樹的建立

 /**
     * 哈夫曼樹的建立
     * @param nodes 一個樹結點組成的集合
     * @return 建立的書的根結點
     */
   public static  HuffmanNode  creatHuffmanTree (ArrayList<HuffmanNode> nodes){
        while (nodes.size()>1){
            //對節點集合進行排序由小到大
            nodes.sort((o1, o2) ->{
                return o1.value-o2.value;
            });

            //取出集合前兩個元素 組成新的節點
            HuffmanNode left = nodes.remove(0);
            HuffmanNode right = nodes.remove(0);
            //新的節點新增到節點集合中
            HuffmanNode father = new HuffmanNode(left.value + right.value);
            father.right=right;
            father.left=left;
            nodes.add(father);
        }

        //返回哈夫曼樹的根結點
        return nodes.get(0);
    }

哈夫曼編碼

哈夫曼編碼是一種字首編碼

字首編碼:是指對字符集進行編碼時,要求字符集中任一字元的編碼都不是其它字元的編碼的字首,例如:設有abcd需要編碼表示(其中,a=0、b=10、c=110、d=11,則表示110的字首可以是c或者da,不唯一)

根據權值,構建以一個哈夫曼樹。 向左的路徑為0向右的路徑為1

壓縮

 //用於儲存生成的哈夫曼編碼
    public static Map<Character,String> codeMap=new HashMap<>();

    public static void main(String[] args) {

        String s="sjdbfsakjfhadbdsfdkjfbkrytnbvyjvblzgvflkvbigadbvklvo";
        char[] chars = s.toCharArray();
        //統計出權重
        Map<Character, Integer> map = calculateWeight(chars);
        //建立哈夫曼結點集合
        ArrayList<HuffmanNode> nodes = new ArrayList<>();
        map.forEach((k,v)-> {
            nodes.add(new HuffmanNode(k,v));
        });
        
        //建立哈夫曼樹
        HuffmanNode root = HuffmanTree.creatHuffmanTree(nodes);

        //生成哈夫曼編碼
        creatHuffmanCode(root,"",new StringBuffer());
        codeMap.forEach((k,v)-> System.out.println("字母:"+k+"-編碼:"+v));


    }

    public static Map<Character,Integer> calculateWeight(char[] arr){

       Map<Character, Integer> map = new HashMap<Character, Integer>();
        for (Character s : arr) {
            Integer weight = map.get(s);
            if (weight==null){
                map.put(s,1);
            }else {
                map.put(s,++weight);
            }
        }
        return map;
    }
    public static void creatHuffmanCode(HuffmanNode node, String code,StringBuffer stringBuffer){
        stringBuffer.append(code);
        if (node!=null){
            if (node.value==null){
                creatHuffmanCode(node.left,"0",stringBuffer);
                creatHuffmanCode(node.right,"1",stringBuffer);
            }else {
                codeMap.put(node.value,stringBuffer.toString());
            }

        }
    }