Python描述数据结构学习之哈夫曼树篇

Python描述数据结构学习之哈夫曼树篇攻略

简介

本篇攻略旨在介绍哈夫曼树的概念、构建方法和应用场景,并结合Python代码进行演示。

哈夫曼树概念

哈夫曼树(Huffman Tree)又称最优树,它是一种带权路径长度最短的树。所谓带权路径长度,就是每个节点的权值乘以其到根节点的路径长度(即树的层数)之和。哈夫曼树广泛应用于数据压缩领域。

哈夫曼树构建方法

  1. 首先将需要编码的字符按照出现的频率从小到大排序,构造出对应的权重序列weights。
  2. 创建一个空的森林(即一组树),每个节点独立成树。
  3. 依次取出权重序列中的最小值,将其作为左右子节点合并为一棵树,同时删除权重序列中的这两个节点,将新生成的树加入到森林中。
  4. 重复步骤三,直到森林中只有一棵树为止,该树就是我们构建的哈夫曼树。

Python代码演示

HuffmanTree类定义

我们首先定义一个HuffmanTree类,用于存储哈夫曼树的节点和相关的操作方法。

class HuffmanTreeNode:  # 哈夫曼树节点类

    def __init__(self, weight, value=None):
        self.weight = weight    # 权值
        self.value = value      # 节点值(仅用于叶子节点)
        self.parent = None      # 父节点
        self.left_child = None  # 左子节点
        self.right_child = None # 右子节点


class HuffmanTree:

    def __init__(self, char_freq):
        self.char_freq = char_freq  # 字符-权值字典
        self.root = None            # 根节点
        self.leaves = []            # 叶子节点列表

    # 构造函数,根据char_freq创建哈夫曼树
    def build_tree(self):
        # 创建叶子节点
        for key, value in self.char_freq.items():
            node = HuffmanTreeNode(value, key)
            self.leaves.append(node)
        # 构建哈夫曼树
        while len(self.leaves) > 1:
            self.leaves.sort(key=lambda node: node.weight)  # 从小到大排序
            left_child = self.leaves.pop(0)                # 取出最小的节点作为左子节点
            right_child = self.leaves.pop(0)               # 取出次小的节点作为右子节点
            # 构建新节点
            weight = left_child.weight + right_child.weight
            parent = HuffmanTreeNode(weight)
            parent.left_child = left_child
            parent.right_child = right_child
            left_child.parent = parent
            right_child.parent = parent
            # 将新节点加入叶子节点列表中
            self.leaves.append(parent)
        self.root = self.leaves[0]    # 根节点为叶子节点列表中最后一个节点

调用HuffmanTree类

char_freq = {'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1}  # 构造字符-权值字典
tree = HuffmanTree(char_freq)   # 构建哈夫曼树
tree.build_tree()               # 构建过程

应用场景

哈夫曼树广泛应用于数据压缩领域。在压缩一个文件时,我们可使用哈夫曼编码将其中的字符表示为二进制码,并用更少的位数表示出出现概率较大的字符,用更多的位数表示出现概率较小的字符,从而达到压缩的效果。

示例演示

示例一:字符编码

为了将一个文件压缩,我们需要将其中的字符转换为哈夫曼编码(即二进制码)。下面是一个简单的示例:

mapping = tree.get_mapping()   # 获取字符-编码的映射

with open('test.txt', 'r') as f:
    text = f.read()
    encoded_text = ''
    for char in text:
        encoded_text += mapping[char]

在上述代码中,我们首先调用tree.get_mapping()方法获取字符-编码的映射,然后读取文件的每个字符,用相应的哈夫曼编码替换它,得到压缩后的字符串。

示例二:文件解码

压缩一个文件后,我们需要将其解压回原始文件。下面是一个简单的示例:

mapping = tree.get_mapping()   # 获取字符-编码的映射
reverse_mapping = dict([(value, key) for key, value in mapping.items()])

with open('compressed.bin', 'rb') as f:
    bit_string = ''
    byte = f.read(1)
    while byte != b'':
        byte = ord(byte)
        bits = bin(byte)[2:].rjust(8, '0')
        bit_string += bits
        byte = f.read(1)

current_code = ''
decompressed_text = ''
for bit in bit_string:
    current_code += bit
    if current_code in reverse_mapping:
        char = reverse_mapping[current_code]
        decompressed_text += char
        current_code = ''

print(decompressed_text)

在上述代码中,我们首先调用tree.get_mapping()方法获取字符-编码的映射,并创建一个相反的映射,即编码-字符的映射,用于解码。接着读取压缩后的二进制文件,将其每8个位分为一组,转换为一个字节,然后将每个字节转换为哈夫曼编码,读取完成后,我们依次从二进制字符串中取出位,拼接成编码,查询出对应的字符,并将其添加到解压后的字符串中。最终我们得到原始文件的字符串。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python描述数据结构学习之哈夫曼树篇 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C++高级数据结构之优先队列

    C++高级数据结构之优先队列 什么是优先队列? 优先队列是一种特殊的队列,其中每个元素都有一个优先级。当加入一个元素时,它会被放置在队列中的适当位置,以确保优先级最高的元素位于队头。从队列中取出元素时,总是从队头删除元素。 优先队列的应用 优先队列的常见应用场景包括: 操作系统任务调度 网络传输协议TCP中的拥塞控制算法 各种图像算法如边缘检测等 C++中S…

    数据结构 2023年5月17日
    00
  • GPS北斗卫星时间同步系统助力电力自动化网络系统

    GPS北斗卫星时间同步系统助力电力自动化网络系统 GPS北斗卫星时间同步系统助力电力自动化网络系统 京准电子官微——ahjzsz 前言 近几年来,随着电力自动化水平的提高,在电力中计算机监控系统、微机保护装置、微机故障录波装置以及各类数据管理机得到了广泛的应用,而这些自动装置的配合工作需要有一个精确统一的时间。当电力系统发生故障时,既可实现全站各系统在统一时…

    算法与数据结构 2023年5月8日
    00
  • Java数据结构学习之栈和队列

    Java数据结构学习之栈和队列 什么是栈 栈(stack)是一种线性数据结构,它只能在一端进行插入和删除操作,这一端被称作栈顶(top)。栈的特点是先进后出(FILO,First-In-Last-Out),即最后进入的元素最先被删除。 栈的实现方式 栈可以使用数组或链表来实现。使用数组实现的栈称作顺序栈,使用链表实现的栈称作链式栈。以下是顺序栈的 Java …

    数据结构 2023年5月17日
    00
  • nginx内存池源码解析

    Nginx内存池源码解析 Nginx是一个高性能、高并发的Web服务器。为了提高其性能和速度,Nginx采用了特殊的内存管理机制,即内存池。 什么是内存池? 内存池是一种高效的内存分配和管理机制。它将一块内存划分成多个大小相等的块,并按需分配给系统。当内存块不再使用时,它并不被立即释放,而是留在内存池中待重复利用。 Nginx内存池结构 Nginx内存池主要…

    数据结构 2023年5月17日
    00
  • 「分治」黑白棋子的移动

    本题为3月23日23上半学期集训每日一题中A题的题解 题面 题目描述 有2n个棋子(n≥4)排成一行,开始位置为白子全部在左边,黑子全部在右边,如下图为n=5的情形: ○○○○○●●●●● 移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能…

    算法与数据结构 2023年4月18日
    00
  • Go语言数据结构之二叉树必会知识点总结

    Go语言数据结构之二叉树必会知识点总结 二叉树是一种非常重要的数据结构,它被广泛应用于算法、数据处理等领域。在Go语言中,使用二叉树可以实现很多高级数据结构和算法。本文将为大家介绍二叉树相关的基本知识和操作,以及如何利用Go语言实现二叉树。 什么是二叉树? 二叉树是一种树形结构,由一个根节点和两个子树组成。它的每个节点最多有两个子节点,称为左子节点和右子节点…

    数据结构 2023年5月17日
    00
  • Java 数据结构与算法系列精讲之哈希算法实现

    Java 数据结构与算法系列精讲之哈希算法实现 什么是哈希算法? 哈希算法是一种能将任意长度的消息压缩到某一固定长度的消息摘要的算法。 通过哈希算法,我们可以将一个任意的大数据量压缩成一段固定长度的数据,这个数据的长度通常比较小,相对于原数据的大小来说,要小得多。哈希算法的压缩特性使得它经常用来进行信息摘要、数据校验、唯一识别等功能,可以很大程度上提高数据的…

    数据结构 2023年5月17日
    00
  • 8个简单部分开启Java语言学习之路 附java学习书单

    8个简单部分开启Java语言学习之路 如果你想要学习Java语言,但是不知道从何入手,在这里,我们将为你提供一份简单易懂的攻略,分8个步骤带你开启Java语言学习之路。 1. 安装Java开发工具 Java学习的第一步是安装Java开发工具,目前比较流行的Java开发工具有多种,例如Eclipse、Intellij IDEA、NetBeans等。本攻略以In…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部