【问题标题】:Iterating over a large string and checking membership of substrings in a dictionary performance遍历大字符串并检查字典性能中子字符串的成员资格
【发布时间】:2017-12-18 04:22:28
【问题描述】:

我目前正在用python实现霍夫曼编码,我已经完成了,但我想让它更高效。

这是我获取原始文件内容的方法

def getDecodedFile(self, text, codes):
        code = ""
        origin = []        
        for ch in text:
            code += ch
            if code in codes:
                origin.append(codes[code])
                code = ""
        bCodes = bytes(origin)
        return bCodes

text是大字符串,codes是霍夫曼编码的字典(key是编码的字符串,value是0到255之间的int)

我尝试使用''.join(somelist) 而不是code += ch,但结果要慢得多。目前这个方法用len(text) = 13972363执行需要3秒,最短代码长度是6

数据示例:

text = "0100101110111"

codes = {'0': 65, '100': 66, '101': 67, '110': 68, '111': 69}

这将导致origin = [65,66,67,68,69]

如果有任何建议可以提高我的代码效率,我将不胜感激。

【问题讨论】:

    标签: python string performance


    【解决方案1】:

    据我所知,您可以做的一项改进是当您这样做时:

    code += ch
    if code in codes:
        origin.append(codes[code])
    code = ""
    

    具体来说,每次修改code 时都要检查if code in codes:。例如,对于长度为 k 的代码,您最终将执行 O(1 + 2 + 3 + ... + k) = O(0.5 * k * k+1) = O(k²) 运算。相反,您应该预处理codes,方法是构建一棵霍夫曼树并沿着树进行一次 O(k) 遍历以解码您的代码(从根开始,并在一次并沿着各自的子边缘;一旦你击中一个字母,在解码的消息中输出它并移回你的树的根部)。这不仅显式节省了检查if code in codes: 的时间复杂度,而且还避免了每次执行code += ch 时都重新构建字符串code

    除此之外,我不确定您是否可以进一步优化。我想知道将每个单独的解码字母转换为byte 并附加到输出列表是否会更快,而不是将字母解码为列表然后通过bytes(origin) 转换列表?

    【讨论】:

    • 我所做的是我使用树来解码代码而不是使用字典,这节省了大约 0.5 秒,但是将每个字母转换为字节实际上减慢了速度,所以我保留了我的列表。谢谢!
    • 没问题!不幸的是,据我所知,这是在算法实现方面实现霍夫曼解码的最快方式。任何进一步的优化都是低级的(例如,将树存储为数组以最大程度地减少内存访问速度,使用更快的语言编写等)
    • 使用 pypy3 而不是默认解释器,同一文件的时间减少到 0.6 秒。
    【解决方案2】:

    最大的性能提升来自使用类似 trie 的东西来存储 Huffman 树。这将让您一次下降一个级别,这将消除对字符串连接或重复检查存在的需要。

    【讨论】:

      猜你喜欢
      • 2020-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 2015-03-30
      • 1970-01-01
      • 2019-05-29
      相关资源
      最近更新 更多