哈夫曼树、哈夫曼编码/解码

这篇具有很好参考价值的文章主要介绍了哈夫曼树、哈夫曼编码/解码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

哈夫曼树

哈夫曼树的基本介绍

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树构建步骤图解

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

创建哈夫曼树代码实现

""" 创建哈夫曼树 """
class EleNode:
    """ 节点类 """
    def __init__(self, value: int):
        self.value = value
        self.left = None  # 指向左子节点
        self.right = None  # 指向右子节点

    def __str__(self):
        return f"Node [value={self.value}]"

    def pre_order(self):
        """前序遍历二叉树"""
        if self is None:
            return
        # 先输出父节点
        print(self, end=' => ')
        # 左子树不为空则递归左子树
        if self.left is not None:
            self.left.pre_order()
        # 右子树不为空则递归右子树
        if self.right is not None:
            self.right.pre_order()


class HuffmanTree:
    arr: list = None

    def __init__(self, arr):
        self.arr = arr

    def create_huffman_tree(self) -> EleNode:
        # 对 arr 列表进行升序排序
        self.arr.sort()
        # 遍历数组,将每个数组元素构建成一个 Node 节点
        # 将 Node 节点加入到一个新列表中
        node_list = []
        for i in self.arr:
            node_list.append(EleNode(i))

        # 循环进行以下步骤,直到列表中只剩下一棵二叉树,此时该二叉树就是哈夫曼树
        while len(node_list) > 1:
            # 取出权值序列中最小的两课二叉树(即列表中的前两个元素)构建一棵新的二叉树
            left = node_list.pop(0)
            right = node_list.pop(0)
            # 新二叉树的根节点的权值=两个节点权值之和
            parent = EleNode(left.value + right.value)
            # 让新二叉树的左右节点分别指向两个最小的节点
            parent.left = left
            parent.right = right
            # 将新二叉树根据根节点的大小插入到序列中的指定位置
            i = 0
            n = len(node_list)
            while i < n:
                if node_list[i].value >= parent.value:
                    node_list.insert(i, parent)  # 找到了根节点存放的位置
                    break
                i += 1
            else:
                # 循环结束表示新的二叉树的权值最大,在node_list列表中没有比它大的
                # 所以添加到列表最后
                node_list.append(parent)

        # 此时列表中只有一棵二叉树,即所求的哈夫曼树
        # 返回哈夫曼树的根结点
        return node_list[0]


huffman = HuffmanTree([13, 7, 8, 3, 29, 6, 1])
node = huffman.create_huffman_tree()
node.pre_order()

哈夫曼编码

基本介绍

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼编码原理剖析

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼编码的实例

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

思路分析

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树

代码实现

""" 哈夫曼编码 """
class CodeNode:
    def __init__(self, data: int, weight: int):
        self.data = data  # 存放字符对应的ASCII码值
        self.weight = weight  # 存放字符在字符串中出现的次数
        self.left = None
        self.right = None

    def __str__(self):
        return f"Node[data={chr(self.data) if self.data else None}, weight={self.weight}]"

    def pre_order(self):
        """二叉树的前序遍历"""
        print(self)
        if self.left:
            self.left.pre_order()
        if self.right:
            self.right.pre_order()


class HuffmanCode:
    # 哈夫曼编码表
    # 存储每个字符对应的编码
    # key为对应的字符,val为字符对应的编码
    huffman_code_tab = {}
    # 记录哈夫曼二进制编码字符串最后一个段的长度
    # 即会将哈夫曼二进制字符串按八位进行分割,分割到最后一个时长度可不为8
    # 所以用一个变量存储最后一段二进制字符串的长度,在解码的时候会用到
    last_char_len = 0

    def create_huffman_tree(self, s: str) -> CodeNode:
        """
        构建哈夫曼编码二叉树
        :param s: 要编码的字符串
        :return:
        """
        # 遍历字符串,统计每一个字符出现的次数,并将结果放入字典
        kw = {}
        for ch in s:
            ascii_code = ord(ch)
            if kw.get(ascii_code):  # 如果该字符出现过,则直接将其次数加1
                kw[ascii_code] += 1
            else:  # 如果没出现过,则出现次数为1
                kw[ascii_code] = 1

        # 按照字符出现的次数对字典进行排序
        kw = sorted(kw.items(), key=lambda kv: (kv[1], kv[0]))
        # 遍历字典,将每个元素构建成一个 Node 节点
        # 将 Node 节点加入到一个新列表中
        node_list = []
        for k, v in kw:
            # print(chr(k),'=', v, end=', ')
            node_list.append(CodeNode(k, v))

        # 循环进行以下步骤,直到列表中只剩下一棵二叉树,此时该二叉树就是哈夫曼树
        while len(node_list) > 1:
            # 取出权值序列中最小的两课二叉树(即列表中的前两个元素)构建一棵新的二叉树
            left = node_list.pop(0)
            right = node_list.pop(0)
            # 新二叉树的根节点的权值=两个节点权值之和
            parent = CodeNode(None, left.weight + right.weight)
            # 让新二叉树的左右节点分别指向两个最小的节点
            parent.left = left
            parent.right = right
            # 将新二叉树根据根节点的大小插入到序列中的指定位置
            n = len(node_list)
            i = 0
            while i < n:
                if node_list[i].weight >= parent.weight:
                    node_list.insert(i, parent)  # 找到了根节点存放的位置
                    break
                i += 1
            else:
                # 循环结束表示新的二叉树的权值最大,在node_list列表中没有比它大的
                # 所以添加到列表最后
                node_list.append(parent)

        # 此时列表中只有一棵二叉树,即所求的哈夫曼树
        # 返回哈夫曼树的根结点
        return node_list[0]

    def get_huffman_code_tab(self, ele_node: CodeNode, code: str, code_str: str):
        """
        遍历所创建的哈夫曼树,得到所有叶子节点(叶子结点即要得到的字符)的编码
        这里规定左节点为0,右节点为1
        :param ele_node: 传入的要遍历的树的根节点,初始为根节点
        :param code: 表示所选择的路径是左节点还是右节点
        :param code_str: 每个字符对应的编码
        :return:
        """
        code_str += code  # 拼接编码
        if ele_node.data is None:
            # 表示是非叶子节点,因为在创建哈夫曼树时设置了为叶子结点的data为空
            # code_str += code
            if ele_node.left:
                self.get_huffman_code_tab(ele_node.left, '0', code_str)
            if ele_node.right:
                self.get_huffman_code_tab(ele_node.right, '1', code_str)
        else:  # 是叶子节点
            self.huffman_code_tab[chr(ele_node.data)] = code_str

    def huffman_zip(self, s: str) -> list:
        """
        利用哈夫曼编码表把字符串中的每一个字符转换成对应的编码
        即将一个字符串根据哈夫曼编码进行压缩,得到一个压缩后的结果
        :param s: 要转换的字符串
        :return: 返回编码后的列表
        """
        res = ''
        # 遍历字符串,将每一个字符转换成对应的编码,并将所有编码拼接起来
        # "i like like like java do you like a java" => 以下形式
        # 1100111111101110001011111110111000101111111011100010100001011000101011
        # 001100001011001000011001110111111101110001011010100001011000101
        for i in s:
            res += self.huffman_code_tab[i]
        # 将得到的编码字符串按八位进行分割,将每八位转换成一个int,并将int存放到列表中
        code_list = []
        i = 0
        n = len(res)
        while i < n:
            num = int(res[i:i + 8], 2)  # 将二进制字符串转换为整数
            code_list.append(num)
            i += 8
            if i < n <= i + 8:  # 已经分割到了最后一部分,记录该部分的长度
                self.last_char_len = n - i

        return code_list

    def huffman_decode(self, code_list) -> str:
        """
        将哈夫曼编码进行解压,得到一个可阅读的字符串
        :param code_list: 要解压的哈夫曼编码列表
        :return: 解码后的字符串
        """
        # 将哈夫曼编码列表转换成对应的二进制字符串
        # [415, 476, 95, 476, 95, 476, 80, 177, 345, 389, 400, 206, 254, 226, 212, 44, 5] =>
        # 1100111111101110001011111110111000101111111011100010100001011000101011
        # 001100001011001000011001110111111101110001011010100001011000101
        code_str = ''  # 存储对应的二进制字符串
        count = 0
        n = len(code_list)
        for i in code_list:
            t = "{:08b}".format(i)  # 将整数转换为二进制字符串
            code_str += t
            count += 1
            if count == n - 1:
                break
        code_str += "{:0{k}b}".format(code_list[count], k=self.last_char_len)

        # 将哈夫曼编码表的键值互换
        # 比如原来的是'a': '001' => 变成 '001': 'a'
        code_tab = {}
        for k, v in self.huffman_code_tab.items():
            code_tab[v] = k

        # 遍历二进制字符串
        j = 0
        i = 1
        n = len(code_str)
        res_code = ''  # 解码后的字符串
        while i <= n:
            t = code_str[j:i]
            ch = code_tab.get(t)
            if ch:
                res_code += ch
                j = i
            i += 1
        return res_code


s = "i like like like java do you like a java"
# s = "I love python hahha nihao"
huffman = HuffmanCode()
root_node = huffman.create_huffman_tree(s)
huffman.get_huffman_code_tab(root_node, '', '')
huffman_code_list = huffman.huffman_zip(s)
decode_str = huffman.huffman_decode(huffman_code_list)
print(decode_str)

使用哈夫曼编码压缩文件的注意事项(代码胜省略)

哈夫曼树、哈夫曼编码/解码,数据结构和算法,算法,数据结构,python,霍夫曼树文章来源地址https://www.toymoban.com/news/detail-720689.html

到了这里,关于哈夫曼树、哈夫曼编码/解码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】实验十:哈夫曼编码

    实验十 哈夫曼编码 一、实验目的与要求 1 )掌握树、森林与二叉树的转换; 2 )掌握哈夫曼树和哈夫曼编码算法的实现; 二、 实验内容 1.  请编程实现如图所示的树转化为二叉树。 2.  编程实现一个哈夫曼编码系统,系统功能包括: (1)  字符信息统计:读取待编码的源文

    2024年02月15日
    浏览(48)
  • (数据结构)哈夫曼编码实现(C语言)

    哈夫曼的编码:从一堆数组当中取出来最小的两个值,按照左下右大的进行绘制,将两个权值之和,放入队列当中,然后再进行取出两个小的,以此类推,直到全部结束,在根据图根节点,到叶子节点,每一个分支来得出编码,向左0,向右1,即可得到一个结果。

    2024年02月16日
    浏览(54)
  • 【数据结构--哈夫曼编码(C语言版)】

    哈夫曼树 介绍哈夫曼树前先介绍下面几个名词: 1. 结点的路径长度 l 从根结点到该结点的路径上分支的数目 ,如下图结点 a 的 l = 3 。 2. 树的路径长度 树中所有叶子结点的路径长度之和 ,如下图该树的路径长度为 2 + 3 + 3 + 2 + 2 。 3. 结点的权 w 给每一个结点赋予一个新的数

    2024年02月04日
    浏览(51)
  • C语言---数据结构实验---哈夫曼树及哈夫曼编码的算法实现---图的基本操作

    本篇实验代码非本人写,代码源自外部,经调试解决了部分warning和error后在本地vs上可以正常运行,如有运行失败可换至vs 未来会重构实现该两个实验 内容要求: 1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树 2、建立编码

    2024年02月13日
    浏览(59)
  • 【数据结构与算法】哈夫曼编码(最优二叉树)实现

    哈夫曼编码 等长编码:占的位置一样 变长编码(不等长编码):经常使用的编码比较短,不常用的比较短 最优:总长度最短 最优的要求:占用空间尽可能短,不占用多余空间,且不能有二义性 这里给出哈夫曼二叉树的实现: HuffmanTree.h: 测试数据(主函数): 运行结果截图

    2024年02月16日
    浏览(47)
  • 【数据结构与算法】哈夫曼编码(最优二叉树实现

    哈夫曼编码 等长编码:占的位置一样 变长编码(不等长编码):经常使用的编码比较短,不常用的比较短 最优:总长度最短 最优的要求:占用空间尽可能短,不占用多余空间,且不能有二义性 这里给出哈夫曼二叉树的实现: HuffmanTree.h: 测试数据(主函数): 运行结果截图

    2024年02月16日
    浏览(45)
  • 数据结构 实验17:Huffman树和Huffman编码——学习理解哈夫曼树

    目录 前言 实验要求 算法描述 个人想法 代码实现和思路、知识点讲解 知识点讲解 文件传输 Huffman树的存储 Huffman的构造  Huffman编码 编码和译码 代码实现 文件写入和输出 Huffman树初始化 构造Huffman树 求带权路径长度 Huffman编码 Huffman译码 结束 代码测试 测试结果 利用Huffman编

    2024年02月03日
    浏览(61)
  • 哈夫曼树、哈夫曼编码/解码

    哈夫曼树的基本介绍 哈夫曼树构建步骤图解 创建哈夫曼树代码实现 基本介绍 哈夫曼编码原理剖析 哈夫曼编码的实例 思路分析 代码实现 使用哈夫曼编码压缩文件的注意事项(代码胜省略)

    2024年02月08日
    浏览(41)
  • 哈夫曼树,哈夫曼编码及解码详解

    🌍新人小白的博客 ⌛️希望大家多多关注 🌱一起加油,共同成长 🎃以后会经常更新哒~🙈 ⭐️个人主页: 收藏加关注,永远不迷路~⭐️ 一: 顺序表的操作,你真的学会了吗? 二: 顺序栈的基本操作 三: 循环队列的基本操作,你学会了吗? 四: 单链表的操作(超详细

    2024年02月05日
    浏览(46)
  • 数据结构【哈夫曼树】

    最优二叉树也称哈夫曼 (Huffman) 树 ,是指对于一组带有确定权值的叶子结点,构造的具有最小带权路径长度的二叉树。权值是指一个与特定结点相关的数值。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。 涉及到的几个概念: 路径: 从树中一个结点到另一个结

    2024年02月14日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包