哈夫曼树

首先,先复习一下二叉树的一些基本知识

树:是一种非线性数据结构。

二叉树:是每个结点最多有两个子树的有序树

根节点:最上面的节点

叶节点:没有子树的节点

深度:二叉树的层数,就是高度。

右图就是一个二叉树,A为根节点,D、E、F为叶节点,深度为2

那么什么是哈弗曼树呢?

哈夫曼树是最优二叉树,何为最优二叉树?就是每个叶节点到根节点的路径都是唯一且最短的。节点的权值越大则离根节点越远。其中,权值一般是该节点内容出现的频率。

大家可能会有疑问,为什么哈弗曼树是最优的呢?为什么可以起到压缩文件的作用呢?

我们学过的线性数据结构有数组、链表和栈,当数据以这种数据结构存储的时候,我们搜索数据就要依次遍历直至找到该数据。而哈夫曼树就简化了遍历的过程,我们在建哈夫曼树的规则是:

1.将数组数据从小到大排序。

2.生成一个新的节点,该节点的权值是最小的节点的权值和,该节点是最小两个节点的父节点。

3.在数组数据中除去最小的两个节点,加上新的节点。

4.排序

5.依次循环,只剩一个节点,该节点则为根节点。

因此,当我们在查找某个数据的时候,只要从根节点开始遍历,大于根节点在左子树,小于根节点在右子树。很快就可以找到。

而且,在存储数据的时候利用哈夫曼树也可以对数据进行压缩。例如:A B C D E 这几个字母,他们的权值分别是5,4,3,2,1.我们在进行存储的时候就可以如图利用他们的哈弗曼编码对数据进行压缩。

下面是我写的哈弗曼编码的java代码,其中实现了建树,和遍历输出哈弗曼编码

package Sameple0505哈弗曼树;
		/**
		 * 实现哈弗曼树的主要类
		 * @author Administrator
		 *
		 */
	public class Test{
		private Node[] leaf =null;//该树的叶节点数组
		private int length=0;//叶节点数组的长度
		private int size=0;
		private int count=0;//用来记录用户输入元素的个数
		private Node result =null;//初始化Node
		public Node getRoot(){
			return result;
		}
		public Test(int size){
			this.size=size;
			leaf=new Node[this.size];
		}
		public Test(){}
		/**
		 * 给叶节点数组添加值
		 * @param data 添加进来的叶节点内容
		 * @param weight 添加进来的叶节点的权值
		 */
	    public void addNode(Object data,int weight){
	    	Node temp =new Node(data,weight);
	    	leaf[length++]=temp;
		}
	   /**
	    * 给节点进行冒泡排序,从小到大排序,返回排好序的数组
	    * @param nodes
	    * @return
	    */
	    public Node[] SortNode(Node[] nodes){
	    	for(int i=0;i<nodes.length;i++){
	    		for(int j=i+1;j<nodes.length;j++){
	    		if(nodes[i].getwgt()>nodes[j].getwgt()){
	    			Node tem=nodes[i];
	    			nodes[i]=nodes[j];
	    			nodes[j]=tem;
	    		}
	    	 }
	      }
	    	return nodes;
	    }
		    /**
		     * 建立哈弗曼树,从下往上建树
		     * @return
		     */
				public Node createTree(){
					//判断哈弗曼树是否建好,如果建好则只剩根节点,length为1
					while(length>1){
						leaf=SortNode(leaf);//先按权值排序
						//新节点的权值为左右节点之和
						result=new Node(leaf[0].getwgt()+leaf[1].getwgt());
						//分别给左右节点设置父节点
						leaf[0].setFather(result);
						leaf[1].setFather(result);
						result.setRight(leaf[0]);//第二个元素为左节点,左边大,右边小
						leaf[0].setPosition(0);//添加位置参数
						result.setLeft(leaf[1]);//设置第一个元素为右节点
						leaf[1].setPosition(1);//添加位置参数
						leaf=newNode(leaf, 2);
						length--;
						leaf[length-1]=result;
					}
					System.out.println(result.getwgt());
					return result;
			     	}
				/**
				 * 建树过程中不断减少的的数组
				 * @param nodes 新的数组
				 * @param num  减少的个数
				 * @return
				 */
				public Node[] newNode(Node[] nodes,int num){
				    Node[] newnodes=new Node[nodes.length-num+1];
					for (int i = 0; i < nodes.length-num; i++) {
						newnodes[i]=nodes[i+num];
					}
					return newnodes;
				}
				/**
				 * 从根节点开始遍历哈弗曼树,打印出叶节点上字母的哈弗曼编码
				 * @param args
				 */
				public void printhfm(Node leaf){
					if (leaf.getLeft()==null&&leaf.getRight()==null) {
						//输出叶节点的内容
						System.out.println(leaf.getData()+"的哈弗曼编码是: ");
						String posString="";//储存哈弗曼编码
						while(leaf.getFather()!=null){
							posString=leaf.getPosition()+posString;
							leaf=leaf.getFather();
						}
						System.out.println(posString);
					}else {	
						printhfm(leaf.getLeft());
					    printhfm(leaf.getRight());
					}
					}
				
				/**
				 *包装方法
				 */
				public void showcode(){
					Node temp=createTree();
					printhfm(temp);
				}
				

	    }
	     

 

这是哈夫曼树的节点类:

package Sameple0505哈弗曼树;

/**
 * 二叉树节点类
 * @author 邵珂
 *
 */

public class Node {
	private Object data;//节点的内容
	private int weight;//节点的权值
	private Node father=null;//父节点
    private Node left=null;//左孩子
	private Node right=null;//右孩子
	private String position=null;//设置该节点在父节点的位置,左边添加1,右边添加0
	/**
	 * 重写构造方法,创建叶节点时使用
	 * @param data  传入的叶节点的内容
	 * @param weight 叶节点的权值
	 */
	public Node(Object data,int weight) {
		this.data = data;
		this.weight=weight;
	}
	/**
	 * 重写构造方法,创建非叶结点时使用
	 * @param weight 权值
	 */
	public Node(int weight){
		this.weight=weight;
	}
	/**
	 * 默认的构造方法
	 */
	public Node(){}
	/**
	 * 返回该节点存储的内容
	 * @return
	 */
	public Object getData() {
		return data;
	}

	/**
	 * 返回该节点的权值
	 * @return
	 */
	public int getwgt(){
		return weight;
	}
	/**
	 * 返回该节点的父节点
	 * @return
	 */
	public Node getFather() {
		return father;
	}
	/**
	 * 设置该节点的父节点
	 * @param father 父节点
	 */
	public void setFather(Node father) {
		this.father = father;
	}
	/**
	 * 返回该节点的左孩子
	 * @return
	 */
	public Node getLeft() {
		return left;
	}
	/**
	 * 设置该节点的左孩子
	 * @param left
	 */
	public void setLeft(Node left) {
		this.left = left;
	}
	/**
	 * 返回该节点的右孩子
	 * @return
	 */
	public Node getRight() {
		return right;
	}
	/**
	 * 设置该节点的右孩子
	 * @param right
	 */
	public void setRight(Node right) {
		this.right = right;
	}
	/**
	 * 获取该节点是处于父节点的左边还是右边
	 * @return
	 */
	public String getPosition() {
		return position;
	}
	/**
	 * 设置该节点是在父节点的左边还是右边,左边传1,右边传0
	 * @param position
	 */
	public void setPosition(int position) {
		this.position = ""+position;
	}
	
	
	
	
	

}

 

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

相关推荐

哈夫曼树(c语言)

用C语言实现哈夫曼树,给定n个权值作为n个叶子结点,构造一棵二叉树,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

数据结构与算法—哈夫曼树详解与构造

文章目录介绍 介绍 定义: 给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。 简而言之,就是按照一个贪心思想和规则进行树的构造,而构造出来的这个树的权值最小! 其中WPL表示计算出的权值。至于为什么按照哈夫曼树方法构造得到的权重最小。这里...

bigsai 1万+

主成分分析避坑指南:为什么你的PCA结果总是不理想?

本文深入剖析了主成分分析(PCA)在实际应用中效果不佳的常见原因与解决方案。针对数据标准化、协方差矩阵选择、主成分数量确定、载荷矩阵解读等关键环节,提供了详细的避坑指南和诊断方法,并探讨了PCA的局限性及非线性数据结构下的备选方案,帮助数据分析师获得更稳健、可解释的降维结果。

convnet3designer的博客 512

哈夫曼树你需要了解一下

哈夫曼树(Huffman Tree)是一种特殊的二叉树,也被称为最优二叉树。在计算机科学中,它是由权值作为叶子节点构造出来的一种二叉树。哈夫曼树的特点是,对于给定的n个权值,构造出的哈夫曼树具有最小的带权路径长度(WPL)。具体来说,哈夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码。这个变长编码表是通过评估来源符号出现机率的方法得到的。出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码。这样,编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

技术人集结地 1220

基于Ardupilot/PX4固件,APM/PIXhawk硬件的VTOL垂直起降固定翼软硬件参数调试(第二篇)软硬件参数调试

基于Ardupilot/PX4固件,APM/PIXhawk硬件的VTOL垂直起降固定翼软硬件参数调试(第二篇) 本文内容大部分来自Kris,我们的K大,在VTOL领域的大牛,在此,非常感谢K大。能引用K大的成果也是自己的荣幸,不便之处还请K大多多包涵,在此引用只是为方便自己日常学习,部分参数表里根据自身情况,增加了修改环节和相应参数。 垂直起降固定翼 中文教程-参数设置 垂直起降固定翼是由 多轴+...

u011322358的博客 2万+

5、基于模型的系统工程(MBSE)全面解析

本文全面解析了基于模型的系统工程(MBSE),介绍了模型在系统工程中的核心地位,以及如何通过视图和符号表示法实现信息的可视化。文章还详细阐述了MBSE的方法构成,包括框架(本体和视图点)和流程集,探讨了MBSE的实施流程、关键要素、应用策略以及未来发展趋势。通过合理应用MBSE,组织可以提高系统开发的效率和质量,降低成本与风险,实现成功部署。

nft7creator的博客 127

哈夫曼树的长度

哈夫曼树的长度 哈夫曼树也称最优二叉树,最优指的是其带权路径和最小,而哈夫曼树的长度也指的是其带权路径和。 一般而言,求其长度时,应当将其按照构造的方式进行构造之后,计算每个叶节点的值乘以权重之后的和。 在这个图中,绿色的节点即叶子节点,故此树的长度WPL为 WPL=1×3+2×3+3×2+3×2+4×2=29 WPL = 1\times 3 + 2 \times 3 + 3\times 2+3...

薛定谔抓猫的博客 3020

数学之美:欣赏超越数e

文章目录一、e为何物?二、利息与e的关系1、利息问题2、计算利息3、欣赏螺旋线(1)螺旋线概述(2)绘制螺旋线三、e和π 一、e为何物? e是一个无限不循环小数,其值约等于2.718281828…,它是一个超越数,有时也称为欧拉数(Euler’s Number)。 以e为底的对数称为自然对数(Natural Logarithm),数学中使用自然这个词的还有自然数(Natural Number)。 这里的“自然”并不是现代人所习惯的“大自然”,而是有点儿“天然存在,非人为”的意思。 二、利息与e的关系

howard2005的专栏 1718

哈夫曼树和哈夫曼编码

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

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

windows exe爬虫:exe抓包

在不知情所拦截应用使用的流量时,所以建议用Wireshark。本文利用python代码,实现自动拦截,写入pcap包,并用代码分析流量的协议。这样会在本地目录下生成capture_inbound.pcap,可以用wireshark分析,也可以利用python代码进行分析,如果使用python代码进行分析,需要借助pyshark或者scapy。使用的python WinDivert的包,当然前提也是需要安装Wireshark软件,设置环境变量,并安装pydirvert包。

youbingchen的博客 618

C#调用企业微信JS-Sdk实现扫描二维码

企业微信JS-SDK是企业微信面向网页开发者提供的基于企业微信内的网页开发工具包。通过使用企业微信JS-SDK,网页开发者可借助企业微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用企业微信分享、扫一扫等企业微信特有的能力,为企业微信用户提供更优质的网页体验提示:生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是H5应用调用企业微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。

清浅 937

【树】哈夫曼树及其构造

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

weixin_45765128的博客 4万+

【半导体工业实战】C#.NET开发SECS/GEM协议上位机(完整可运行源码+全进制转换工具类+工业级通信封装)

在半导体这个高精尖的工业领域,SECS/GEM协议是设备通信的基石,而C#.NET凭借其稳定性、高效的字节处理能力、Windows工控机的深度适配,成为SECS上位机开发的最优选择。本文从半导体行业的专属认知出发,提供了完整的进制转换工具类、工业级的SECS通信封装、实战的报文解析与业务调用示例、半导体专属的避坑指南,所有内容均为真实项目经验的沉淀,无空洞理论、无AI冗余文字,所有源码均可直接编译运行、无缝移植到半导体项目中。半导体工控开发的核心,从来不是炫技,而是。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 898

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

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

weixin_52958292的博客 5403

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Huffman树(哈夫曼树)

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

南方以北 1万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

哈夫曼树的绘制

数据结构之哈夫曼树绘制本人还是一个年轻的程序猿(还是个学生),请大家多多指教! 哈夫曼树 已知权重绘制哈夫曼树 开始我的表演 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万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

哈夫曼树以及哈夫曼算法

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

kxbdys的博客 6131

java 实现哈夫曼树

一、 什么是哈夫曼树 要理解什么是哈夫曼树,首先要理解几个概念 路径:从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径。 路径长度:路径上的分支数目。 树的路径长度:从树根到每一个结点的路径长度之和。(完全二叉树就是树的路径长度最短的二叉树) 考虑带权的结点 结点的带权路径长度:从该结点到树根之间的路径长度和结点上权的乘积。 树的带权路径长度:树的所有结点的带权路径之和(...

www_chinese_com的博客 5376
上一篇: File应用之文件搜索器(关键字搜索)
下一篇: 运算符小记
rootke
博客等级 码龄12年 1粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值