【发布时间】:2018-11-11 08:28:03
【问题描述】:
所以我一直在尝试使用 huffman 进行解码,我有这个工作功能,但它的时间和空间复杂性非常可怕。到目前为止,我一直在做的是读取每个字节,获取每个位并将其添加到 currentBitString。然后我反转字符串,并将其添加到一个巨大的字符串中,该字符串基本上包含文件的所有字节数据。在那之后,我会追踪这个巨大的字符串并寻找霍夫曼代码,然后如果它匹配,我会写入文件。这段代码解码一个 200kb 大约需要 60 秒,这非常糟糕,但我不确定如何改进它?我知道对于初学者来说,我可以一次向文件写入一个以上的字节,但它似乎并没有改善我尝试的时间?
public static void decode(File f) throws Exception {
BufferedInputStream fin = new BufferedInputStream(new FileInputStream(f));
int i = f.getName().lastIndexOf('.');
String extension="txt";
String newFileName=f.getName().substring(0, i)+extension;
File nf = new File(newFileName);
BufferedOutputStream fw = new BufferedOutputStream(new FileOutputStream(nf));
int c;
byte bits;
byte current;
String currentBitString="";
String bitString="";
//read each byte from file, reverse it, add to giant bitString
//reads ALL BYTES
while( (c=fin.read())!=-1 ) {
current=(byte) c;
currentBitString="";
bits=0;
for(int q=0;q<8;q++) {
bits=getBit(current,q);
currentBitString+=bits;
}
StringBuilder bitStringReverse=new StringBuilder(currentBitString);
bitString+=bitStringReverse.reverse().toString();
}
currentBitString="";
boolean foundCode=false;
for(int j=0;j<bitString.length();j++) {
currentBitString+=bitString.charAt(j);
for(int k=0;k<nodes.length;k++) {
//nodes is an array of huffman nodes which contains the the byte
//data and the huffman codes for each byte
if(nodes[k].code.compareTo(currentBitString.trim())==0) {
fw.write(nodes[k].data);
foundCode=true;
break;
}
}
if(foundCode) {
currentBitString="";
foundCode=false;
}
}
fw.flush();
fw.close();
fin.close();
}
这里是 gitBit 函数
public static byte getBit(byte ID, int position) {
// return cretin bit in selected byte
return (byte) ((ID >> position) & 1);
}
这里是 HuffmanNode 类的数据成员(节点数组是 HuffmanNodes 的数组)
public class HuffmanNode{
byte data;
int repetitions;
String code;
HuffmanNode right;
HuffmanNode left;
}
【问题讨论】:
-
也许这会有所帮助geeksforgeeks.org/…
-
您可能有一个非常低效的编码实现,但复杂性并不能说明这一点。它仍然是 O(n) 时间,并且从快速扫描来看,也是 O(n) 空间。你问错了问题,你不能 xhsnde 它的复杂性,但你想优化代码。而且这个问题对于 SO 来说可能太宽泛了。
-
我真的不知道你的代码在做什么。但我观察到内存分配非常繁重:对于您读取的每个字符,您分配一个 StringBuilder 实例,toString() 分配一个 String实例和
+=分配另一个9 String 实例。优化潜力巨大。 -
见rules.sonarsource.com/java/RSPEC-1643。此外,当您可以使用
for (int q=7;q>=0;q--)以正确的方式开始构建它时,为什么要从左到右构建位串然后反转它(从而占用更多内存并占用更多时间)。
标签: java huffman-code