• 堆排序及哈夫曼编码实现数据压缩


    一.堆排序

            1.将较小的值放在叶子节点

    1. public static void adjustHeap(int arr[], int i, int length) {
    2. int temp = arr[i];
    3. for (int k = i * 2 + 1; k < length; k = k + 2 + 1) {
    4. if (k + 1 < length && arr[k] < arr[k + 1]) {
    5. k++;// 指向右子结点
    6. }
    7. if (arr[k] > temp) {
    8. arr[i] = arr[k];
    9. i = k;
    10. } else {
    11. break;
    12. }
    13. }
    14. arr[i] = temp;
    15. }

            2.进行排序

    1. public static void sort(int[] arr) {
    2. for (int i = arr.length / 2 - 1; i >= 0; i--) {
    3. adjustHeap(arr, i, arr.length);
    4. }
    5. System.out.println(Arrays.toString(arr));//得到大顶堆
    6. for (int i = arr.length - 1; i >= 0; i--) {
    7. int temp = arr[i];
    8. arr[i] = arr[0];
    9. arr[0] = temp;
    10. adjustHeap(arr, 0, i);
    11. }
    12. System.out.println(Arrays.toString(arr));
    13. }

    二.得到哈夫曼编码

    1.获得每个字符的数量

    1. public static List getNodes(byte[] bytes) {
    2. ArrayList nodes = new ArrayList<>();
    3. HashMap map = new HashMap<>();
    4. for (byte b : bytes) {
    5. Integer count = map.get(b);
    6. if (count == null) {
    7. map.put(b, 1);
    8. } else {
    9. map.put(b, count + 1);
    10. }
    11. }
    12. for (Map.Entry entry : map.entrySet()) {
    13. nodes.add(new Node(entry.getKey(), entry.getValue()));
    14. }
    15. return nodes;
    16. }

    2.创建哈夫曼树

    1. public static Node createHuffmanTree(List nodes) {
    2. while (nodes.size() > 1) {
    3. Collections.sort(nodes);
    4. Node leftNode = nodes.get(0);
    5. Node rightNode = nodes.get(1);
    6. Node parent = new Node(null, leftNode.weight + rightNode.weight);
    7. parent.left = leftNode;
    8. parent.right = rightNode;
    9. nodes.remove(leftNode);
    10. nodes.remove(rightNode);
    11. nodes.add(parent);
    12. }
    13. return nodes.get(0);
    14. }

    3.获得哈夫曼编码

    1. public static void getCodes(Node node, String code, StringBuilder stringBuilder) {
    2. StringBuilder stringBuilder1 = new StringBuilder(stringBuilder);
    3. // 拼接上一轮的code
    4. stringBuilder1.append(code);
    5. if (node != null) {
    6. if (node.date == null) {// 非叶子结点
    7. // 向左递归
    8. getCodes(node.left, "0", stringBuilder1);
    9. // 向右递归
    10. getCodes(node.right, "1", stringBuilder1);
    11. } else {
    12. huffmanCodes.put(node.date, stringBuilder1.toString());
    13. }
    14. }
    15. }

    4.进行压缩

    1. public static byte[] zip(byte[] bytes, Map huffmanCodes) {
    2. StringBuilder stringBuilder = new StringBuilder();
    3. for (byte b : bytes) {
    4. stringBuilder.append(huffmanCodes.get(b));
    5. }
    6. int len;
    7. if (stringBuilder.length() % 8 == 0) {
    8. len = stringBuilder.length() / 8;
    9. } else {
    10. len = stringBuilder.length() / 8 + 1;
    11. }
    12. // 存储压缩后的byte数组
    13. byte[] huffmanCodeBytes = new byte[len];
    14. int index = 0;
    15. for (int i = 0; i < stringBuilder.length(); i += 8) {
    16. String strByte;
    17. if (i + 8 > stringBuilder.length()) {
    18. strByte = stringBuilder.substring(i);
    19. } else {
    20. strByte = stringBuilder.substring(i, i + 8);
    21. }
    22. // 将strByte 转成byte,放入到huffmanCodeBytes
    23. huffmanCodeBytes[index] = (byte) Integer.parseInt(strByte, 2);
    24. index++;
    25. }
    26. return huffmanCodeBytes;
    27. }

    二.进行解码

    1.对压缩后文件进行解码

    1. public static String byteToBitString(boolean flag,byte b){
    2. int temp=b;
    3. if (flag){
    4. temp |=256;// 按位与
    5. }
    6. // 返回二进制补码
    7. String str=Integer.toBinaryString(temp);
    8. if (flag){
    9. return str.substring(str.length()-8);
    10. }else {
    11. return str;
    12. }
    13. }
    1. public static byte[] decode(Map huffmanCodes,byte[] huffmanBytes){
    2. StringBuilder stringBuilder = new StringBuilder();
    3. // 得到对应二进制字符串
    4. for (int i = 0; i < huffmanBytes.length; i++) {
    5. byte b = huffmanBytes[i];
    6. boolean flag=(i== huffmanBytes.length-1);
    7. stringBuilder.append(byteToBitString(!flag,b));
    8. }
    9. // 反向查询
    10. // 将字符串按照指定哈夫曼编码进行解码
    11. HashMap map = new HashMap<>();
    12. for (Map.Entry entry : huffmanCodes.entrySet()) {
    13. map.put(entry.getValue(),entry.getKey());
    14. }
    15. // 存放byte
    16. ArrayList list = new ArrayList<>();
    17. for (int i = 0; i < stringBuilder.length(); ) {
    18. int count=1;
    19. boolean flag=true;
    20. Byte b=null;
    21. while (flag){
    22. String key = stringBuilder.substring(i, i + count);
    23. b=map.get(key);
    24. if (b==null){
    25. count++;
    26. }else {
    27. flag=false;
    28. }
    29. }
    30. list.add(b);
    31. i+=count;
    32. }
    33. byte[] b = new byte[list.size()];
    34. for (int i = 0; i < b.length; i++) {
    35. b[i]=list.get(i);
    36. }
    37. return b;
    38. }

  • 相关阅读:
    SpringCloud Alibaba核心组件Nacos【服务多级存储模型&配置集群】第2章
    【JAVASE系列】01_注释,数据类型,强转
    uniapp组件库总结笔记
    FP64、FP32、FP16、int8
    从Gamma空间改为Linear空间会导致性能下降吗
    windows上传文件到linux的方法
    APP推广ZB简介
    声音生成评价项目AudioLDM_eval项目配置过程
    Netflix SpringCloud-ribbon & zipkin
    猫头虎博主第四期赠书活动:《精通Go语言:(第2版) 》
  • 原文地址:https://blog.csdn.net/qq_58679358/article/details/126915762