package app;
import java.util.*;
/**
* 题目要求:子树的权重一样,节点数多的放左边,少的放右边,不然,权重大的放右边,权重小的放左边
*
* @Author lyr
* @create 2019/9/30 0:28
*/
public class Main {
public static void main(String[] args) {
String str = "it is a tall ill lia";
// char[] p = str.toLowerCase().replaceAll("\\s+|,","").toCharArray();
char[] p = str.toCharArray();
HashMap<Character,Integer> map = new HashMap(16);
for(char i:p)
{
map.put(i,map.getOrDefault(i,0)+1);
}
LinkedList<Map.Entry<Character, Integer>> list = new LinkedList<>(map.entrySet());
list.sort(v);
list.forEach(k-> System.out.println("字符 "+k.getKey()+" 出现频率为:"+k.getValue()));
TreeNode root = TreeNode.build(list);
TreeNode.preOrderPrint(root);
System.out.println("\r\n哈夫曼编码字典");
TreeNode.createCode(root).forEach((k,v)-> System.out.println(k+": "+v));
}
/**
* 树节点
*/
static class TreeNode implements Comparable<TreeNode>
{
private TreeNode left;
private TreeNode right;
Character data;
int weight;
/**
* 左边字母,右边频率权重
*/
/**
* 二进制编码
*/
TreeNode(Map.Entry<Character,Integer>entry)
{
weight = entry.getValue();
data = entry.getKey();
}
public TreeNode(int weight){this.weight=weight;}
public TreeNode(Character key,int weight) {
data = key;
this.weight = weight;
}
/**
* 建立二叉树
* @param list 字符出现的次数字典
* @return 返回创建的二叉树根节点
*/
public static TreeNode build(LinkedList<Map.Entry<Character,Integer>>list)
{
PriorityQueue<TreeNode> queue = new PriorityQueue<>();
for(Map.Entry<Character,Integer> i:list)
{
TreeNode node = new TreeNode(i);
queue.add(node);
}
while (queue.size()>1)
{
TreeNode left = queue.poll();
TreeNode right = queue.poll();
TreeNode root = new TreeNode(left.weight+right.weight);
root.left = left;
root.right = right;
queue.add(root);
}
return queue.peek();
}
/**
* 根据哈夫曼树的根节点返回生成对应的哈夫曼编码
* @param root 哈夫曼树的根节点
* @return
*/
public static HashMap<Character,String> createCode(TreeNode root)
{
return createCode(root,"",new StringBuilder(),new HashMap(16));
}
public static HashMap<Character,String> createCode(TreeNode root,String code,StringBuilder preFix,HashMap map)
{
// HashMap<Character,String> map = new HashMap<>(16);
if(root==null||map==null)
{
return map;
}
StringBuilder sb = new StringBuilder(preFix).append(code);
if(root.data==null)
{
createCode(root.left,"0",sb,map);
createCode(root.right,"1",sb,map);
}else{
map.put(root.data,sb.toString());
}
return map;
}
public static void preOrderPrint(TreeNode root)
{
if(root==null) {
return;
}
if(root.data!=null)
{
System.out.print(root.data+" ");
}
preOrderPrint(root.left);
preOrderPrint(root.right);
}
/**
* @param root 一棵树的根节点
* @return 该树的节点数
*/
public static int sizeOf(TreeNode root)
{
if(root==null)
{
return 0;
}
return sizeOf(root.left)+sizeOf(root.right)+1;
}
@Override
public int compareTo(TreeNode o) {
if(this.weight==o.weight)
{
return sizeOf(o)-sizeOf(this);
}
//权重一样,按照节点个数比,节点多的放左边
//权重不一样,按照权重比
return this.weight-o.weight;
}
}
static Comparator<Map.Entry<Character, Integer>> v = new Comparator<Map.Entry<Character, Integer>>() {
@Override
public int compare(Map.Entry<Character, Integer> o1,
Map.Entry<Character, Integer> o2) {
return o1.getValue()-o2.getValue();
}
};
}
生成哈夫曼树及其编码
最新推荐文章于 2024-08-11 20:18:31 发布