日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法系列之使用赫夫曼编码的实战应用【对文件进行压缩、解压缩】

發布時間:2024/10/5 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法系列之使用赫夫曼编码的实战应用【对文件进行压缩、解压缩】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.首先在準備一張圖片

2.測試壓縮效果



3.測試解壓縮效果

將桌面a.jpg刪除



4.源代碼

package com.zsh.algorithm.tree;import java.io.*; import java.util.*;/*** @author:Ronin* @since:2021/9/29* @email:1817937322@qq.com*/public class HuffmanEncrypt {public static void main(String[] args) { // String str = "i love china china china oh"; // byte[] bytes = huffmanZip(str.getBytes()); // System.out.println(Arrays.toString(bytes)); // String s = calHuffmanZipRatio(str.getBytes(), bytes); // System.out.println("壓縮率為:" + s); // String s1 = byteToBinaryString(false, (byte) -1); // System.out.println("測試-1的補碼為:"+ s1); // decode(huffmanCodesMap, bytes); // System.out.println("以下是文件壓縮的測試----------------");// fileEncode("C:\\Users\\18179\\Desktop\\a.jpg", "C:\\Users\\18179\\Desktop\\a.zip");fileDecode("C:\\Users\\18179\\Desktop\\a.zip", "C:\\Users\\18179\\Desktop\\a.jpg");}//用來存儲轉換二進制字符串集合private static StringBuilder stringBuilder = new StringBuilder();//哈夫曼編碼表private static Map<Byte, String> huffmanCodesMap = new HashMap<>();//---------------------------------------以下是壓縮相關函數------------------------------------------///*** 赫夫曼編碼封裝方法** @param bytes* @return*/public static byte[] huffmanZip(byte[] bytes) {//1.計算字符串中每個字符出現的次數,并字符、次數封裝到EncryptNode結點中,將其加入到list集合中List<EncryptNode> encryptNodeList = calByteNums(bytes);//outputList(encryptNodeList);//2.構建哈夫曼樹EncryptNode root = buildHuffmanTree(encryptNodeList);// preErgodic(root);//3.生成赫夫曼編碼表Map<Byte, String> huffmanCodes = getHuffmanCodes(root);//System.out.println(huffmanCodes);//4.轉換為赫夫曼編碼字節表return zip(bytes, huffmanCodes);}/*** 計算字符串中的每個字符的長度** @param bytes 待計算的字符串* @return 返回list集合*/public static List<EncryptNode> calByteNums(byte[] bytes) {Map<Byte, Integer> map = new HashMap<>();byte[] charArray = bytes;for (byte c : charArray) {if (map.containsKey(c)) {int num = map.get(c);map.replace(c, num, num + 1);} else {map.put(c, 1);}}List<EncryptNode> list = new ArrayList<>();for (Map.Entry<Byte, Integer> entry : map.entrySet()) {Byte key = entry.getKey();Integer value = entry.getValue();list.add(new EncryptNode(key, value));}return list;}/*** 構建赫夫曼樹** @param list 權重集合* @return 返回root節點*/public static EncryptNode buildHuffmanTree(List<EncryptNode> list) {while (list.size() > 1) {Collections.sort(list);EncryptNode leftNode = list.remove(0);EncryptNode rightNode = list.remove(0);EncryptNode parentNode = new EncryptNode(null, leftNode.value + rightNode.value);parentNode.left = leftNode;parentNode.right = rightNode;list.add(parentNode);}return list.remove(0);}/*** 重載getHuffmanCodes(EncryptNode node, String path, StringBuilder stringBuilder)** @param root 根節點* @return 哈夫曼編碼map集合*/public static Map<Byte, String> getHuffmanCodes(EncryptNode root) {if (root == null) {return null;} else {getHuffmanCodes(root.left, "0", stringBuilder);getHuffmanCodes(root.right, "1", stringBuilder);}return huffmanCodesMap;}/*** 赫夫曼編碼** @param node 結點* @param path 1代表右結點,0代表左結點路徑* @param stringBuilder 用于path拼接*/public static void getHuffmanCodes(EncryptNode node, String path, StringBuilder stringBuilder) {StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);stringBuilder2.append(path);if (node != null) {if (node.c == null) {getHuffmanCodes(node.left, "0", stringBuilder2);getHuffmanCodes(node.right, "1", stringBuilder2);} else {huffmanCodesMap.put(node.c, stringBuilder2.toString());}}}/*** @param bytes 待編碼字節數組* @param entry 赫夫曼編碼集合* @return 返回編碼后的byte數組*/public static byte[] zip(byte[] bytes, Map<Byte, String> entry) {StringBuilder stringBuilder = new StringBuilder();for (byte ch : bytes) {stringBuilder.append(entry.get(ch));}//System.out.println("stringBuilder=" + stringBuilder.toString());int length = stringBuilder.length();int len = (length + 7) / 8;byte[] huffmanCodeBytes = new byte[len];int index = 0;for (int k = 0; k < length; k += 8) {String str;if ((k + 8) > length) {str = stringBuilder.substring(k);} else {str = stringBuilder.substring(k, k + 8);}huffmanCodeBytes[index] = (byte) Integer.parseInt(str, 2);index++;}return huffmanCodeBytes;}/*** 計算赫夫曼壓縮率** @param original 未壓縮前的字節數組* @param newByte 壓縮后的字節數組* @return 壓縮率*/public static String calHuffmanZipRatio(byte[] original, byte[] newByte) {double zipRatio = (double) (original.length - newByte.length) / original.length * 100;String s = String.format("%.2f", zipRatio);return s + "%";}//---------------------------------以上是壓縮相關函數--------------------------------------------------------////---------------------------------以下是解壓縮相關函數-----------------------------------------------------//private static byte[] decode(Map<Byte, String> huffmanCodesMap, byte[] bytes) {StringBuilder stringBuilder = new StringBuilder();for (int k = 0; k < bytes.length; k++) {boolean flag = (k == bytes.length - 1);stringBuilder.append(byteToBinaryString(!flag, bytes[k]));}Map<String, Byte> reverseMap = new HashMap<>();for (Map.Entry<Byte, String> map : huffmanCodesMap.entrySet()) {reverseMap.put(map.getValue(), map.getKey());}List<Byte> list = new ArrayList<>();for (int i = 0; i < stringBuilder.length(); ) {int count = 1;Byte b = null;boolean flag = true;while (flag) {String key = stringBuilder.substring(i, i + count);b = reverseMap.get(key);if (b == null) {count++;} else {flag = false;}}list.add(b);i += count;}byte[] result = new byte[list.size()];for (int k = 0; k < result.length; k++) {result[k] = list.get(k);}return result;}/*** @param flag 如果為true, 表示需要進行高位補齊;如果是false,表示不需要進行高位補齊-->因為最后一位不一定剛好是滿足八位* @param be 這是將轉換為二進制字符串的字節* @return 返回二進制字符串*/private static String byteToBinaryString(boolean flag, byte be) {int beInt = be;if (flag) {beInt |= 256; //按位與 , 解決正數的高位補齊的問題}String s = Integer.toBinaryString(beInt); //補碼,正數需要高位補齊,負數需要截取if (flag) {return s.substring(s.length() - 8);} else {return s;}}//---------------------------------以上是解壓縮相關函數-----------------------------------------------------////---------------------------------以下是文件壓縮解壓相關函數-----------------------------------------------------///*** 文件壓縮方法 --- 赫夫曼編碼壓縮* @param readFile 壓縮文件路徑 文件 + 文件名* @param storeFile 壓縮之后存儲的路徑 文件 + 文件名*/private static void fileEncode(String readFile, String storeFile) {FileInputStream is = null;ObjectOutputStream oos = null;FileOutputStream os = null;try {is = new FileInputStream(readFile);byte[] bytes = new byte[is.available()];is.read(bytes);byte[] huffmanBytes = huffmanZip(bytes);os = new FileOutputStream(storeFile);oos = new ObjectOutputStream(os);oos.writeObject(huffmanBytes);oos.writeObject(huffmanCodesMap);os.write(huffmanBytes);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {oos.close();os.close();is.close();} catch (IOException e) {e.printStackTrace();}}}public static void fileDecode(String zipFile, String dstFile) {System.out.println("文件解壓開始----------------------");FileInputStream is = null;ObjectInputStream ois = null;FileOutputStream os = null;try {is = new FileInputStream(zipFile);ois = new ObjectInputStream(is);byte[] huffmanBytes = (byte[])ois.readObject();Map<Byte, String> huffmanCodes = (Map<Byte, String>) ois.readObject();byte[] bytes = decode(huffmanCodes, huffmanBytes);os = new FileOutputStream(dstFile);os.write(bytes);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {try {os.close();ois.close();is.close();} catch (IOException e) {e.printStackTrace();}}}//---------------------------------以上是文件壓縮解壓相關函數-----------------------------------------------------////先序遍歷赫夫曼樹public static void preErgodic(EncryptNode cur) {if (cur == null) {return;}System.out.println(cur);preErgodic(cur.left);preErgodic(cur.right);}//打印list集合public static <T> void outputList(List<T> list) {for (T t : list) {System.out.println(t);}} }/*** 實現Comparable接口,便于使用Collections.sort排序*/ class EncryptNode implements Comparable<EncryptNode> {public int value; //出現的次數public Byte c; //字符public EncryptNode left;public EncryptNode right;public EncryptNode(int value) {this.value = value;}public EncryptNode(Byte c, int value) {this.value = value;this.c = c;}@Overridepublic int compareTo(EncryptNode o) {return this.value - o.value; //升序}@Overridepublic String toString() {return "EncryptNode{" +"value=" + value +", c=" + c +'}';} }


結束~

總結

以上是生活随笔為你收集整理的算法系列之使用赫夫曼编码的实战应用【对文件进行压缩、解压缩】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久草热在线观看 | 欧美黑人性受xxxx精品 | 国产精品300页 | √天堂在线 | 精品少妇久久久 | 日本国产精品 | 91精品福利在线 | 免费观看污视频 | 日韩一区二区免费视频 | 成人特级毛片 | 三级av毛片 | 免费看日韩毛片 | 国产剧情av麻豆香蕉精品 | 热久久中文 | 国产色呦呦 | 日日摸夜夜添夜夜添高潮喷水 | 大又大又粗又硬又爽少妇毛片 | 欧美日韩伊人 | 久久aⅴ乱码一区二区三区 亚洲成人18 | 久草福利在线视频 | 人妻饥渴偷公乱中文字幕 | 肉大捧一进一出免费视频 | 男女性网站 | 亚洲美女中文字幕 | 好吊视频一区二区 | 免费福利在线观看 | 一边摸一边做爽的视频17国产 | 成人熟女一区二区 | 91在线网址 | www麻豆视频| 91亚洲一区 | 精品福利视频导航 | 在线播放你懂得 | 99热久久这里只有精品 | 九九五月天 | 亚洲色图图片区 | 天堂av在线网 | 亚洲资源在线播放 | 亚洲精品一区二区三区区别 | 国产精品久久久久久亚洲调教 | 91色拍| 911看片| 伊人精品 | 国产精品自产拍在线观看 | av资源站最新av | 国产精品一区二区在线播放 | 日日夜夜免费视频 | 午夜影院污| 国产黄网在线观看 | 精品国产九九九 | 777亚洲| 香蕉视频官方网站 | 日韩一区二区久久 | 日本不卡影院 | 探花视频在线免费观看 | 国产成人综合一区二区三区 | 欧美午夜精品久久久久免费视 | 99精品免费 | 亚洲国产精品成人av | 神马影院一区二区 | av网站在线免费看 | 亚州男人的天堂 | 日韩欧美国产片 | 热久久网站| 久久亚洲一区 | 亚洲涩涩| 天天爽夜夜春 | 日韩一区二区三区四区五区 | 日韩精品高清在线观看 | 禁漫天堂免费网站 | 精品黑人一区二区三区国语馆 | 香蕉色网 | 国产一区二区三区免费播放 | 日韩一区二区中文字幕 | 欧美一级性 | 亚洲伦理久久 | 亚洲av无码日韩精品影片 | 久久久久99精品成人片三人毛片 | 久久久久人妻一区精品色 | 亚洲区免费 | 国产专区视频 | 亚洲a免费| 深夜毛片| 欧美v视频 | 亚洲人视频在线观看 | 91黄色影视 | 四虎永久地址 | wwwwxxx日本| 日日摸夜夜添狠狠添欧美 | 日本加勒比在线 | 国产高清一区在线观看 | 性欧美在线 | 华丽的外出在线 | 国产男女爽爽爽 | 国产网红主播精品av | 国产精品久久久久三级无码 | 天天色图片 | 色涩视频在线观看 | 超级变态重口av番号 |