数据结构 —— 哈夫曼树

数据结构 —— 哈夫曼树

  • 哈夫曼树
      • 定义
      • 构造算法
      • 特性
      • 应用
  • 哈夫曼编码
      • 核心概念
      • 工作原理
      • 特点

我们今天来看哈夫曼树

哈夫曼树

哈夫曼树(Huffman Tree),是一种特殊的二叉树,由D.A. Huffman在1952年提出,主要用于数据压缩,特别是哈夫曼编码(Huffman Coding)中。以下是关于哈夫曼树的全面概念:

定义

哈夫曼树是一种带权路径长度最短的二叉树,也称为最优二叉树。它是在给定一组具有不同权重的叶子节点(通常代表数据中的符号或字符)的情况下,通过特定的构建算法得到的。该树的特点是,所有叶子节点位于最底层或倒数第二层,且没有度为1的节点(除了根节点可能外),同时保证了从根节点到任何叶子节点的路径上的权值之和(即带权路径长度)最小。

举个例子:
在这里插入图片描述
在这里插入图片描述

构造算法

  1. 初始化:将每个权重作为一个叶子节点,放入一个优先队列(优先级基于节点权重,通常使用最小堆实现)。
  2. 合并节点:从队列中取出两个权重最小的节点,创建一个新的内部节点,其权重为这两个节点的权重之和,新节点作为这两个节点的父节点。
  3. 重复步骤2:将新创建的节点放回优先队列,重复上述过程,直到队列中只剩下一个节点,该节点即为哈夫曼树的根节点。
  4. 生成编码:从根到每个叶子节点的路径可以转化为一个唯一的二进制字符串(路径上向左走记为0,向右走记为1),这个字符串就是该叶子节点代表的字符的哈夫曼编码。

在这里插入图片描述这里我没有写得那么复杂,我用一个vector维护森林,并且排好序,然后依次拿出构造哈夫曼树:

#pragma once
#include<algorithm>
#include<iostream>
#include<vector>

// 定义霍夫曼树节点结构体
template<class T>
struct HuffManTreeNode
{
public:
    // 构造函数,初始化节点数据、左孩子和右孩子
    HuffManTreeNode(T data)
            :_data(data)
            , _leftchild(nullptr)
            , _rightchild(nullptr)
    {

    }

    // 拷贝构造函数,用于复制已有节点的信息
    HuffManTreeNode(HuffManTreeNode<T>* node)
            :_data(node->_data)
            , _leftchild(node->_leftchild)
            , _rightchild(node->_rightchild)
    {

    }

    // 析构函数
    ~HuffManTreeNode()
    {

    }

    // 创建新节点并返回指针
    HuffManTreeNode<T>* CreateNode(T data)
    {
        HuffManTreeNode<T>* newnode = new HuffManTreeNode(data);
        return newnode;
    }

    // 根据已有节点创建新节点并返回指针
    HuffManTreeNode<T>* CreateNode(HuffManTreeNode<T>* node)
    {
        HuffManTreeNode<T>* newnode = new HuffManTreeNode(node);
        return newnode;
    }

    // 向树中插入新节点
    void Insert(HuffManTreeNode<T>*& node, T data)
    {
        HuffManTreeNode<T>* newnode = CreateNode(data);

        if (newnode == nullptr)
        {
            perror("new fail");
            return;
        }

        if (node->_leftchild == nullptr)
        {
            node->_leftchild = newnode;
        }
        else if (node->_rightchild == nullptr)
        {
            node->_rightchild = newnode;
        }

        return;
    }

    // 向树中插入已有节点
    void Insert(HuffManTreeNode<T>*& node, HuffManTreeNode<T>* temp)
    {
        if (node->_leftchild == nullptr)
        {
            node->_leftchild = CreateNode(temp);
        }
        else if (node->_rightchild == nullptr)
        {
            node->_rightchild = CreateNode(temp);
        }
        return;
    }

    // 重载赋值运算符
    HuffManTreeNode<T>& operator=(const HuffManTreeNode<T>* node)
    {
        if (this == node)
        {
            return *this;
        }

        _data = node->_data;
        _leftchild = node->_leftchild;
        _rightchild = node->_rightchild;

        return *this;
    }

    // 数据成员
    T _data;
    // 左右孩子指针
    HuffManTreeNode<T>* _leftchild;
    HuffManTreeNode<T>* _rightchild;
};

// 中序遍历霍夫曼树
template<class T>
void Inorder(HuffManTreeNode<T>* node)
{
    if (node == nullptr)
    {
        return;
    }

    Inorder(node->_leftchild); // 遍历左子树
    std::cout<< node->_data << " "; // 访问当前节点
    Inorder(node->_rightchild); // 遍历右子树
}
#include"Huffman.h"

int main()
{
   std::vector<int> vt = {1,45,12,56,78,0,1,3};
   std::sort(vt.begin(),vt.end());

   for(auto e : vt)
   {
       std::cout << e << " ";
   }

   std::cout<<std::endl;

   //创建哈夫曼树
   HuffManTreeNode<int>* node = new HuffManTreeNode(vt[0]+vt[1]);

   node->Insert(node,vt[0]);
   node->Insert(node,vt[1]);

   for(int i = 2 ; i < vt.size(); i++)
   {
       HuffManTreeNode<int>* temp = node;

       node = node->CreateNode(node->_data +vt[i]);

       node->Insert(node,temp);
       node->Insert(node,vt[i]);
   }

   Inorder(node);

   return 0;
}

在这里插入图片描述

特性

  • 最优性:在所有叶子节点数量相同且节点权值已知的二叉树中,哈夫曼树的带权路径长度是最小的。
  • 编码效率:哈夫曼编码根据字符出现的频率分配编码,高频字符的编码较短,低频字符的编码较长,从而在整体上达到高效的数据压缩效果。
  • 无损编码:哈夫曼编码是一种无损数据压缩方法,可以完全恢复原始数据。
  • 自适应性:虽然经典哈夫曼编码基于静态概率模型,但存在变体如自适应哈夫曼编码,能够根据数据流动态调整编码表,适用于数据统计特性随时间变化的情况。

应用

  • 数据压缩:广泛应用于文本、图像、音频等数据的无损压缩。
  • 通信系统:优化数据传输,减少带宽需求。
  • 文件存储:减小文件大小,节约存储空间。
  • 编译器:用于词法分析中的关键字识别,通过为常用关键字分配较短编码,提高解析速度。

哈夫曼编码

哈夫曼编码(Huffman Coding)是一种高效的熵编码(Entropy Encoding)方法,用于无损数据压缩。它是基于哈夫曼树(Huffman Tree)构造的一种数据编码方式,由David A. Huffman在1952年提出。以下是哈夫曼编码的核心概念、工作原理以及特点:

核心概念

哈夫曼编码的基本思想是根据数据中各个符号(如字符、像素值等)出现的频率来为它们分配不同的编码,出现频率高的符号分配较短的编码,而频率低的符号则分配较长的编码。这样,当整个数据集被编码时,由于高频符号使用的短编码能频繁重复,从而实现整体数据量的压缩。

工作原理

  1. 频率统计:首先统计待编码数据中每个符号出现的频率。
  2. 构建哈夫曼树:使用频率作为权重,通过哈夫曼树的构造算法(见前述哈夫曼树的构造过程),构建一棵二叉树。在这个过程中,每次都将两个最小频率的节点合并成一个新的节点,新节点的频率是两个子节点频率之和。
  3. 生成编码:从哈夫曼树的根到每个叶子节点的路径定义了该叶子节点代表符号的编码。具体来说,向左分支时编码添加一个“0”,向右分支时添加一个“1”。因此,叶子节点越深,其对应的编码就越长。
  4. 编码数据:使用生成的哈夫曼编码表对原始数据进行编码,即将数据中的每个符号替换为其对应的编码字符串。

特点

  • 无损编码:哈夫曼编码是一种无损数据压缩技术,意味着解码后可以完全恢复原始数据。
  • 自适应性:虽然标准哈夫曼编码需要预先知道数据的概率分布,但可以通过动态哈夫曼编码技术,在不知道全部数据的情况下逐步更新编码表,适应数据流的变化。
  • 效率:在所有前缀编码(即任意编码都不会是另一个编码的前缀)中,哈夫曼编码提供了理论上的最优平均编码长度,即熵的上限。
  • 简单性:尽管编码效率高,哈夫曼编码的算法实现相对直接且易于理解。

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/750182.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

php聚合快递寄快递小程序

一、引言&#xff1a;告别传统寄件&#xff0c;拥抱便捷新选择 在数字化时代&#xff0c;我们越来越追求便捷和高效。传统的寄件方式已经无法满足现代人快速、便捷的需求。因此&#xff0c;一款聚合快递优惠寄件小程序应运而生&#xff0c;它集合了多家快递公司&#xff0c;为…

推荐两款电脑文件处理工具,强大到你不舍得卸载

EasyFileCount EasyFileCount是一款基于Java开发的多功能文件管理工具&#xff0c;旨在帮助用户更轻松地管理和优化他们的文件存储。以下是EasyFileCount的主要功能和特点&#xff1a; 查看文件夹大小&#xff1a;用户可以快速统计和查看文件夹的总大小&#xff0c;实时显示各…

计算机组成原理——系统总线

题目:计算机使用总线结构便于增减外设,同时__C____。 A.减少了信息传送量 B.提高了信息传输速度 C.减少了信息传输线的条数 1. 总线的分类 1.1. 片内总线 芯片内部的总线 在CPU芯片内部,寄存器与寄存器之间、寄存器与逻辑单元ALU之间 1.1.1. 数据总线 双向传输总线 数…

ISO37001认证:防范贿赂风险的强大工具

随着全球反贿赂法规的日益严格&#xff0c;各类组织面临的贿赂风险和合规压力不断增加。ISO37001反贿赂管理体系认证应运而生&#xff0c;为组织提供了一个系统化的管理框架&#xff0c;帮助其有效发现、预防和管控贿赂风险。本文将详细探讨ISO37001认证的作用和意义&#xff0…

刷代码随想录有感(119):动态规划——打家劫舍III(树形dp)

题干&#xff1a; 代码&#xff1a; class Solution { public:vector<int>dp(TreeNode* cur){if(cur NULL)return vector<int>{0, 0};vector<int> left dp(cur -> left);vector<int> right dp(cur -> right);//偷int val1 cur -> val l…

U-boot相关基础知识

U-boot和Bootloader之间的关系 U-Boot是Bootloader的一种实现&#xff0c;它专门用于嵌入式系统&#xff0c;特别是那些基于ARM、MIPS等处理器的系统。U-Boot提供了丰富的硬件支持和功能&#xff0c;使得开发者能够轻松地初始化硬件、加载操作系统内核&#xff0c;并进行一些基…

Adobe Indesign 操作

页面设置 版面&#xff1a;图文和空白部分的总和。 版心&#xff1a;规划在版面中排印文本和图片的部分。 开本&#xff1a;单个页面的宽度和高度。 如图所示&#xff0c;新建文件&#xff0c;自定义是210297毫米。这个数据是开本大小。 点击“边距和分栏”&#xff0c;出现…

技术干货|SimLab 电子产品热流体仿真

电子产品热仿真特点有哪些&#xff1f; 结构复杂&#xff0c;电子设备包含几十~上千个元器件 体积小&#xff0c;功率密度高、关注热敏感元器件 多种冷却方式&#xff0c;自然冷却、风扇冷却、液冷、热管等 多维度&#xff0c;芯片级&#xff0c;板级&#xff0c;系统级 单…

.idea文件夹里面iml文件有啥用

.idea文件夹和其中的.iml文件对于IntelliJ IDEA项目非常重要&#xff0c;它们共同构成了IDEA对项目理解的基础。让我们详细了解一下这两者的作用&#xff1a; .idea文件夹 .idea文件夹包含了IntelliJ IDEA项目的所有配置信息&#xff0c;包括但不限于&#xff1a; 编译器设置…

掌握SEO:如何优化用ChatGPT生成的文章以提升搜索排名

在数字化时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;已经成为网站流量的重要来源。随着人工智能技术的进步&#xff0c;越来越多的人开始使用ChatGPT等AI工具来生成文章。然而&#xff0c;虽然这些工具可以快速生成内容&#xff0c;但要确保这些内容在搜索引擎中…

武汉星起航:深度洞察消费趋势,亚马逊美国站选品独具匠心

亚马逊美国站作为全球电商巨头的重要分支&#xff0c;其选品特点不仅反映了美国市场的消费趋势&#xff0c;更引领着全球消费者的购物潮流。从运动户外、宠物用品到美容个人护理&#xff0c;亚马逊美国站的选品策略始终紧跟市场脉搏&#xff0c;为消费者提供丰富多样、品质优良…

Maven高级理解属性

属性 在这一章节内容中&#xff0c;我们将学习两个内容&#xff0c;分别是 属性版本管理 属性中会继续解决分模块开发项目存在的问题&#xff0c;版本管理主要是认识下当前主流的版本定义方式。 4.1 属性 4.1.1 问题分析 讲解内容之前&#xff0c;我们还是先来分析问题: …

docker harbor仓库搭建,主从库复制

背景&#xff1a;需要主机安装docker-ce和docer-compose #1.安装相关依赖. yum install -y yum-utils device-mapper-persistent-data lvm2 #2.下载官方的docker yum源文件 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo …

QT项目实战:拼图小游戏

一、拼图智益-经典游戏&#xff08;开发环境&#xff09; 1&#xff1a;操作系统&#xff1a;Windows 10 x64专业版。 2&#xff1a;开发工具&#xff1a;Qt 5.12.8。 二、拼图智益-经典游戏&#xff08;功能模块&#xff09; 1&#xff1a;功能模块1&#xff1a;游戏启动…

C#校园在线投票系统-计算机毕业设计源码10577

摘 要 随着互联网大趋势的到来&#xff0c;社会的方方面面&#xff0c;各行各业都在考虑利用互联网作为媒介将自己的信息更及时有效地推广出去&#xff0c;而其中最好的方式就是建立网络管理系统&#xff0c;并对其进行信息管理。由于现在网络的发达&#xff0c;校园投票通过网…

服务器重装系统后,远程ssh需要修改的内容

前提 首先实验室服务器内部是搭了内网的&#xff0c;所以有固定的IP,IP是和网卡的MAC地址有关的&#xff0c;所以和系统没有关系&#xff0c;所以更换了系统不会影响IP的。 修改内容 1、首先需要安装 SSH sudo apt install openssh-server2、之后需要修改ssh的配置参数 打…

社交App广告优化新篇章:Xinstall引领用户体验升级,助力买量效果提升

随着移动互联网的快速发展&#xff0c;社交App已经成为人们生活中不可或缺的一部分。然而&#xff0c;在竞争激烈的市场环境下&#xff0c;如何有效地进行广告投放&#xff0c;吸引并留住用户&#xff0c;成为了每个社交App运营者面临的重大挑战。今天&#xff0c;我们就来谈谈…

软件系统测试包括哪些测试内容?有什么作用?

在软件开发的过程中&#xff0c;软件系统测试是不可或缺的环节。它是为了验证并评估软件系统的功能、性能以及其它需要满足的特性。那么&#xff0c;软件系统测试包括哪些测试呢?又有什么作用? 软件系统测试是通过执行一系列策略和技术&#xff0c;检测软件系统是否满足用户…

气象相关图表制作-字体图标、图片、折线的堆叠

开发工作中有个需要展示气温&#xff08;折线&#xff09;、天气&#xff08;图片&#xff09;、风羽&#xff08;字体图标&#xff09;的图表展示需求&#xff0c;之前用过highcharts的关于类似的chart&#xff0c;里面的风雨用的是自带的图片&#xff0c;但是现在要求风羽需要…

一站式自动化测试工具——AI-TestOps

文章目录 软件测试的重要性龙测科技是什么&#xff1f;核心优势平台使用 软件测试的重要性 软件测试在整个软件生命周期里&#xff0c;具有十分关键的地位&#xff0c;学校只可以在运行与后期维护时期以前&#xff0c;软件调试瀑布模型&#xff0c;是一类常规的运行方式&#…