哈夫曼樹及哈夫曼編碼
阿新 • • 發佈:2020-07-25
哈夫曼樹及哈夫曼編碼
哈夫曼樹
基本介紹
- 給定n個葉子結點 ,構造一棵二叉樹。若該樹的帶權路徑長度(wpl)達到最值,則稱這棵樹為最有二叉樹,也稱為哈夫曼樹。
- 哈夫曼樹是帶權路徑長度最短的樹,權值較大點根本較近
- 路徑個路徑長度:在一棵樹中,從一個節點往下可以達到的孩子節點或孫子節點之間的通路。成為路徑,通路中分支的數目成為路徑長度,若規定根節點的層數為1,則從根節點到第L層的節點的路徑長度為L-1
- 結點的權及帶權路徑長度:若將樹中結點賦予一個有某種含義的數值,則這個數值稱為該節點的權,結點的帶權路徑長度為:從根節點到該結點之間的路經長度與該節點的權的乘積。
- 樹的帶權路徑長度:所有葉子節點的帶權路徑長度之和。記作WPL,權值越大的結點越靠近根節點,這棵樹的WPL越小。
- 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()); } } }