数据结构020_赫夫曼解码
数据解压就是数据压缩的逆向。
直接上代码:
/** * 数据解压 思路: 1.将huffmanCodeByte[-88, -65, -56, -65, -56, -65, -55, 77, -57, * 6, -24, -14, -117, -4, -60, -90, 28] 重新先转成赫夫曼编码对应的二进制字符串“10101000...” * 2.赫夫曼编码对应的二进制字符串“1010100....” => 对照赫夫曼编码 => "i like like...." */ /** * 功能:(数据解压第一步)将一个byte转成一个二进制的字符串 * * @param b * 传入的byte * @param flag * 标识是否需要补高位,true表示需要补高位,false不需要.如果是最后一个字节不需要补高位。 * @return 是该byte对应的二进制字符串(注意是按补码返回的) */ private static String byteToBitString(boolean flag, byte b) { // 使用变量保存b,将b转成int使用integer的toBinaryString int temp = b; if (flag) { // 正数还存在补高位 temp |= 256; // 按位与 256(1 0000 0000) 1(0000 0001) 按位与=> 1 0000 0001 } String str = Integer.toBinaryString(temp);// 这里返回的是temp对应的二进制的补码 if (flag) return str.substring(str.length() - 8); else return str; } /** * 功能:(数据解压第二步 核心代码)解码 * * @param huffmanCodes * 赫夫曼编码表 * @param huffmanBytes * 赫夫曼编码得到的字节数组 * @return 就是原来的字符串对应的数组 */ private static byte[] decode(Map<Byte, String> huffmanCodes, byte[] huffmanBytes) { // 1.先得到huffmanByte对应的二进制字符串,形式“1010100...” StringBuilder sb = new StringBuilder(); // 2.将byte数组转换成二进制字符串 for (int i = 0; i < huffmanBytes.length; i++) { byte b = huffmanBytes[i]; boolean flag = (i == huffmanBytes.length - 1); // 最后一位不用补位 这里还可以这样写呀 sb.append(byteToBitString(!flag, b)); } // System.out.println("赫夫曼字节数组对应的二进制字符串="+sb.toString()); // 把字符串按照指定的赫夫曼编码进行解码 // 把赫夫曼编码表进行调换,因为要反向查询(原先97->100,现在100->97) Map<String, Byte> map = new HashMap<String, Byte>(); for (Map.Entry<Byte, String> entry : huffmanCodes.entrySet()) { map.put(entry.getValue(), entry.getKey()); } // 大概就是map={000=108, 01=32, 100=97, 101=105, 11010=121, 0011=111, // 1111=107, 11001=117, 1110=101, 11000=100, 11011=118, 0010=106} // 创建一个集合,存放byte List<Byte> list = new ArrayList<>(); for (int i = 0; i < sb.length();) { // i可以理解成一个索引,扫描sb // 【这里循环可以不写步长的唉,第一次】 int count = 1;// 小的计数器 boolean flag = true; Byte b = null; while (flag) { // 递增地取出key,就是1,10,101,...直到匹配到 String key = sb.substring(i, i + count);// i不懂,让count走,直到匹配到一个字符 b = map.get(key); if (b == null) // 没有匹配到 count++; else // 匹配到 flag = false; } list.add(b); i += count; } // 当for循环结束后,list中就存放了所有的字符 // 把list中的数据放入一个byte[]并返回 byte b[] = new byte[list.size()]; for (int i = 0; i < b.length; i++) { b[i] = list.get(i); } return b; }