使用 Python 进行霍夫曼编码2025年3月17日 | 阅读11分钟 霍夫曼编码是一种基于文本中字符频率的无损压缩和编码文本的方法。在信息论和计算机科学研究中,霍夫曼码是一种特殊类型的最优前缀码,通常用于无损数据压缩。 在下面的教程中,我们将了解霍夫曼编码的理论及其使用Python编程语言的实现。在此之前,让我们简要了解一下霍夫曼编码。 理解霍夫曼编码霍夫曼编码是一种用于数据压缩的无损压缩算法。它是由David A. Huffman在他作为麻省理工学院 (MIT) 的理学博士生时开发的算法,于1952年发表在论文“一种构造最小冗余码的方法”中。它是他计算机编程研究的一部分,通常可以在C、C++、Python、Java、JavaScript、Ruby等编程语言中找到。霍夫曼编码背后的思想如下: 频繁出现的字母或符号使用较短的代码表示,而不频繁出现的字母或符号使用较长的代码表示。 这种思想使得字符的表示更高效,需要更少的内存来存储。因此,我们可以得出结论,我们可以使用霍夫曼编码作为数据压缩方法。 现在让我们了解霍夫曼编码的理论。 理解霍夫曼编码的理论我们知道文件以二进制代码存储在计算机上,并且文件中的每个字符都被分配了一个二进制字符,并且字符代码通常对于不同的字符具有固定长度。霍夫曼编码是根据文件中每个字符出现的频率以及数据结构中频率为零 (0) 的字符数建立的。典型文本文件的霍夫曼编码可以节省实际数据大小的约40%。因此,像编译后的可执行文件一样,霍夫曼二进制代码也将具有独特的空间节省。其中ASCII字符以0.5的频率编码的二进制文件将具有与其ASCII等效文件非常不同的频率和分布。 为了使用字符序列压缩文件,我们需要一个表格,该表格提供每个字符使用的位序列。该表格生成一个编码树,该树利用根/叶路径来创建编码字符的位序列。我们可以沿着根和叶来创建具有编码字符最大位长度和出现次数的字符列表。 我们可以使用贪婪算法来构建最优树。霍夫曼编码树返回用于压缩数据的最短字符编码。树中的节点表示字符出现的频率。根节点表示字符串的长度,遍历树可以得到指定给字符的编码。一旦树构建完成,遍历树就可以得到每个符号的相应代码。 完成后的最优树如以下表格和图片所示
![]() 现在让我们在下一节中开发和实现一个使用霍夫曼编码的程序。 使用Python实现霍夫曼编码我们将从创建一个名为Nodes的类开始,它指的是二叉霍夫曼树的节点。本质上,每个节点都包含一个符号和相关的概率变量、左和右子节点以及代码变量。根据我们在遍历霍夫曼树时选择的侧(左为0,右为1),代码变量将是0或1。 让我们看下面的代码片段来说明这一点: 示例 说明 在上面的代码片段中,我们定义了一个名为Nodes的类,并初始化了一些参数,如概率、符号、左和右。我们最初将左和右变量的值设置为None,因为方向尚未定义。最后,我们还初始化了代码变量。 现在,我们将添加一些支持函数。第一个函数是计算给定数据中符号的概率。第二个函数是获取符号的编码,我们将在拥有霍夫曼树后使用它。最后一个函数是获取结果(编码数据)。 示例 说明 在上面的代码片段中,我们定义了三个不同的辅助函数,用于计算给定数据中符号的概率、获取符号的编码以及获取结果。 对于第一个函数,我们定义了一个字典名为the_symbols,并使用for循环遍历给定数据中的项,并将它们插入字典中。我们还使用了if-else条件语句来检查数据是否包含某些元素并相应地执行操作。 对于第二个函数,我们定义了另一个字典名为the_codes。在函数中,我们分配了一个变量来存储当前节点的霍夫曼代码,并使用if条件语句将节点添加到当前节点的左侧和右侧,并返回符号编码。 对于最后一个函数,我们创建了一个空数组。然后我们使用for循环遍历数据中的字符,并使用append()函数将数据添加到数组中。然后我们使用join()函数将数组中的元素连接到字符串中并返回字符串。 此外,我们还将定义另一个名为TotalGain的函数,它接受初始数据和来自CalculateCode的字典,其中包含符号及其代码。该函数将帮助我们计算压缩数据和未压缩数据的位大小之间的差异。 让我们看下面的代码片段来说明这一点: 示例 说明 在上面的代码片段中,我们定义了该函数。我们计算了压缩前存储数据所需的总比特空间。然后我们定义了一个变量来存储数据压缩后的比特空间大小并将其设置为零。然后我们遍历了来自CalculateCode函数字典的键并计算了它们的出现次数。然后我们计算了压缩后存储数据所需的比特空间。 我们将使用HuffmanEncoding函数,它只接受数据作为参数,并使用上述所有函数返回结果编码和总增益。 让我们通过以下代码片段来理解这一点: 示例 说明 在上面的代码片段中,我们使用了数据参数,使用CalculateProbability函数计算了符号的概率,并将结果数据存储在一个变量中。然后我们提取了符号(键)和概率(值)并打印给用户。然后我们定义了一个数组名为the_nodes,并将符号和概率转换为霍夫曼树的节点。我们使用for循环遍历符号并将它们附加到数组中。我们还使用了while循环来根据它们的概率按升序对节点进行排序。我们选择了两个最小的节点并将它们组合成一个新节点。我们从数组中删除了最小的节点并添加了新节点。然后我们使用了CalculateCodes函数来计算霍夫曼编码的代码并打印带有代码的符号给用户。我们还使用了TotalGain函数,提供所需的参数来计算压缩数据和未压缩数据的位空间之间的差异。最后,我们打印了结果并返回了encodedOutput和数组的第零个索引。 现在,我们将定义一个函数来解码霍夫曼编码数据,以再次获得初始的未压缩数据,这是一个非常简单的过程。 让我们考虑以下代码片段,它演示了霍夫曼编码数据的解码过程。 示例 说明 在上面的代码片段中,我们定义了一个名为HuffmanDecoding的函数,它接受两个参数:encodedData和huffmanTree。然后我们将huffmanTree变量分配给另一个变量。我们还定义了一个空数组名为decodedOutput。然后我们使用for循环遍历编码数据中的元素。在循环中,我们使用了if-elif-else条件语句和try-exception方法来解码编码数据并将每个解码元素附加以生成解码输出。最后,我们创建了一个字符串并返回该字符串供用户使用。 现在,让我们初始化字符串数据并打印结果。 示例 说明 在上面的代码片段中,我们定义了字符串数据并将其打印给用户。我们将此数据传递给HuffmanEncoding函数,并将值存储在encoding和the_tree变量中。然后我们将编码结果打印给用户。最后,我们将编码数据传递给HuffmanDecoding函数并打印解码后的字符串。 现在,让我们在执行前查看完整的项目。 完整的项目代码 让我们看看霍夫曼编码的完整Python项目代码。 文件: huffmanAlgo.py 输出 AAAAAAABBCCCCCCDDDEEEEEEEEE symbols: dict_keys(['A', 'B', 'C', 'D', 'E']) probabilities: dict_values([7, 2, 6, 3, 9]) symbols with codes {'E': '00', 'A': '01', 'C': '10', 'D': '110', 'B': '111'} Space usage before compression (in bits): 216 Space usage after compression (in bits): 59 Encoded output 01010101010101111111101010101010110110110000000000000000000 Decoded Output AAAAAAABBCCCCCCDDDEEEEEEEEE 下一主题Python中的嵌套字典 |
元字符是正则表达式中一个非常重要的概念,它帮助我们使用 Python 的 regex 模块解决编程任务。在本教程中,我们将学习 Python 中的元字符或如何使用它们。我们将解释每个元字符并附上...
阅读 6 分钟
介绍 一种用于计算机科学的复杂算法方法,称为所有后缀的 Trie,它允许我们快速在文本中搜索特定的模式。为了实现快速模式匹配,这种方法将 Trie(前缀树)数据结构的思想与后缀相结合。一个...
阅读 4 分钟
Python中的assert语句使用户能够向其代码添加健全性测试。断言是他们在编写代码时可以用来检查特定假设是否仍然有效的一种检查。如果他们的任何断言变为假,则他们的代码中存在缺陷。断言将……
阅读 4 分钟
Python 中模块和包的区别 许多程序员和业余程序员经常会混淆模块和包。问题通常出现在很难确定何时何地应该实现模块或包时。在下文中……
阅读 2 分钟
Python 字典是一种数据结构,包含所有以键值对形式存在的元素。每个键值对将键映射到其关联的值。因此,它也被称为 Python 字典的关联数组。字典的所有元素都包含在花括号内...
阅读9分钟
Python 因其简洁性而成为程序员中流行的编程语言。还需要注意的是,Python 将一切都视为对象。然而,许多种类的 Python 对象彼此之间存在显着差异。也就是说,某些 Python 对象可以更改,...
阅读 6 分钟
在本教程中,我们将学习 Python pandas 方法 df.info() 方法。Pandas 是一个非常流行的库,可以轻松有效地分析数据。它是 Python 中一个重要且广泛使用的方法。此方法打印数据帧的信息或摘要....
5 分钟阅读
简介 信号的功率谱密度 (PSD) 描绘了其功率如何在频率上分布。它在许多技术领域都有信号处理应用。PSD 用于评估无线电和雷达等通信系统中的信道占用率和相关频率。PSD 广泛用于……
阅读 4 分钟
在本文中,我们将讨论如何在Python中输入列表。但在讨论它们的方法之前,我们必须了解Python中的列表。什么是列表?列表是Python提供的一种内置数据结构,它能够组织和存储……
阅读 6 分钟
| Python中常量的重要性 在本教程中,我们将了解常量类型以及它们如何帮助提高代码可读性。如果您不熟悉,常量是表示在程序执行期间不更改的值的名称。它们是最常见的……
阅读 10 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India