自用笔记 尚硅谷老师还是有点错误的 自己找了一个小时错误和分析
1.写一段文本用来压缩 比如
String str="i like like like java do you like a java";
2.string分成 byte数组
str.getBytes()
3.做成频度map CountMap计算每个byte(包括空格)的频度
4.以频度作为weight 字符/byte作为data的节点 然后将所有节点做成list 排序然后做成哈夫曼树
5.最后做成哈夫曼树可以得到哈夫曼树的一个root
6.根据哈夫曼树节点开始遍历以左为0,右为1进行依次往下遍历 创建byte对应的01编码,同时用一个HuffmanCode的Map进行保存各种byte对应的编码
huffmanCode:{32=01, 97=100, 100=11000, 117=11001, 101=1110, 118=11011, 105=101, 121=11010, 106=0010, 107=1111, 108=000, 111=0011}
ascii码对照后
可以变成这个表:[i, , l, i, k, e, , l, i, k, e, , l, i, k, e, , j, a, v, a, , d, o, , y, o, u, , l, i, k, e, , a, , j, a, v, a]
//会根据不同做法01可能有所不同 但是wpl长度整体是相同的
7.以String为顺序i like like like java do you like a java 的顺序,用HuffmanCode进行替换成不同的01编码 得到一个长字符串比如:1010100010111111110010001011111111001000101111111100100101001101110001110000011011101000111100101000101111111100110001001010011011100
8.开始压缩: 将上面的长字符串进行每8位分割 保存成一个新的byte的 然后做成一个压缩数组 保存压缩后的码数组
zipBytes:[-88, -65, -56, -65, -56, -65, -55, 77, -57, 6, -24, -14, -117, -4, -60, -90, 28]
9.进行解压 byte数组用二进制转回上面的一长串文本
10.用huffmanCode对上面编码识别 然后翻译成原来的一个文本 或文本数组
String str="i like like like java do you like a java";
11.最后,酱这个文本翻译成最初的bytes数组
huffmanCode:{32=01, 97=100, 100=11000, 117=11001, 101=1110, 118=11011, 105=101, 121=11010, 106=0010, 107=1111, 108=000, 111=0011}
重新复习的时候发现问题:
1.在7中翻译01文本后 用byte[]数组存成压缩码数组,每8位存入一个,前面是没有问题的.但是当最后一位的时候,假如剩下文本不足8位 最后的为01100 的文本,按二进制翻译成14,没有问题. 但是当解码的时候 数组最后一位是14 ->翻译成1100 这样就会导致与01100 少了前部的0 后面用map编译翻译文本的时候会出现翻译后文本错误翻译甚至能正常执行完毕
2.解决办法 我用 zipcode返回成压缩文本的长度 用于最后比较翻译时候的最后一个byte的文本长度
private static int zipCode(String str) {
HuffmanTreeAg huffmanTree = createHuffmanTree(str);
generateHuffmanCode(huffmanTree.root,"");
String translateStr = translateStr(str, huffmanCodeMap);
System.out.println(translateStr);
//byte[] transbyteArray=spliteArrays(translateStr);
zipCodeBytes=spliteArrays(translateStr);
return translateStr.length();
}
翻译 deCode酱byte[]翻译成原文本串 最后一个byte的时候用length比较最后的文本长度差值 反正肯定是差0不会差1 直接补全0 最后返回正确的字符串
private static String deCode(byte[] zipCodeBytes,Map<Byte, String> huffmanCodeMap,int zipCodeLength) {
StringBuilder sb=new StringBuilder();
for (int i = 0; i < zipCodeBytes.length; i++) {
byte oneBye=zipCodeBytes[i];
String binaryString="";
if(i==zipCodeBytes.length-1){//最后一位小于 8位 直接返回
binaryString= Integer.toBinaryString((int) oneBye);
//需要根据zipcodelength末尾补全
int difference=zipCodeLength%8-binaryString.length();
//System.out.println(zipCodeLength%8+"*****");
//System.out.println(difference+"*****");
StringBuilder sbDifference=new StringBuilder(binaryString);
if(difference>0){
for (int j = 0; j < difference; j++) {
sbDifference.insert(0,"0");
}
}
binaryString=sbDifference.toString();
}else {//正数的时候需要补0
int o=(int)oneBye | 256;
binaryString= Integer.toBinaryString((int) o);
binaryString = binaryString.substring(binaryString.length() - 8);
}
//System.out.println(binaryString);
sb.append(binaryString);
}
String decodeStr=sb.toString();
System.out.println(decodeStr);
String resStr = translateDecodeStr(decodeStr, huffmanCodeMap);
//再翻译成原文本
return resStr;
}