compresión de codificación hoffman, cadena de descompresión

package org.structure.hoffmanCode;

import java.util.*;

/**
 * hoffman  字符串压缩与解压压缩编码,
 * @author cjj_1
 * @date 2020-08-26 11:39
 */
public class HoffmanCode {
    
    
    public static void main(String[] args) {
    
    
        String str = "i like like like like you";
        byte[] bytes = str.getBytes();//获取字符串的字节数组
       List<Node> nodes = getByteNodes(bytes);//把每个字节包装成一个node,则字节数组转换为一个list<Node>
      Node node = realizeHoffman(nodes);//把node节点转换成hoffman 树
       Map<Byte,String> map = getHoffmanCode(node,"",stringBuilders);//获取字符的hoffman编码表;
        System.out.println("hoffman 编码序列:"+stringBuilders.toString());
        byte[] res=  zip(bytes,map);
        byte[]  restoreBytes = decode(res,map,bytes.length);
        System.out.println(new String(restoreBytes));
    }

    static  Map<Byte,String> charPath = new HashMap<>();
    static  StringBuilder stringBuilders = new StringBuilder();
    /**
     * 把byte 转换成hoffman编码序列,根据hoffman编码序列还原出对应的字符串
     * @param bs
     * @param map
     * @param length
     * @return
     */
    public static byte[] decode(byte[] bs, Map<Byte, String> map, int length){
    
    
        StringBuilder sb = new StringBuilder();
        boolean flag;
        //构建hoffman编码序列
        for(int i =0;i<bs.length;i++){
    
    
            flag = (i==bs.length);
            sb.append(byte2BitString(bs[i],!flag));
        }
        System.out.println("hoffman序列:"+sb.toString());
        //hoffman序列 转换 成对应的字符串
        //Map<Byte,String> 反转 key 与 value
        Map<String,Byte> hoffmanCodeToByte = new HashMap<>();
        for(Map.Entry<Byte,String> entry:map.entrySet()){
    
    
            hoffmanCodeToByte.put(entry.getValue(),entry.getKey());
        }
        byte[] bytes = new byte[length+1];
        int index =0;
        for (int j=0;j<sb.length();){
    
    
            int count=j+1;
            String str= "";
            Byte b;
            boolean flag1 = Boolean.TRUE;
            while (flag1){
    
    
                str = sb.substring(j,count);
               b= hoffmanCodeToByte.get(str);
               if(b==null){
    
    
                   count++;
               }else {
    
    
                   flag1 =  Boolean.FALSE;
               }
            }
            byte ch = hoffmanCodeToByte.get(str);
            bytes[index] = ch;
            index++;
            j=count;
        }
        return bytes;
    }

    /**
     * 字节转换成二进制字符串(0与1表示)
     * @param b
     * @param flag
     * @return
     */
    public static String byte2BitString(byte b,boolean flag){
    
    
        String bitString;
        int temp = b;
        if(flag) {
    
    
            temp |= 256;
        }
        bitString = Integer.toBinaryString(temp);
        if(flag)
            return bitString.substring(bitString.length()-8);
        else return bitString;
    }
    //把赫夫曼编码 开始压缩
    public static byte[] zip(byte[] bytes, Map<Byte,String> hoffmancode){
    
    
        StringBuilder sb = new StringBuilder();
        for(Byte b:bytes){
    
    
           String hoffmanpath = hoffmancode.get(b);
            sb.append(hoffmanpath);
        }
        System.out.println(sb);
        int len;
        if(sb.length()%8==0)
            len = sb.length()/8;
        else
            len = sb.length()/8 +1;
        byte[] hoffmanByte = new byte[len];
        int index =0;
        for (int i =0;i<sb.length();i+=8){
    
    
            byte b;
            if((i+8)>sb.length()){
    
    
                b = (byte)Integer.parseInt(sb.substring(i,sb.length()),2);
            }else {
    
    
                b = (byte)Integer.parseInt(sb.substring(i,i+8),2);
            }
            hoffmanByte[index++]= b;
        }
        return hoffmanByte;
    }

    /**
     * hoffMan编码字典
     * @param root
     * @param code
     * @param stringBuilder
     * @return
     */
    public static Map<Byte, String> getHoffmanCode(Node root, String code, StringBuilder stringBuilder){
    
    
        StringBuilder sb = new StringBuilder();
        sb.append(stringBuilder.toString()).append(code);
        if(root.data == null){
    
    
            getHoffmanCode(root.left,"0",sb);
            getHoffmanCode(root.right,"1",sb);
        }else {
    
    
            charPath.put(root.data,sb.toString());
            stringBuilders.append(sb.toString());
        }
        return charPath;
    }
    /**
     * 获取每个字符的个数
     * @param bytes
     * @return
     */
    public static List<Node> getByteNodes(byte[] bytes){
    
    

       List<Node> nodes = new ArrayList<>();
        Map<Byte,Integer> nodeCounts = new HashMap<>();
        for (Byte b:bytes){
    
    
            Integer byteCount = nodeCounts.get(b);
            if(byteCount == null){
    
    
                nodeCounts.put(b,1);
            }else {
    
    
                nodeCounts.put(b,++byteCount);
            }
        }
        for(Map.Entry<Byte,Integer> entry:nodeCounts.entrySet()){
    
    
            nodes.add(new Node(entry.getKey(),entry.getValue()));
        }
        System.out.println(nodes);
        return nodes;
    }
    public static Node realizeHoffman(List<Node> nodes){
    
    
        while (nodes.size()>1){
    
    
            Collections.sort(nodes);
            Node leftNode = nodes.get(0);
            Node rightNode = nodes.get(1);
            Node parent  = new Node(leftNode.weight+rightNode.weight);
            parent.left = leftNode;
            parent.right = rightNode;
            nodes.add(parent);
            nodes.remove(0);
            nodes.remove(0);
        }
        return nodes.get(0);
    }
}
class Node implements  Comparable<Node>{
    
    
    Byte data;
    int weight;
    Node left;
    Node right;
    public Node(int weight){
    
    
        this.weight = weight;
    }
    public Node(Byte data,int weight){
    
    
        this.data = data;
        this.weight = weight;
    }
    @Override
    public String toString() {
    
    
        return "Node{" +
                "data=" + data +
                ", weight=" + weight +
                '}';
    }
    /**
     * 实现接口
     * @param o
     * @return
     */
    @Override
    public int compareTo(Node o) {
    
    
        return this.weight - o.weight;
    }

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

Supongo que te gusta

Origin blog.csdn.net/weixin_40128696/article/details/108284769
Recomendado
Clasificación