Java——数据结构与算法(哈夫曼编码)(基础学习)

哈夫曼编码

基本介绍:

  1. 广泛应用于数据文件压缩,压缩率在20%~90%之间。
  2. 是可变字长编码(VLC)的一种,也称为最佳编码。

原理剖析步骤:

  1. I like like like java do you like a java
  2. d:1 y:1 u:1 j:2 v:2 o:2 l:4 k:4 e:4 i:5 a:5 :9
  3. 按照上面的字符出现的次数构建一颗哈夫曼树,次数作为权值。
  4. 哈夫曼树构建过程步骤看上篇
  5. 根据哈夫曼树给各个字符固定编码(前缀编码),左0又1。
    例如:o:1000 v:0001

注意:

这个赫夫曼树根据排序方法不同,也可能不太一样,这样对应的赫夫曼编码也不完全一样,但是wpl是一样的,都是最小的,最后生成的赫夫曼编码的长度是一样。

在这里插入图片描述
代码:

package huffmancode;

import java.lang.reflect.Array;
import java.util.*;

public class HuffmanCode {
    public static void main(String[] args) {
        String content = "i like like like java do you like a java";
        byte[] contentBytes = content.getBytes();
        System.out.println(contentBytes.length);

        List<Node> nodes = getNodes(contentBytes);
        System.out.println("nodes = "+ nodes);

        //构建哈夫曼树
        System.out.println("哈夫曼树");
        Node huffmanTreeRoot = createHuffmanTree(nodes);
        huffmanTreeRoot.preOrder();
    }
    //前序遍历
    public static void preOrder(Node root){
        if (root != null){
            root.preOrder();
        }else {
            System.out.println("哈夫曼树为空!");
        }
    }

    /**
     *
     * @param byte 接收字节数组
     * @return List形式Node
     */
    private static List<Node> getNodes(byte[] bytes){
            //nodes数组接受byte[]对象
        ArrayList<Node> nodes = new ArrayList<>();
        //存储每一个byte出现的次数->map[key,value]
        Map<Byte,Integer> counts = new HashMap<>();
        for (byte b: bytes){
            Integer count = counts.get(b);
            if (count == null){
                counts.put(b,1);
            }else {
                counts.put(b,++count);
            }
        }
        //把每个键值对转换成Node对象,并加入nodes集合
        for (Map.Entry<Byte,Integer> entry: counts.entrySet()){
            nodes.add(new Node(entry.getKey(),entry.getValue()));
        }
        return nodes;
    }

    //通过List,创建对应的哈夫曼树
    private static Node createHuffmanTree(List<Node> nodes){
        while(nodes.size() > 1){
            //排序,从小到大
            Collections.sort(nodes);
            //取出最小和次小的二叉树
            Node leftNode = nodes.get(0);
            Node rightNode = nodes.get(1);
            //创建一颗新的二叉树,没有data,只有权值
            Node parent = new Node(null, leftNode.weigh+ rightNode.weigh);
            parent.left = leftNode;
            parent.right = rightNode;
            //移除已经处理的这两颗二叉树
            nodes.remove(leftNode);
            nodes.remove(rightNode);
            //将新的二叉树加入
            nodes.add(parent);
        }
        //返回nodes结点,是哈夫曼树的跟结点
        return nodes.get(0);

    }
}


//创建Node,数据 和权值
class Node implements Comparable<Node>{
    Byte data;  //存放数据(字符)本身。例如:‘a’ => 97
    int weigh;
    Node left;
    Node right;

    public Node(Byte data, int weigh) {
        this.data = data;
        this.weigh = weigh;
    }

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

    @Override
    public String toString() {
        return "Node{" +
                "data=" + data +
                ", weigh=" + weigh +
                '}';
    }

    public void preOrder(){
        System.out.println(this);
        if (this.left != null){
            this.left.preOrder();
        }
        if (this.right != null){
            this.right.preOrder();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值