1 はじめに
1.1 ハフマン木
- ハフマン木最適二分木: 木の重み付き経路長が最小の二分木。
- 重みはすべてリーフ ノードです。
- 重みが大きいほど、ノードはルート ノードに近くなります。
1.2 パス、パス長、ノード重み、ノード重み付きパス長
1.3 ツリーの加重パス長 WPL
2. ハフマンツリー構築手順
- 重みシーケンスを昇順に並べ、マージする 2 つの最小の重みを選択します。
- マージされたノードをウェイト シーケンスに追加し、順序を変更します。
- シーケンス内にノードが 1 つだけ残るまで上記 2 つの操作を繰り返し、作成を完了します。
- 上記の場合の手動ビルド結果:
3. コードの実装
package com.northsmile.tree.huffman;
import java.util.*;
public class HuffmanTree {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=Integer.parseInt(scanner.nextLine());
List<TreeNode> nodes=new LinkedList<>();
for (int i=0;i<n;i++){
nodes.add(new TreeNode(Integer.parseInt(scanner.nextLine())));
}
root=createHuffmanTree(nodes);
System.out.println(calWPL());
}
private static TreeNode root;
public static TreeNode createHuffmanTree(List<TreeNode> nodes){
while (nodes.size()!=1){
nodes.sort(new Comparator<TreeNode>() {
@Override
public int compare(TreeNode o1, TreeNode o2) {
return o1.val-o2.val;
}
});
TreeNode left=nodes.get(0);
TreeNode right=nodes.get(1);
TreeNode curRoot = new TreeNode(left.val+right.val);
curRoot.left=left;
curRoot.right=right;
nodes.add(curRoot);
nodes.remove(0);
nodes.remove(0);
}
return nodes.get(0);
}
public static int calWPL(){
int wpl=0;
Deque<TreeNode> queue=new ArrayDeque<>();
queue.offer(root);
int height=0;
while (!queue.isEmpty()){
int size=queue.size();
for (int i=0;i<size;i++){
TreeNode cur = queue.pop();
if (cur.left==null&&cur.right==null){
wpl+=(cur.val*height);
}
if (cur.left!=null){
queue.offer(cur.left);
}
if (cur.right!=null){
queue.offer(cur.right);
}
}
height++;
}
return wpl;
}
private static class TreeNode{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val){
this.val=val;
}
}
}