生成哈夫曼树及其编码

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();
        }


    };
    


}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值