Day579&580.霍夫曼编码 -数据结构和算法Java

Posted 阿昌喜欢吃黄桃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day579&580.霍夫曼编码 -数据结构和算法Java相关的知识,希望对你有一定的参考价值。

霍夫曼编码

一、介绍

利用霍夫曼树,来构建或形成的一种编码【程序算法

二、原理剖析

1、定长编码

通过英文对照转换为Ascii码对应的二进制

2、变长编码

根据字符出现的次数,来规定对应的二进制值,出现的越多,二进制值越小,并最后根据数值对应转化

存在匹配的多异性

3、霍夫曼编码(无损压缩)

统计各个字符出现的个数,根据出现的字符出现的次数来构建一颗霍夫曼数,次数作为权值;

根据上面构建的霍夫曼树,给一个个字符构建编码,树中朝左边的为0,朝右边的为1,他是前缀编码


  • 注意点
    当对应字符出现的次数一样的情况,会出现霍夫曼编码不完全一样的情况

三、实现案例需求

四、思路分析

五、代码实现

package com.achang.hufumancode;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 霍夫曼编码
 */
public class HuffmanCode 

    static HashMap<Byte, String> huffManCodeMap = new HashMap<>();
    static StringBuffer sb = new StringBuffer();

    public static void main(String[] args) 
        String msg = "i like like like java do you like a java";
        byte[] strBytes = msg.getBytes(StandardCharsets.UTF_8);
        System.out.println("未压缩长度为:" + strBytes.length);

        List<Node> nodes = getNodes(strBytes);
        System.out.println(nodes);

        Node huffmanTreeNode = buildHuffmanTree(nodes);
        System.out.println("霍夫曼树的前序遍历:↓");
        huffmanTreeNode.preOrder();
        getCodes(huffmanTreeNode);
        System.out.println("======生成的霍夫曼编码表:↓=======");
        System.out.println(huffManCodeMap);
    


    static HashMap<Byte, String> getCodes(Node nodeRoot)
        if (nodeRoot == null)
            return null;
        else 
            getCodes(nodeRoot.left,"",sb);
            getCodes(nodeRoot.right,"",sb);
        
        return huffManCodeMap;
    

    //生成霍夫曼树对应的霍夫曼编码
    static void getCodes(Node node,String code,StringBuffer sb)
        StringBuffer stringBuffer = new StringBuffer(sb);
        stringBuffer.append(code);
        if (node != null)
            if (node.data == null)//非叶子节点
                getCodes(node.left,"0",stringBuffer);//向左递归
                getCodes(node.right,"1",stringBuffer);//向右递归
            else //叶子节点
                huffManCodeMap.put(node.data,stringBuffer.toString());
            
        
    

    //获取对应数组对应字符出现的次数,并转成Node节点的集合
    static List<Node> getNodes(byte[] strBytes) 
        ArrayList<Node> nodes = new ArrayList<>();
        HashMap<Byte, Integer> countMap = new HashMap<>();

        for (byte strByte : strBytes) 
            Integer count = countMap.get(strByte);
            if (count == null) 
                count = 1;
             else 
                count++;
            
            countMap.put(strByte, count);
        
        for (Map.Entry<Byte, Integer> byteIntegerEntry : countMap.entrySet()) 
            nodes.add(new Node(byteIntegerEntry.getKey(), byteIntegerEntry.getValue()));
        
        return nodes;
    

    //构建霍夫曼树
    static Node buildHuffmanTree(List<Node> list) 
        while (list.size() > 1) 
            Collections.sort(list);
            Node leftNode = list.get(0);
            Node rightNode = list.get(1);
            //根节点只有权值,没有data
            Node parent = new Node(null, leftNode.weight + rightNode.weight);
            parent.left = leftNode;
            parent.right = rightNode;

            list.remove(leftNode);
            list.remove(rightNode);
            list.add(parent);
        
        return list.get(0);
    



class Node implements Comparable<Node> 
    Byte data;//阿斯克码存储
    int weight;//权值,数据出现的次数
    Node left;
    Node right;

    public Node(Byte data, int weight) 
        this.data = data;
        this.weight = weight;
    

    @Override
    public int compareTo(Node o) 
        //从小到大排序
        return this.weight - o.weight;
    

    @Override
    public String toString() 
        return "Node【data=" + data + ",weight=" + weight + "】";
    

    //前序遍历
    public void preOrder() 
        System.out.println(this);
        if (left != null) 
            this.left.preOrder();
        
        if (right != null) 
            this.right.preOrder();
        
    





以上是关于Day579&580.霍夫曼编码 -数据结构和算法Java的主要内容,如果未能解决你的问题,请参考以下文章

Day10 树---哈夫曼树 家谱处理 搜索树判断 目录树

Day10 树---哈夫曼树 家谱处理 搜索树判断 目录树

哈夫曼编码压缩解压缩实现&不同类型文件压缩比的测试

哈夫曼树和哈夫曼编码

视频编解码·学习笔记7. 熵编码算法:基础知识 & 哈夫曼编码

习题:荷马史诗(哈夫曼树&贪心)