Android 快速哈夫曼解码
我已经用Scala编写了一个huffman压缩/解压缩程序。解码小文件需要几秒钟,但解码大文件需要非常长的时间。有没有关于如何加快这一进程的建议Android 快速哈夫曼解码,android,scala,huffman-code,Android,Scala,Huffman Code,我已经用Scala编写了一个huffman压缩/解压缩程序。解码小文件需要几秒钟,但解码大文件需要非常长的时间。有没有关于如何加快这一进程的建议 def lookup(list:List[Int],list2:List[(Char,List[Int])]): Option[String]={ val mutableListBuffer = scala.collection.mutable.ArrayBuffer(list2: _*) var option:Option[String]=
def lookup(list:List[Int],list2:List[(Char,List[Int])]): Option[String]={
val mutableListBuffer = scala.collection.mutable.ArrayBuffer(list2: _*)
var option:Option[String]= None
for(i <- 0 until mutableListBuffer.length){
if(mutableListBuffer(i)._2 == list){
option = Some(mutableListBuffer(i)._1.toString)
}
}
option
}
/*
*Decode function for matching groups of bits in a list to characters in the HCodeMap
*@returns String
*/
def decode(acc:Int,s:String,list:(List[Int],List[(Char,List[Int])])):String ={
var s = ""
var accum = 1
val listp1 = scala.collection.mutable.ArrayBuffer(list._1: _*)
val listp2 = scala.collection.mutable.ArrayBuffer(list._2: _*)
var tupList = (listp1,listp2)
while(!tupList._1.isEmpty){
if(lookup(tupList._1.take(accum).toList,tupList._2.toList).isDefined){
println(accum)
s = s ++ lookup(tupList._1.take(accum).toList,tupList._2.toList).getOrElse("a")
Log.d("MyTAG", "de" + s)
tupList._1.remove(0,accum)
accum = accum - accum + 1
}
else{
accum = accum + 1
}
}
s
}
def查找(list:list[Int],list2:list[(Char,list[Int])):选项[String]={
val mutableListBuffer=scala.collection.mutable.ArrayBuffer(列表2:*)
变量选项:选项[字符串]=无
例如(我这可能属于codereview,但我认为这里的代码与您的代码完全相同,没有任何到ArrayBuffers的转换(这是不必要的)。列表操作相当有效,只需执行拖放和列表遍历,因此我认为您将错误的方向归咎于不可变列表
def lookup(list: List[Int], list2: List[(Char, List[Int])]): Option[String] =
list2.find(_._2 == list).map(_._1.toString)
/*
*Decode function for matching groups of bits in a list to characters in the HCodeMap
*@returns String
*/
def decode(s: String, list: (List[Int], List[(Char, List[Int])])): String = {
var s = ""
var accum = 1
var listp1 = list._1
val listp2 = list._2
while (!listp1.isEmpty) {
lookup(listp1.take(accum), listp2) match {
case Some(m) =>
println(accum)
s = s ++ m
Log.d("MyTAG", "de" + s)
listp1 = listp1.drop(accum)
accum = 1
case None =>
accum = accum + 1
}
}
s
}
这可能属于codereview,但我认为这里的代码与您的代码完全相同,没有任何到ArrayBuffers的转换(这是不必要的)。列表操作相当有效,只需进行取舍和列表遍历,因此我认为您将错误的方向归咎于不可变列表
def lookup(list: List[Int], list2: List[(Char, List[Int])]): Option[String] =
list2.find(_._2 == list).map(_._1.toString)
/*
*Decode function for matching groups of bits in a list to characters in the HCodeMap
*@returns String
*/
def decode(s: String, list: (List[Int], List[(Char, List[Int])])): String = {
var s = ""
var accum = 1
var listp1 = list._1
val listp2 = list._2
while (!listp1.isEmpty) {
lookup(listp1.take(accum), listp2) match {
case Some(m) =>
println(accum)
s = s ++ m
Log.d("MyTAG", "de" + s)
listp1 = listp1.drop(accum)
accum = 1
case None =>
accum = accum + 1
}
}
s
}
如果你想让它更快,那么你的出发点是错误的。你应该直接使用比特流,而不是整数列表,每个整数都包含一个比特。在某些地方,你在浪费时间将输入的比特转换为整数列表,然后浪费大量时间解码该列表
制作快速哈夫曼解码器的一种方法是建立允许直接索引查找的解码表。选择一个大约等于统一代码长度的位n。例如,如果有256个符号,让n作为8开始。(稍后可以使用n来优化速度。)
现在构建一个256个条目的表,该表由接下来的8位输入进行索引下一个代码的长度为8位或更少,或b)下一个代码的长度为9位或更多。对于a),表将告诉您代码中的位数及其解码到的符号。在这种情况下,您将从流中删除那么多位并发出符号
对于b),该表指向下一个表,以便使用后续位和多少位进行索引。然后从流中丢弃8位并索引子表,该子表也将指示a)或b)。尽管可能两级表是最佳的,因此子表将始终指示a),完成解码并发出符号。在在这种情况下,子表的大小(即索引中的位数)是最长代码的长度减去8,该代码的前缀为索引主表的8位
表的构建非常简单,构建只需一次,有很多用途,因此构建时间非常值得。表中的条目通常会重复多次。例如,一个四位代码在基本的八位表中会重复16次
您可以在位缓冲区(一个整数)上使用位操作,根据需要从流中提取字节,以使其加载足够的位以形成下一个索引。简单的位移位会在使用位时向下移动位,而输入字节上的位移位会在将其放入位缓冲区之前进行
一旦一切正常,你可以改变n,并用代表性输入对解码器计时,以找到n的最佳值。如果你想让它更快,那么你的起点是错误的。你应该直接处理比特流,而不是整数列表,每个整数包含一个比特。在某些地方你浪费了时间e将输入位转换为整数列表,然后浪费大量时间解码该列表
制作快速哈夫曼解码器的一种方法是建立允许直接索引查找的解码表。选择一个大约等于统一代码长度的位n。例如,如果有256个符号,让n作为8开始。(稍后可以使用n来优化速度。)
现在构建一个256个条目的表,该表由接下来的8位输入索引。每个条目表示a)下一个代码为8位或更少,或b)下一个代码为9位或更长。对于a),该表告诉您代码中的位数及其解码到的符号。在这种情况下,您将从strea中删除那么多位m并发出符号
对于b),该表指向下一个表,以便使用后续位和多少位进行索引。然后从流中丢弃8位并索引子表,该子表也将指示a)或b)。尽管可能两级表是最佳的,因此子表将始终指示a),完成解码并发出符号。在在这种情况下,子表的大小(即索引中的位数)是最长代码的长度减去8,该代码的前缀为索引主表的8位
表的构建非常简单,构建只需一次,有很多用途,因此构建时间非常值得。表中的条目通常会重复多次。例如,一个四位代码在基本的八位表中会重复16次
您可以在位缓冲区(一个整数)上使用位操作,根据需要从流中提取字节,以使其加载足够的位以形成下一个索引。简单的位移位会在使用位时向下移动位,而输入字节上的位移位会在将其放入位缓冲区之前进行
一旦一切正常,你就可以用代表性的输入改变解码器的n和时间,以找到n的最佳值。如果你解释参数是什么,并更详细地命名它们,会有很大帮助。此外,还有一些奇怪之处-acc
是第一个解码的参数,但没有使用。很难看出是什么首先,代码正在执行。acc是冗余的,你是对的。第二个是要解码的字符串。第三个是一对,包含要解码的位列表以及t