数据结构与算法

 

哈夫曼编码压缩

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);
        byte[] bytes=huffmanZip(contentBytes);
       /* List nodes = getNodes(contentBytes);
        System.out.println(nodes);
        System.out.println("哈夫曼树");
        Node huffmanTreeRoot = createHuffmanTree(nodes);
        System.out.println("前序遍历");
        huffmanTreeRoot.preOrder();
        getCodes(huffmanTreeRoot,"",stringBuilder);
        System.out.println("哈夫曼编码表"+huffmanCodes);
        System.out.println("-------------------------------");
        Map codes = getCodes(huffmanTreeRoot);
        System.out.println(codes);
        System.out.println("--------------------------------");
        byte[] huffmanCodeBytes=zip(contentBytes,huffmanCodes);
        System.out.println("huffmanCodeBytes="+Arrays.toString(huffmanCodeBytes));*/
        System.out.println(Arrays.toString(bytes));

    }
    //将方法封装
    public static byte[] huffmanZip(byte[] bytes){
       //获取结点的Map[key,value]
        List nodes = getNodes(bytes);
        //创建哈夫曼树
        Node huffmanTreeRoot = createHuffmanTree(nodes);
        //获取哈夫曼编码表
        Map codes = getCodes(huffmanTreeRoot);
        //压缩哈夫曼表
        byte[] huffmanCodeBytes=zip(bytes,huffmanCodes);
        return huffmanCodeBytes;
    }

    //将哈夫曼编码表存放在Map形式
    static Map huffmanCodes=new HashMap<>(); //储存着结点的编码信息
    //在生成哈夫曼编码表示,用StringBuilder去拼接,存储某个叶子结点的路径
    static StringBuilder stringBuilder = new StringBuilder(); // 仅仅只是一个空对象,方便传参

    //为了调用方便,重载getCodes
    public static Map getCodes(Node root){
        if(root==null){
            return null;
        }
        //处理root左子树
        getCodes(root.left,"0",stringBuilder);
        //处理root右子树
        getCodes(root.right,"1",stringBuilder);
        return huffmanCodes;
    }


    //获取结点的哈夫曼编码
    public static void getCodes(Node node,String code,StringBuilder stringBuilder){
        StringBuilder stringBuilder1=new StringBuilder(stringBuilder);
        //将code加入到stringBuilder1中
        stringBuilder1.append(code);
        if(node!=null){//如果node==null不处理
            //判断当前node是叶子结点还是非叶子结点
            if(node.data==null){//非叶子结点
                //递归处理
                //向左递归
                getCodes(node.left,"0",stringBuilder1);
                //向右递归
                getCodes(node.right,"1",stringBuilder1);
            }else{//叶子结点
                huffmanCodes.put(node.data,stringBuilder1.toString());
            }

        }
    }

    //将哈夫曼编码压缩
    public static byte[] zip(byte[] bytes,Map huffmanCodes){
        //利用huffmanCodes将bytes转成哈弗曼编码对应字符串
        StringBuilder stringBuilder = new StringBuilder();
        //遍历bytes数组
        for(byte b : bytes){
            stringBuilder.append(huffmanCodes.get(b));
        }
        int length;
        if(stringBuilder.length()%8==0){
            length=stringBuilder.length()/8;
        }else{
            length=stringBuilder.length()/8+1;
        }
        //创建存储压缩后的byte数组
        byte[] huffmanCodeBytes=new byte[length];
        int index=0;//记录是第几个byte
        for(int i=0;istringBuilder.length()){//不够8位
                strByte=stringBuilder.substring(i);
            }else{
                strByte=stringBuilder.substring(i,i+8);
            }
            //将strByte转成一个byte,放入到huffmanCodeBytes
            huffmanCodeBytes[index]=(byte)Integer.parseInt(strByte,2);
            index++;
        }
        return huffmanCodeBytes;
    }
    //前序遍历
    public static void preOrder(Node root) {
        if (root != null) {
            root.preOrder();
        } else {
            System.out.println("哈夫曼树为空");
        }
    }


    //获取结点的Map[key,value]
    public static List getNodes(byte[] bytes) {
        //创建一个ArrayList
        List nodes = new ArrayList<>();
        //遍历bytes,统计每个byte出现的次数->Map[key,value]
        Map counts = new HashMap<>();
        for (byte b : bytes) {
            Integer count = counts.get(b);
            if (count == null) {
                counts.put(b, 1);
            } else {
                counts.put(b, count + 1);
            }
        }
        //遍历map,将每一个键值对转换为Node对象,并加入到nodes集合中
        Set key = counts.keySet();
        for (Byte k : key) {
            nodes.add(new Node(k, counts.get(k)));
        }
        return nodes;
    }

    //创建哈夫曼树
    public static Node createHuffmanTree(List 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.weight + rightNode.weight);
            parent.left = leftNode;
            parent.right = rightNode;
            //将取出的两个结点删除
            nodes.remove(leftNode);
            nodes.remove(rightNode);
            //将新的结点加入
            nodes.add(parent);
        }
        return nodes.get(0);
    }
}

//创建结点
class Node implements Comparable {
    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 (this.left != null) {
            this.left.preOrder();
        }
        if (this.right != null) {
            this.right.preOrder();
        }
    }
}

你可能感兴趣的:(java,jvm,数据结构)