哈夫曼树

【数据结构基础】树 - 哈夫曼树(Huffman Tree) 路径与路径长度: 从树中一个节点到另一个节点之间的分支构成了两个节点之间的路径,路径上的分支数目称作路径长度。树的带权路径长度: 树的带权路径长度为所有叶子节点的带权路径长度之和,称为WPL。在森林中选出根结点的权值最小的两棵树进行合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;从根节点到每一个叶子节点的路径上,左分支记为0,右分支记为1,将这些0与1连起来即为叶子节点的哈夫曼编码。节点的权: 将树中的节点赋予一个某种含义的数值作为该节点的权值,该值称为节点的权; 阅读详情

1,什么是哈夫曼树?

2,如何构建哈夫曼树?

3,哈夫曼编码?

4,算法实现?

一,什么是哈夫曼树

什么是哈夫曼树呢?

哈夫曼树是一种带权路径长度最短的二叉树,也称为最优二叉树。下面用一幅图来说明。

ds48

它们的带权路径长度分别为:

图a: WPL=5*2+7*2+2*2+13*2=54

图b: WPL=5*3+2*3+7*2+13*1=48

可见,图b的带权路径长度较小,我们可以证明图b就是哈夫曼树(也称为最优二叉树)。

二,如何构建哈夫曼树

一般可以按下面步骤构建:

1,将所有左,右子树都为空的作为根节点。

2,在森林中选出两棵根节点的权值最小的树作为一棵新树的左,右子树,且置新树的附加根节点的权值为其左,右子树上根节点的权值之和。注意,左子树的权值应小于右子树的权值。

3,从森林中删除这两棵树,同时把新树加入到森林中。

4,重复2,3步骤,直到森林中只有一棵树为止,此树便是哈夫曼树。

下面是构建哈夫曼树的图解过程:

ds52

三,哈夫曼编码

利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子节点都有一条路径,对路径上的各分支约定指向左子树的分支表示”0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为各个叶子节点对应的字符编码,即是哈夫曼编码。

就拿上图例子来说:

A,B,C,D对应的哈夫曼编码分别为:111,10,110,0

用图说明如下:

ds50

记住,设计电文总长最短的二进制前缀编码,就是以n个字符出现的频率作为权构造一棵哈夫曼树,由哈夫曼树求得的编码就是哈夫曼编码。

四,算法实现

C#版:

复制代码
namespace HuffTree.CSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            //四个叶子节点
            int leafNum = 4;

            //赫夫曼树的节点总数
            int totalNodes = 2 * leafNum - 1;

            //各叶子节点的权值
            int[] weight = new int[] { 5,7,2,13};

            //各叶子节点的值
            string[] alphabet = new string[] { "A","B","C","D"};

            //初始化赫夫曼树
            HuffmanTree[] huffmanTree = new HuffmanTree[totalNodes].Select(p => new HuffmanTree() { }).ToArray();

            //构建赫夫曼树
            HuffmanTreeBLL.Create(huffmanTree,leafNum,weight);

            //赫夫曼编码
            string[] huffmanCode = HuffmanTreeBLL.Coding(huffmanTree,leafNum);

            //打印结果
            PrintResult(alphabet,huffmanTree,huffmanCode,leafNum);

            Console.ReadKey();
        }

        /// <summary>
        /// 打印结果
        /// </summary>
        /// <param name="alphabet"></param>
        /// <param name="huffmanTree"></param>
        /// <param name="huffmanCode"></param>
        /// <param name="leafNum"></param>
        private static void PrintResult(string[] alphabet,HuffmanTree[] huffmanTree,string[] huffmanCode,int leafNum)
        {
            if (alphabet.Count() < 1 || huffmanTree.Count() < 1 || huffmanCode.Count() < 1) return;

            for (int i = 0; i < leafNum; i++)
            {
                Console.WriteLine("字符:{0},权重值:{1},赫夫曼编码:{2}",alphabet[i],huffmanTree[i].Weight,huffmanCode[i]);
            }
        }
    }
}

namespace DS.BLL
{
    /// <summary>
    /// 描述:赫夫曼树操作类
    /// 作者:鲁宁
    /// 时间:2013/9/17 18:14:33
    /// </summary>
    public class HuffmanTreeBLL
    {
        /// <summary>
        /// 构建赫夫曼树
        /// 思路:一步一步向上搭建
        /// </summary>
        /// <param name="huffmanTree">待操作的赫夫曼树</param>
        /// <param name="leafNum">叶节点数量</param>
        /// <param name="weight">节点权重值</param>
        /// <returns>构建好的赫夫曼树</returns>
        public static HuffmanTree[] Create(HuffmanTree[] huffmanTree, int leafNum, int[] weight)
        {
            //获取赫夫曼树结点总数
            int totalNodes = 2 * leafNum - 1;

            InitLeafNode(huffmanTree,leafNum,weight);
            
            //构造赫夫曼树(4个节点只需要3步就可以完成构建)
            for (int i = leafNum; i < totalNodes; i++)
            { 
                //获取权重最小的两个叶子节点的下标
                int minIndex1 = -1;
                int minIndex2 = -1;
                SelectNode(huffmanTree,i,ref minIndex1,ref minIndex2);

                huffmanTree[minIndex1].Parent = i;
                huffmanTree[minIndex2].Parent = i;

                huffmanTree[i].Left = minIndex1;
                huffmanTree[i].Right = minIndex2;
                huffmanTree[i].Weight = huffmanTree[minIndex1].Weight + huffmanTree[minIndex2].Weight;
            }
            return huffmanTree;
        }

        /// <summary>
        /// 赫夫曼编码
        /// 思路:左子树为0,右子树为1,对应的编码后的规则是:从根节点到子节点
        /// </summary>
        /// <param name="huffmanTree">待操作的赫夫曼树</param>
        /// <param name="leafNum">叶子节点的数量</param>
        /// <returns>赫夫曼编码</returns>
        public static string[] Coding(HuffmanTree[] huffmanTree, int leafNum)
        { 
            string[] huffmanCode= new string[leafNum];

            //当前节点下标
            int current = 0;
            //父节点下标
            int parent = 0;

            for (int i = 0; i < leafNum; i++)
            {
                string codeTemp = string.Empty;
                current = i;
                
                //第一次获取最左节点
                parent = huffmanTree[current].Parent;

                while (parent != 0)
                {
                    if (huffmanTree[parent].Left == current) codeTemp += "0";
                    else codeTemp += "1";

                    current = parent;
                    parent = huffmanTree[parent].Parent;
                }
                huffmanCode[i] = new string(codeTemp.Reverse().ToArray());
            }
            return huffmanCode;
        }


        /// <summary>
        /// 初始化叶节点
        /// </summary>
        /// <param name="huffmanTree"></param>
        /// <param name="leafNum"></param>
        /// <param name="weight"></param>
        private static void InitLeafNode(HuffmanTree[] huffmanTree, int leafNum, int[] weight)
        {
            if (huffmanTree == null || leafNum<1 || weight.Count()<1) return;

            for (int i = 0; i < leafNum; i++)
            {
                huffmanTree[i].Weight = weight[i];
            }
        }

        /// <summary>
        /// 获取叶子节点中权重最小的两个节点
        /// </summary>
        /// <param name="huffmanTree">待操作的赫夫曼</param>
        /// <param name="searchNode">要查找的节点数</param>
        /// <param name="minIndex1"></param>
        /// <param name="minIndex2"></param>
        private static void SelectNode(HuffmanTree[] huffmanTree, int searchNode, ref int minIndex1, ref int minIndex2)
        {
            HuffmanTree minNode1 = null;
            HuffmanTree minNode2 = null;

            for (int i = 0; i < searchNode; i++)
            {
                //只查找独根树叶子节点
                if (huffmanTree[i].Parent == 0)
                {
                    //如果为null,则表示当前节叶子节点最小
                    if (minNode1 == null)
                    {
                        minIndex1 = i;
                        minNode1= huffmanTree[i];
                        continue;
                    }

                    if (minNode2 == null)
                    {
                        minIndex2 = i;
                        minNode2= huffmanTree[i];

                        //交换位置,确保minIndex1为最小
                        if (minNode1.Weight >= minNode2.Weight)
                        { 
                            //节点交换
                            var temp = minNode1;
                            minNode1 = minNode2;
                            minNode2 = temp;

                            //交换下标
                            var tempIndex = minIndex1;
                            minIndex1 = minIndex2;
                            minIndex2 = tempIndex;

                            continue;
                        }
                    }

                    if (minNode1 != null && minNode2 != null)
                    {
                        if (huffmanTree[i].Weight < minNode1.Weight) //注意,不能是“<=”
                        {
                            //将min1临时转存给min2
                            minNode2 = minNode1;
                            minNode1 = huffmanTree[i];

                            //记录在数组中的下标
                            minIndex2 = minIndex1;
                            minIndex1 = i;
                        }
                        else
                        {
                            if (huffmanTree[i].Weight < minNode2.Weight)
                            { 
                                minNode2= huffmanTree[i];
                                minIndex2 = i;
                            }
                        }
                    }
                }
            }
        }
    }

    /// <summary>
    /// 赫夫曼树存储结构
    /// </summary>
    public class HuffmanTree
    {
        public int Weight { get; set; } //权值

        public int Parent { get; set; } //父节点

        public int Left { get; set; } //左孩子节点

        public int Right { get; set; } //右孩子节点
    }
}
复制代码

程序输出结果为:

ds51


原文链接:http://www.cnblogs.com/mcgrady/p/3329825.html


最优二叉树—哈夫曼(huffman)树 哈夫曼树又称最优二叉树,是一类带权路径长度最短的二叉树,有着广泛的应用。基本概念权:将树中的结点赋上一个有着某种意义的数值路径:从A结点道B结点所经过的分支序列路径长度:从A结点道B结点所经过的分支数目查找效率平均查找长度(ASL)取决于树的高度ASL=(1+2*2+3)/4=2 ASL=(1+2+3... 阅读详情

相关推荐

哈夫曼树及哈夫曼树编码译码详解

使用链表形式,实现哈夫曼树的构建及编码译码

m0_73555097的博客 2920

哈夫曼树原理解析,构造方法,意义和作用。

哈夫曼树(最优二叉树) 百度百科:https://baike.baidu.com/item/%E5%93%88%E5%A4%AB%E6%9B%BC%E6%A0%91/2305769?fr=aladdin 一. 目的: 找出存放一串字符所需的最少的二进制编码 二. 构造方法: 首先统计出每种字符出现的频率!(也可以是概率)//权值 ----------------------------...

Anakki的博客 30万+

树 —— 哈夫曼树和哈夫曼编码

基本概念 哈夫曼树又叫最优二叉树,它是由 n 个带权叶子结点构成的所有二叉树中带权路径长度 WPL 最短的二叉树。 路径:指从一个结点到另一个结点之间的分支序列。 路径长度:指从一个结点到另一个结点所经过的分支数目。 树的路径长度:树中所有叶子结点的路径长度之和。 权:给树的每个结点赋予一个具有某种实际意义的实数,我们称该实数为这个结点的权。 带权路径长度:在树形结构中,我们把...

starter_____的博客 1478

哈夫曼树(Huffman)【数据结构】

假如

m0_73065213的博客 1万+

单细胞多组学数据整合分析实战:从原始数据到跨平台合并

本文详细介绍了单细胞多组学数据整合分析的实战流程,从原始数据处理到跨平台合并分析。通过Seurat和Harmony等工具的应用,帮助研究者有效解决批次效应问题,保留真实的生物学信号。文章包含代码示例和常见问题解决方案,特别适合需要进行单细胞合并分析的研究人员参考。

weixin_30752699的博客 90

网络安全 —— 实验(基于华为eNSP模拟器)

8. 实验八 —— 通过路由的远程管理(基于实验七的基础配置)8. 实验八 —— 通过路由的远程管理(基于实验七的基础配置)6. 实验六 —— 交换机的远程控制(直接控制和间接控制)6. 实验六 —— 交换机的远程控制(直接控制和间接控制)5. 实验五 —— 将交换机作为PC端通过交换机相连。5. 实验五 —— 将交换机作为PC端通过交换机相连。4. 实验四 —— 两个PC机通过两台交换机相连。2. 实验二 —— 两个PC机通过交换机相连。2. 实验二 —— 两个PC机通过交换机相连。

这个家伙看起来很懒,只想把你留下来哦 9338

哈 夫 曼 树

哈夫曼树

NOSaac的博客 1万+

【C语言项目合集】这十个入门必备练手项目,让C语言对你来说不再难学!

适合刚入门C语言的编程学习小白的十个练手项目,每个都很经典且实用,让你学完C语言不再迷茫!

kxtxdy的博客 3万+

哈夫曼树和哈夫曼编码

本文主要是用C语言实现数据结构之哈夫曼树,同时对应哈夫曼编码。

墨城烟柳ベ旧人殇的博客 5016

警惕!数字签名伪造的攻防演练:用SigThief克隆证书的真实测试(Windows环境)

本文深入探讨了Windows环境下数字签名伪造的攻防技术,详细介绍了使用SigThief工具进行签名提取与克隆的实战步骤。通过真实测试案例,揭示了数字签名安全机制的潜在漏洞,并提供了有效的防御策略和检测技术,帮助安全人员提升系统防护能力。

weixin_42530732的博客 408

FX2N-2AD模块实战:从硬件连接到FROM/TO指令编程详解

本文详细解析FX2N-2AD模拟量输入模块的硬件连接与FROM/TO指令编程技巧,涵盖BFM缓冲存储器配置、梯形图程序设计及工程实战经验。通过实例演示如何实现精准信号采集与数据处理,特别针对PLC系统中的常见故障提供解决方案,助力工业自动化工程师高效完成设备调试与维护。

prometheus9mon的博客 507

【树】哈夫曼树及其构造

1.哈夫曼树的基本概念 结点间的路径和路径长度 路径是指从一个结点到另一个结点之间的分支序列 路径长度是指从一个结点到另一个结点所经过的分支数目。 结点的权和带权路径长度 在实际的应用中,人们==给树的每个结点赋予一个具有某种实际意义的实数,称该实数为这个结点的权。==在树型结构中,把从树根到某一结点的路径长度与该结点的权 的乘积,叫做该结点的带权路径长度。  树的带权路径长度 树的带权路径...

weixin_45765128的博客 4万+

Ubuntu 22.04下Minkowski Engine编译避坑指南:解决Cuda 12.2与Pytorch cu118版本冲突

本文详细介绍了在Ubuntu 22.04系统中解决Minkowski Engine编译时Cuda 12.2与Pytorch cu118版本冲突的实用方法。通过修改版本检查逻辑、创建兼容符号链接等技巧,帮助开发者顺利完成编译,并提供了性能优化建议和替代方案,确保三维点云处理任务的高效运行。

weixin_42543309的博客 161

【哈夫曼树】创建哈夫曼树

在一棵树中,从一个结点到另外一个结点所经过得所有的结点,我们成为两个结点之间得路径。从A到叶子结点E的路径就是:A->B->D->E;在一棵树中,从一个几点到另外一个结点所经过的边的数量,就是路径长度。从根结点A到叶子结点E,共经过了3条边,因此路径长度是3。树的每一个结点,都可以拥有自己的“权重”(weight),权重在不同的算法中起到不同的作用。结点的带权路径长度 = 树的根节点到该结点的路径长度 * 该结点权重。

weixin_52958292的博客 5402

别再凭感觉选电容了!手把手教你计算电机控制器里的母线电容(附Excel计算工具)

本文详细解析了电机控制器中母线电容的选型方法,从理论计算到工程实践,帮助工程师避免常见误区。通过精确计算纹波电压、电容容量等关键参数,并结合薄膜电容与电解电容的性能对比,提供实用的选型建议。附带的Excel计算工具可快速完成参数计算,适用于工业伺服驱动和电动车电机控制器设计。

weixin_28720573的博客 518

第25节:cesium 地形开挖综合实例-地下管网(含源码+视频)

地图开挖综合示例,包括底图切换,绘制开挖区域,移除开挖区域,影藏地图等等。

qq_29384639的博客 1781

Huffman树(哈夫曼树)

哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以...

南方以北 1万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

哈夫曼树的绘制

数据结构之哈夫曼树绘制本人还是一个年轻的程序猿(还是个学生),请大家多多指教! 哈夫曼树 已知权重绘制哈夫曼树 开始我的表演 Step 1. 已知权重:2,3,3,4,7,6 Step 2. 选取其中小的两个权重:2,3 Step 3. 把2,3作为孩子结点如下图: Step 4. 重复Step 2的步骤取出权重值里两个较小的权重值3,4并进行绘制树,如下图: Step 5. 重复Step 2的步骤

yypClever的博客 2万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

哈夫曼树以及哈夫曼算法

一、哈夫曼树的定义 1、哈夫曼树:最优树即带权路径长度(WPL)最短的树 “带权路径长度最短”是在"度相同”的树中比较而得的结果,因此有最优二叉树、最优三叉树之称等等。 2、哈夫曼树:最优二叉树即带权路径长度(WPL)最短的二叉树 因为构造这种树的算法是由哈夫曼教授于1952年提出的,所以被称为哈夫曼树,相应的算法称为哈夫曼算法。 二、哈夫曼树的特点 1、满二叉树不一定是哈夫曼树 2、哈夫曼树中权越大的叶子离根越近 3、具有相同带权结点的哈夫曼树不唯一 三、哈夫曼算法(构造哈夫曼树的方法)

kxbdys的博客 6131

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

上一篇: 阿里云Maven库配置
下一篇: 大数据/数据挖掘/推荐系统/机器学习相关资源
! 不再维护
博客等级 码龄11年 63粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值