浅谈【数据结构】树与二叉树之哈夫曼树

news2025/1/13 13:18:51

目录

1、哈夫曼树

1.1哈夫曼编码

1.2哈夫曼树

1.3构建一棵哈夫曼树


谢谢帅气美丽且优秀的你看完我的文章还要点赞、收藏加关注

没错,说的就是你,不用再怀疑!!!

希望我的文章内容能对你有帮助,一起努力吧!!!


1、哈夫曼树

1.1哈夫曼编码

在电报通信过程中,电文是以二进制0/1序列传送的,每一个字符对应了一个二进制的编码。

为了缩短按电文长度,采用不等长的编码方式,把使用频率较高的字符采用短编码。使用频率低的字符 采用长的编码。

1.2哈夫曼树

哈夫曼树:又称为最优二叉树

它是由n个带权的叶子结点构成的所有二叉树中,带权路径长度 WPL 最小的二叉树

一棵树的带权路径长度:树中所有叶子结点的带权路径长度之和。

结点的带权路径长度:从根结点开始到该结点的路径的长度与该结点上的权值的乘积。

1.3构建一棵哈夫曼树

假设N个权值,分别为W1,W2,W3....Wn的叶子结点,构建这一棵哈夫曼树的规则:

  • 第一步:
    • 构建森林
      • 把每一个叶子结点作为一棵独立的树看待(只有根结点的树),这样就拥有了n棵树的以 一个森林
      • 把森林存放到一个优先队列(不是队列)中,方便取出最小的结点。
  • 第二步:
    • 从优先队列中取出权值最小的两棵树(结点),再创建一棵新结点,将新结点设为两个最小结 点的父结点。父结点的权值就是两个结点的权值之和。
  • 第三步:
    • 将创建好的新结点加入到优先队列中。
  • 第四步:
    • 重复第二步和第三步直到优先队列中只剩一个结点,该节点就是哈夫曼树的根结点。

***示例代码***

#include <iostream>
#include <queue>


template <typename __queue_node_type__>
class priorityQueue
{
private:
    typedef struct node
    {
        __queue_node_type__ data;
        struct node *next;
    }Node;

    Node *first;
    Node *final;
    int   count;
public:
    priorityQueue()
        :first(nullptr)
        ,final(nullptr)
        ,count(0)
    {}
    ~priorityQueue()
    {}
    void push(__queue_node_type__ data_t)
    {
        // 新结点
        Node *new_ptr = new Node;
        new_ptr->data = data_t;
        new_ptr->next = nullptr;

        // 是否为链表中第一个结点
        if(count == 0)
        {
            first = new_ptr;
            final = new_ptr;
            // 更新个数
            count++;
            return;
        }
        else
        {
            if(first->data > data_t)
            {
                new_ptr->next = first;
                first = new_ptr;
                // 更新个数
                count++;
                return;
            }
            // 查找插入位置
            Node *node_ptr = first;
            while(node_ptr->next)
            {
                if(node_ptr->data > data_t)
                {
                    new_ptr->next = node_ptr->next;
                    node_ptr->next = new_ptr;
                    count++;
                    return;
                }
                node_ptr = node_ptr->next;
            }
        }

        final->next = new_ptr;
        final = new_ptr;
        count++;
        return;
    }
    __queue_node_type__ pop()
    {
        if(count == 0)
            throw int(-1);
        __queue_node_type__ data_t = first->data;

        Node *node_ptr = first;
        first = first->next;

        node_ptr->next = nullptr;
        delete node_ptr;
        count--;
        return data_t;
    }
    int length() const
    {
        return count;
    }
};



template <typename __tree_node_type__>
class HafuManTree
{
private:
    typedef struct node
    {
        __tree_node_type__ weight;
        struct node *lchild;
        struct node *rchild;
    } Node;

    Node *root;
public:
    HafuManTree(std::initializer_list<__tree_node_type__> list)
     : root(nullptr)
    {
        // 构建森林
        // 创建一个优先队列
        priorityQueue<Node*> queue;

        // 第一步:把所有的结点存入优先队列
        for(auto var : list)
        {
            Node *node_ptr = new Node;
            node_ptr->weight = var;
            node_ptr->lchild = nullptr;
            node_ptr->rchild = nullptr;
            queue.push(node_ptr);
        }

        // 第四步:重复第二步和第三步
        while(queue.length()!=1)
        {
            // 第二步:取出权值最小的两棵树(结点),再创建一棵新结点
            Node* data1 = queue.pop();
            Node* data2 = queue.pop();
            
            // 第三步创建新结点作为两个结点的父节点
            Node* newfather = new Node;
            newfather->weight = data1->weight + data2->weight;

            newfather->lchild = data1;
            newfather->rchild = data2;

            // 把新结点存入优先队列
            queue.push(newfather);
        }

        // 最后一个元素是哈夫曼树的根结点
        root = queue.pop();
    }


    ~HafuManTree(){}

    void levelprint()
    {
        std::queue<Node*> queque;

        queque.push(root);

        while(queque.size())
        {
            Node *node_ptr = queque.front();
            queque.pop();

            if(node_ptr->lchild)
                queque.push(node_ptr->lchild);
            if(node_ptr->rchild)
                queque.push(node_ptr->rchild);
            std::cout << node_ptr->weight << std::endl;
        }
    }
};


int main()
{
    HafuManTree<int> tree({1,2,3,4,5,6,7,8,9});

    tree.levelprint();
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【FPGA数字信号处理】什么是信号?

在数字信号处理的奇妙世界里&#xff01;“信号”是一切的基础&#xff0c;理解了信号&#xff0c;就相当于拿到了开启数字信号处理大门的钥匙。 今天&#xff0c;就让我们一起深入探究数字信号处理基础中的“信号”。 一、信号的基本概念 信号&#xff0c;简单来说&#xf…

【持续更新】Mχ Plaayer Pro 1.86.0安卓知名播放器最新免费高级修改版

Mχ Plaayer Pro MOD 版本免费 APK&#xff0c;专为安卓手机和平板打造。这是一款功能强大的视频播放器&#xff0c;具备先进的硬件加速技术和字幕支持功能。 • 硬件加速 - 新增 HW 解码器帮助更多视频格式实现硬件加速。 • 多核心解码 - Mχ Plaayer 是首款支持多核心解码的…

链接 -- 动静态链接 --特点、区别、静态库安装下载

1.链接是什么&#xff1f; 我们的程序&#xff0c;和 库&#xff08;语言一定会有自己的标准库&#xff09; 结合的过程就叫做链接。 2.为什么有链接&#xff1f; 让开发站在巨人的肩膀&#xff0c;提高开发效率。 c语言库&#xff1a; ls /user/include/ 动静态库的特点与区别…

领域驱动设计DDD详解与战术建模落地

一、什么是DDD&#xff1f; 1.1、DDD的概念 Domain-Driven Design&#xff08;领域驱动设计&#xff09;它由Eric Evans在他的2003年出版的书籍《Domain-Driven Design: Tackling Complexity in the Heart of Software》中首次提出。DDD 核心思想是通过领域驱动设计方法定义领…

COMSOL工业碱性电解槽(3D、双欧拉模型)

本案例通过改写COMSOL官方案例获得&#xff0c;使用了碱性电解槽和欧拉-欧拉&#xff08;湍流&#xff09;模型&#xff0c;阳极室和阴极室带有乳突状的结构&#xff0c;模型进行了人为缩小&#xff0c;仅供参考。其中一些参数可参考如下链接文章的说明。COMSOL碱性电解槽参数解…

在NextChat中接入SiliconCloud API 体验不同的开源先进大语言模型

NextChat介绍 One-Click to get a well-designed cross-platform ChatGPT web UI, with GPT3, GPT4 & Gemini Pro support. 一键免费部署你的跨平台私人 ChatGPT 应用, 支持 GPT3, GPT4 & Gemini Pro 模型。 主要功能 在 1 分钟内使用 Vercel 免费一键部署提供体积…

Cyberchef实用功能之-json解析美化和转换

本文将介绍如何使用cyberchef的json操作功能&#xff0c;根据自己的需求处理常见的json问题。 在网络安全日常的运营&#xff0c;护网行动&#xff0c;重保活动的过程中&#xff0c;经常需要查看多种平台的json格式日志&#xff0c;如下&#xff1a; 以json格式存储的防火墙日…

基于Python Django的保险数据分析系统优化要点

&#x1f393; 作者&#xff1a;计算机毕设小月哥 | 软件开发专家 &#x1f5a5;️ 简介&#xff1a;8年计算机软件程序开发经验。精通Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等技术栈。 &#x1f6e0;️ 专业服务 &#x1f6e0;️ 需求定制化开发源码提…

畅捷通CRM newleadset.php SQL注入漏洞复现

0x01 产品简介 用友畅捷通CRM是面向小企业全力打造的简单、实用的客户关系管理应用。帮助企业用好自己的客户资源、管好商机跟进过程、引导好业务员跟单行为,促进团队销售能力的提升;通过查询和分析,识别企业的价值客户,融合电话、短信、邮件等工具,实现精准营销;帮助企…

STM32(F103ZET6)第一课:按键控制LED灯和蜂鸣器

目录 功能要求一、开发思路二、详细过程1.查看原理图2.各模块编写LED灯按键使用蜂鸣器 功能要求 设备上电&#xff0c;4个灯灭 按键1按下&#xff0c;4个灯灭 按键2按下&#xff0c;4个灯亮 按键3按下&#xff0c;蜂鸣器响 按键4按下&#xff0c;蜂鸣器关闭 一、开发思路 1.…

ARM32开发——(八)中断

1. 中断概念 中断是计算机系统中的一种机制&#xff0c;用于响应外部事件或内部事件,它可以使单片机暂时中断正在执行的程序&#xff0c;转而去执行一个中断处理函数&#xff0c;待中断处理函数执行完毕后&#xff0c;再回到原来的程序继续执行。中断机制使得计算机可以响应各…

【已解决】Win11任务栏怎么使用小图标_Win11任务栏调整图标大小方法

使用注册表编辑器 1、打开运行&#xff0c;并输入 regedit 命令&#xff0c;确定或回车&#xff0c;可以打开注册表编辑器。 2、注册表编辑器窗口&#xff0c;依次展开到以下路径&#xff1a; HKEY_CURRENT_USER-Software-Microsoft -Windows-CurrentVersion-Explorer-Advanc…

『功能项目』技能释放【08】

我们打开上一篇07摄像机跟随角色的项目&#xff0c; 本章要做的事情是摄像机跟随主角移动&#xff0c; 首先创建一个空文件夹Resources 创建一个球体Shpere 修改球体缩放尺寸 创建一个材质Material 将材质重命名为Yellow&#xff0c;色板调至为黄色 将Yellow材质球拖拽至球体S…

0基础学习spark

零、pyspark模板 import os from pyspark import SparkContext, SparkConf os.environ[SPARK_HOME] /export/server/spark os.environ[PYSPARK_PYTHON] /root/anaconda3/bin/python3 os.environ[PYSPARK_DIRVER_PYTHON] /root/anaconda3/bin/python3 if __name__ __main__:…

物联网---ESP32

物联网---ESP32 一、TCP/IP协议(互联网协议)二、MQTT协议(通信协议)2.1 MQTT基本原理2.2 连接MQTT服务端 三、ESP323.1 ESP介绍3.2 ESP32连接云端3.2.1 ESP32连接WIFI/MQTT3.2.2 OneNET云端 一、TCP/IP协议(互联网协议) TCP/IP是一组用于互联网及其他网络中数据传输的通信协议…

MySQL集群 主从复制 和 高可用 配置详解

安装数据库 1、环境依赖 [rootmysql-node10 ~]# yum install cmake gcc-c openssl-devel ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el9_4.x86_64.rpm rpcgen.x86_64 -y2、下载软件包 3、进行解压 [rootmysql ~]# tar zxf mysql-boost-5.7.44.tar.gz4、生成源码 #进入…

zotero同步之infiniteCLOUD网盘 WebDAV

zotero zotero打开 编辑->首选项->同步 一、数据同步 数据同步&#xff0c;申请并登录zotero账号&#xff0c;免费额度300M&#xff0c;用于存储条目信息。 二、文件同步 有zotero和WebDAV两种形式&#xff0c;zotero是直接把pdf存储在zotero账号中&#xff0c;免费…

【面试问题汇总】

面试问题汇总: Math.round函数:基础加0.5,向下取整 MySQL查询执行流程: 当我们执行一条SQL查询语句时,MySQL数据库会按照以下步骤进行处理: 语法解析器会对SQL语句进行解析,检查SQL语法是否正确。元数据查询器会检查查询的表和字段是否存在,以及当前用户是否具有相应…

前端通过draggable结合fabricjs实现拖拽至画布生成元素自定义编排功能

前端通过draggable结合fabricjs实现拖拽自定义编排功能 太久没有更新了&#xff0c;主要最近行情不太好失业了一段时间&#xff0c;一度到怀疑人生&#xff0c;然后就是做的东西大多没有什么含金量&#xff0c;没什么好分享的就很尴尬。 刚好最近遇到一个奇葩的需求&#xff0…

SparkSQL日期时间模式详解

datatime使用场景 CSV/JSON数据源使用模式字符串来解析和格式化日期时间内容。日期时间函数用于转换StringType类型到DateType或TimestampType类型&#xff0c;反之亦然。例如&#xff0c;unix_timestamp, date_format, to_unix_timestamp, from_unixtime, to_date, to_timest…