哈夫曼编码 Java

package huffmancode;

import org.omg.CORBA.INTERNAL;

import java.util.*;

/**
 * @author Xiaotong Xu
 * @create 2021-06-19 16:14
 */
public class HuffmanCode {
    public static void main(String[] args) {
        String str = "i like like like java do you like a java";
        byte[] bytes = huffmanZip(str);
        System.out.println(Arrays.toString(bytes));

        byte[] bytes1 = byteToString(huffmanCode, bytes);
        System.out.println(new String(bytes1));

    }

    //解码
    public static byte[] byteToString(Map<Byte, String> huffmanCode, byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        String s;
        for (int i = 0; i < bytes.length; i++) {
            int ints = bytes[i]; //补码
            if (i != bytes.length - 1) {
                ints |= 256;  //补位处理
                s = Integer.toBinaryString(ints);  //转换为ints形式的补码
                s=s.substring(s.length()-8);

            } else {
                s = Integer.toBinaryString(ints);
            }

            builder.append(s);
        }
        Map<String,Byte> map=new HashMap<>();
        List<Byte> list=new ArrayList();
        for(Map.Entry<Byte,String> entry :huffmanCode.entrySet()){
            map.put(entry.getValue(),entry.getKey());
        }
        for(int i=0;i<builder.length();){
            int count=0;
            boolean flag=true;
            while(flag){
                String s1=builder.substring(i,i+count);
                if(map.get(s1)==null){
                    count++;
                }else{
                    list.add(map.get(s1));
                    flag=false;
                }
            }
            i=i+count;
        }
        byte[] bytesDecode=new byte[list.size()];
        for(int i=0;i<list.size();i++){
            bytesDecode[i]=list.get(i);
        }
        return bytesDecode;
    }

    //封装编码所有方法
    public static byte[] huffmanZip(String str) {
        //创建哈夫曼树
        Node huffmanTree = createHuffmanTree(str);
        //转换为哈夫曼编码
        Map<Byte, String> huffmanCode = createHuffmanCode(huffmanTree);
        //转换为二进制压缩编码
        byte[] bytes = huffmanCodeZip(str, huffmanCode);
        return bytes;

    }

    //压缩数据
    public static byte[] huffmanCodeZip(String str, Map<Byte, String> huffmanCode) {
        byte[] bytes = str.getBytes();
        StringBuilder builder = new StringBuilder();
        for (byte b : bytes) {
            builder.append(huffmanCode.get(b));
        }
        int len = (builder.length() + 7) / 8;
        byte[] huffmanZipByte = new byte[len];
        int index = 0;
        for (int i = 0; i < builder.length(); i += 8) {
            if (i + 8 > builder.length()) {
                huffmanZipByte[index] = (byte) Integer.parseInt(builder.substring(i), 2);  
                //转换为byte,将数字看成要转换的byte型的带符号的补码

            } else {
                huffmanZipByte[index] = (byte) Integer.parseInt(builder.substring(i, i + 8), 2);
                index++;
            }
        }
        return huffmanZipByte;
    }

    //创造二进制编码
    static StringBuilder builder = new StringBuilder();
    static Map<Byte, String> huffmanCode = new HashMap<>();

    public static Map<Byte, String> createHuffmanCode(Node root) {
        if (root == null) {
            System.out.println("此二叉树为空");
            return null;
        } else {
            createHuffmanCode(root.left, "0", builder);
            createHuffmanCode(root.right, "1", builder);
        }
        return huffmanCode;
    }

    public static void createHuffmanCode(Node node, String code, StringBuilder stringBuilder) {
        StringBuilder builder1 = new StringBuilder(stringBuilder);
        builder1.append(code);
        if (node != null) {
            if (node.value == null) {

                createHuffmanCode(node.left, "0", builder1);

                createHuffmanCode(node.right, "1", builder1);
            } else {
                huffmanCode.put(node.value, builder1.toString());
            }

        }
    }

    //传入数据 得到哈夫曼树
    public static Node createHuffmanTree(String str) {
        byte[] content = str.getBytes();
        Map<Byte, Integer> map = new HashMap<>();
        for (Byte b : content) {
            Integer count = map.get(b);
            if (count == null) {
                map.put(b, 1);
            } else {
                map.put(b, count + 1);
            }
        }

        List<Node> nodes = new ArrayList();
        for (Map.Entry<Byte, Integer> entry : map.entrySet()) {
            Node node = new Node(entry.getKey(), entry.getValue());
            nodes.add(node);
        }
        while (nodes.size() > 1) {
            Collections.sort(nodes);
            Node leftNode = nodes.get(0);
            Node rightNode = nodes.get(1);
            Node parent = new Node(null, rightNode.wight + leftNode.wight);
            parent.left = leftNode;
            parent.right = rightNode;
            nodes.remove(rightNode);
            nodes.remove(leftNode);
            nodes.add(parent);
        }
        return nodes.get(0);
    }

    public static void proOrder(Node root) {
        if (root == null) {
            System.out.println("此二叉树为空");
        } else {
            root.proOrder();
        }
    }
}

class Node implements Comparable<Node> {
    int wight;
    Byte value;
    Node left;
    Node right;

    public Node(Byte value, int wight) {
        this.wight = wight;
        this.value = value;
    }

    public void proOrder() {
        System.out.println(this);
        if (this.left != null) {
            this.left.proOrder();
        }
        if (this.right != null) {
            this.right.proOrder();
        }
    }

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

    @Override
    public int compareTo(Node o) {
        return this.wight - o.wight;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值