哈弗曼树

数据结构之哈弗曼树与哈弗曼编码 一.哈弗曼树和哈弗曼编码先知 哈弗曼树是二叉树中一种特殊的树,也被称为最优二叉树。其通过某种规则(权值)来构造出一哈夫曼二叉树,在这个二叉树中,只有叶子节点才是有效的数据节点,其他的非叶子节点是为了构造出哈夫曼而引入的! 哈夫曼编码是通过哈夫曼树进行的一种编码,一般情况下,以字符‘0’与‘1’表示。编码的实现过程很简单,只要实现哈夫曼树,通过遍历哈夫曼树,规定向左子树遍历一个节点编码为“0”,... 阅读详情

https://www.jb51.net/article/90728.htm
https://blog.youkuaiyun.com/bruce_6/article/details/38656413
http://www.cnblogs.com/ssyfj/p/9472733.html

定义:

节点之间的路径长度:在树中从一个结点到另一个结点所经历的分支,构成了这两个结点间的路径上的经过的分支数称为它的路径长度
树的路径长度:从树的根节点到树中每一结点的路径长度之和。在结点数目相同的二叉树中,完全二叉树的路径长度最短。
结点的权:在一些应用中,赋予树中结点的一个有某种意义的实数。
结点的带权路径长度:结点到树根之间的路径长度与该结点上权的乘积。
树的带权路径长度(Weighted Path Length of Tree:WPL):定义为树中所有叶子结点的带权路径长度之和

最优二叉树:从已给出的目标带权结点(单独的结点) 经过一种方式的组合形成一棵树.使树的权值最小.。最优二叉树是带权路径长度最短的二叉树。根据结点的个数,权值的不同,最优二叉树的形状也各不相同。
它们的共同点是:带权值的结点都是叶子结点。权值越小的结点,其到根结点的路径越长。

如,给定4个叶子结点a,b,c和d,分别带权7,5,2和4。构造如下图所示的三棵二叉树(还有许多棵),它们的带权路径长度分别为:
这里写图片描述

(a)WPL=7*2+5*2+2*2+4*2=36
(b)WPL=7*3+5*3+2*1+4*2=46
(c)WPL=7*1+5*2+2*3+4*3=35

其中(c)树的WPL最小,可以验证,它就是哈夫曼树。

注意:
① 叶子上的权值均相同时,完全二叉树一定是最优二叉树,否则完全二叉树不一定是最优二叉树。
② 最优二叉树中,权越大的叶子离根越近。
③ 最优二叉树的形态不唯一,WPL最小。


哈夫曼树特点:

1.没有度为1的结点
2.n个叶子节点的哈夫曼树共有2n-1个结点

树的特点:度为2结点和叶结点的关系n2=n0-1
所以:当叶结点为n时,度为二的结点数为n-1
因为哈夫曼没有度为一的结点,所以一共在树中有2n-1个结点

3.哈夫曼树任意非叶结点的左右子树交换后还是哈夫曼树
4.对同一组权值{w1,w2,…,wn},是会存在不同结构的哈夫曼树


构造哈夫曼树

1) 根据给定的n个权值{w1, w2, w3, w4……wn}构成n棵二叉树的森林 F={T1 , T2 ,
T3…..Tn},其中每棵二叉树只有一个权值为wi 的根节点,其左右子树都为空;

2) 在森林F中选择两棵根节点的权值最小的二叉树,作为一棵新的二叉树的左右子树,且令新的二叉树的根节点的权值为其左右子树的权值和;

3)从F中删除被选中的那两棵子树,并且把构成的新的二叉树加到F森林中;

4)重复2 ,3 操作,直到森林只含有一棵二叉树为止,此时得到的这棵二叉树就是哈夫曼树。

构造过程如下图:
这里写图片描述

例子2:

有一个字符串:aaaaaaaaaabbbbbaaaaaccccccccddddddfff

第一步,我们先统计各个字符出现的次数,称之为该字符的权值。a 15 ,b 5, c 8, d 6, f 3。

第二步,找去这里面权值最小的两个字符,b5和f3,构建节点。
这里写图片描述

然后将f3和b5去掉,现在是a15,c8,d6,fb8。

第三步,重复第二步,直到构建出只剩一个节点。
这里写图片描述

现在是dfb14,a15,c8。

这里写图片描述

最后,
这里写图片描述

构建的步骤

 1.统计字符串中字符以及字符的出现次数;

 2.根据第一步的结构,创建节点;

 3.对节点权值升序排序;

 4.取出权值最小的两个节点,生成一个新的父节点;

 5.删除权值最小的两个节点,将父节点存放到列表中;

 6.重复第四五步,直到剩下一个节点;

 7.将最后的一个节点赋给根节点。

代码实现

首先需要有个节点类来存放数据。

package huffman;
/**
 * 节点类
 * @author yuxiu
 *
 */
public class Node {
 public String code;// 节点的哈夫曼编码
 public int codeSize;// 节点哈夫曼编码的长度
 public String data;// 节点的数据
 public int count;// 节点的权值
 public Node lChild;
 public Node rChild;

 public Node() {
 }

 public Node(String data, int count) {
  this.data = data;
  this.count = count;
 }

 public Node(int count, Node lChild, Node rChild) {
  this.count = count;
  this.lChild = lChild;
  this.rChild = rChild;
 }

 public Node(String data, int count, Node lChild, Node rChild) {
  this.data = data;
  this.count = count;
  this.lChild = lChild;
  this.rChild = rChild;
 }
}

构造过程

package huffman;

import java.io.*;
import java.util.*;

public class Huffman {
 private String str;// 最初用于压缩的字符串
 private String newStr = "";// 哈夫曼编码连接成的字符串 
 private Node root;// 哈夫曼二叉树的根节点
 private boolean flag;// 最新的字符是否已经存在的标签
 private ArrayList<String> charList;// 存储不同字符的队列 相同字符存在同一位置
 private ArrayList<Node> NodeList;// 存储节点的队列

  15  16  /**
  * 构建哈夫曼树
  * 
  * @param str
  */
 public void creatHfmTree(String str) {
  this.str = str;
  charList = new ArrayList<String>();
  NodeList = new ArrayList<Node>();
  // 1.统计字符串中字符以及字符的出现次数
  // 基本思想是将一段无序的字符串如ababccdebed放到charList里,分别为aa,bbb,cc,dd,ee
  // 并且列表中字符串的长度就是对应的权值
  for (int i = 0; i < str.length(); i++) {
   char ch = str.charAt(i); // 从给定的字符串中取出字符
   flag = true;
   for (int j = 0; j < charList.size(); j++) {
    if (charList.get(j).charAt(0) == ch) {// 如果找到了同一字符
     String s = charList.get(j) + ch;
     charList.set(j, s);
     flag = false;
     break;
    }
   }
   if (flag) {
    charList.add(charList.size(), ch + "");
   }
  }
  // 2.根据第一步的结构,创建节点
  for (int i = 0; i < charList.size(); i++) {
   String data = charList.get(i).charAt(0) + ""; // 获取charList中每段字符串的首个字符
   int count = charList.get(i).length(); // 列表中字符串的长度就是对应的权值
   Node node = new Node(data, count); // 创建节点对象
   NodeList.add(i, node); // 加入到节点队列
  }

  // 3.对节点权值升序排序
  Sort(NodeList);
  while (NodeList.size() > 1) {// 当节点数目大于一时
   // 4.取出权值最小的两个节点,生成一个新的父节点
   // 5.删除权值最小的两个节点,将父节点存放到列表中
   Node left = NodeList.remove(0);
   Node right = NodeList.remove(0);
   int parentWeight = left.count + right.count;// 父节点权值等于子节点权值之和
   Node parent = new Node(parentWeight, left, right);
   NodeList.add(0, parent); // 将父节点置于首位

  }
  // 6.重复第四五步,就是那个while循环
  // 7.将最后的一个节点赋给根节点
  root = NodeList.get(0);
 }
 /**
  * 升序排序
  * 
  * @param nodelist
  */
 public void Sort(ArrayList<Node> nodelist) {
  for (int i = 0; i < nodelist.size() - 1; i++) {
   for (int j = i + 1; j < nodelist.size(); j++) {
    Node temp;
    if (nodelist.get(i).count > nodelist.get(j).count) {
     temp = nodelist.get(i);
     nodelist.set(i, nodelist.get(j));
     nodelist.set(j, temp);
    }

   }
  }

 }

 /**
  * 遍历
  * 
  * @param node
  *   节点
  */
 public void output(Node node) {
  if (node.lChild != null) {
   output(node.lChild);
  }
  System.out.print(node.count + " "); // 中序遍历
  if (node.rChild != null) {
   output(node.rChild);
  }
 }

 public void output() {
  output(root);
 }
/**
  * 主方法
  * 
  * @param args
  */
 public static void main(String[] args) {
  Huffman huff = new Huffman();//创建哈弗曼对象
  huff.creatHfmTree("sdfassvvdfgsfdfsdfs");//构造树
 }
数据结构&&哈弗曼树和哈弗曼编码 哈弗曼树和哈弗曼编码 阅读详情

相关推荐

哈弗曼树及其构造

树和哈夫曼编码。哈夫曼编码是哈夫曼树的一个应用。哈夫曼编码应用广泛,如 JPEG中就应用了哈夫曼编码。 首先介绍什么是哈夫曼树。哈夫曼树又称最优二叉树, 是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点 的权值乘上其到根结点的 路径长度(若根结点为0层,叶结点到根结点的路径长度 为叶结点的层数)。树的带权路径长度记为WPL= (W1*L1+W2*L

maowenge的专栏 1187

哈夫曼树

哈夫曼树概念哈夫曼(Huffman)树又称最优二叉树。它是n个带权叶子结点构成的二叉树中,带权路径长度WPL最小的二叉树。因为构造这种树的算法是最早由哈夫曼于1952年提出的,所以被称之为哈夫曼树。二叉树的性质二叉树中有五点性质非常重要,需要记住。 性质1:在二叉树的第 i 层上至多有2^(i-1)个结点 性质2:深度为k的二叉树至多有2^k-1个结点 性质3:对任何一颗二叉树T,如果其终端结

知之可否 9268

Teams会议翻译对比测试:Copilot同传 vs 人工翻译,结果出乎意料

本文通过对比测试Microsoft 365 Copilot的实时翻译与专业人工翻译在Teams会议中的表现,揭示了AI同传技术在准确率、响应速度和多语言切换方面的优势与局限。实验数据显示,Copilot在常规商务场景下接近人工翻译水平,且成本效益显著,但在专业术语和文化特定表达上仍需人工辅助。

weixin_29054195的博客 224

有关哈夫曼树的基础知识和应用

(1):指从一个结点到另一个结点之间的分支序列。(2):指从一个结点到另一个结点所经过的分支数目。(3):给树的每个结点赋予一个具有某种实际意义的实数,我们称该实数为这个结点的权。(4):在树形结构中,我们把从树根到某一结点的路径长度与该结点的权的乘积,叫做该结点的带权路径长度。(5):树中所有的带权路径长度之和,通常记为:其中n为叶子结点的个数,为第i个叶子结点的权值,为第i个叶子结点的路径长度。

qq_63959489的博客 993

Bochs源码分析 - 26:8259中断控制器介绍

前言 现在我们跟着《x86/x64体系探索及编程》来分析17章内容 -- 8259中断控制器。这个是涉及硬件的,很遗憾,除了大学期间使用STM32搞过一个计算器,其余就没多少硬件编程经验,我在淘宝上找了下大概是这个东东。 https://pdos.csail.mit.edu/6.828/2010/readings/hardware/8259A.pdf 上面是8259A的芯片手册,里面讲的还是挺详细的,虽然里面很多东西还是看不太懂,但是结合着《x86/...

WriteAnything_的博客 967

保姆级教程:用ROS2 Humble + Gazebo Classic 从零搭建一个能键盘控制的差分AGV模型

本文提供了一份详细的ROS2 Humble与Gazebo Classic教程,指导用户从零开始搭建一个键盘控制的差分AGV模型。内容涵盖环境配置、Xacro文件设计、Gazebo仿真集成以及键盘控制实现,特别针对常见问题提供解决方案,帮助开发者快速掌握ROS2机器人仿真技术。

weixin_30387423的博客 168

已知哈夫曼树总顶点数求叶子结点数

题目: 已知一棵哈夫曼树有13个顶点,求其叶子结点的个数。 分析: 首先,哈夫曼树是一个二叉树;第二点,哈弗曼树的度只有两种情况,一是只有两个度的结点,二是没有度的结点,即叶子结点。明确这两点之后,做该题就非常简单了。 解题: 设分支结点个数为a, 叶子结点个数为b,则有以下连个关系式: a + b = 13 2*a + 1 = 13 根据以上两个式子可以求得: b =...

fu_jian_ping的博客 2万+

【Lammps】MS将cif通过msi2lmp.exe转为data文件

在Materials Studio中打开cif文件,在Modules工具行选择Forcite>calculation>Energy中选用cvff力场,点击more,不要运行run,在more中取消勾选calculate automatically,点击calculate,然后叉掉后在file>export导出car文件,同步生成了mdf文件。对于MS中没有的立场,选择之后点calculate会报错,右键选择label,然后根据Forcite选择原子,会发现有力场的有标号,没有力场的MS没有对选择标号。

zhangguoliang624的博客 3673

关于若哈夫曼树的叶子结点数为N,则总结点数为2N-1的推导

2.关于边的总数,由于哈夫曼树只有度为2的结点和度为0的结点(即叶子结点),一个度为2的结点有两条边(分别连着左孩子和右孩子),一个度为0的结点(即叶子结点)没有边(因为其没有孩子),即:E=2I。3.关于边与总结点数的关系,这里可看作所有除了根结点的结点都有一条与其父结点相连的边。4.将T=N+I 与 E=2I 代入 E=T-1。5.将I=N-1代入T=N+I 得:T=N+N-1=2N-1。叶子结点数N,非叶子结点数I,结点总数T,边的总数E。得:2I=N+I-1。

m0_63887447的博客 1174

esp32 python开发环境搭建_eclipse esp32开发环境搭建

安装方法基本是按照官网提供的方法来操作https://github.com/espressif/idf-eclipse-plugin#GettingStarted但是官网的方法安装之后还是不能编译成功的,第一次编译会出现一下问题问题1:Building in: E:\eclipse-workspace\helloworlk\buildcmake -G Ninja -DCMAKE_TOOLCHAIN...

weixin_39978276的博客 1262

爆肝整理:微信公众号文章HTML编写完整规范,运营必备手册

微信公众号文章排版总是出错?📱 这份完整的HTML编写规范文档帮你彻底解决!文档包含所有支持的标签、CSS属性、实用代码模板和注意事项 📋,让你快速掌握微信文章的HTML编写技巧,告别第三方编辑器依赖 ✅

XiaoqiangClub的博客 2303

数据结构之哈夫曼树的基本知识

前面讲到了线索二叉树的基础知识后,今天我们紧随其后来说说另一种特殊二叉树---哈夫曼树.这几种特殊二叉树可能理解起来有点难度,没关系,我只能说慢慢理解,隔一段时间拿出来理解理解,说不定自己随着学的东西越来越多,理解起来就会越来越容易.好啦,直入正题,给大家分享一下哈夫曼树的基础知识吧 1.学习哈夫曼树必懂的几个术语: 在一棵树中,从一个结点往下可以达到的结点之间的通路,称为路径。 某一路径所经过的“边”的数量,称为该路径的路径长度 若将树中结点赋给一个带有某种含义的数值,则该数值称为该结点的权。

m0_63932570的博客 2221

SAP_ABAP_SD_BAPI清单案例教程——销售订单开票_BAPI_BILLINGDOC_CREATEMULTIPLE_VF01_S4版本

SAP BAPI(Business Application Programming Interface)是SAP系统中的一组规范和标准,用于从SAP系统中获取数据、输入数据和更新数据。这些API允许开发者以编程方式与SAP系统交互,而无需编写大量的自定义代码。2.1 Copy代码 直接可使用。2.2 VF01开票。

java_zhong1990的专栏 2214

画哈弗曼树

哈弗曼树又称最优二叉树,是一类带权路径长度最短的树,其画法如下:

weixin_44300286的博客 1万+

OFDM调制解调系统信道估计和均衡算法的MATLAB仿真

然后,从接收到的信号中提取导频序列,并使用LS算法进行信道估计。OFDM(正交频分复用)是一种常用于高速数据传输的调制技术,它将高速数据流分割成多个低速子载波,通过在不同的子载波上传输数据,实现了频域上的正交性。因此,信道估计和均衡算法在OFDM系统中起着至关重要的作用,用于减小信道衰落引起的影响。通过运行上述代码,可以进行基于LS算法的OFDM调制解调系统信道估计和均衡的MATLAB仿真。本文将介绍一种基于LS(最小二乘)算法的OFDM调制解调系统信道估计和均衡算法,并提供相应的MATLAB仿真代码。

uote_e的博客 229

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

哈弗曼树与哈弗曼编码

哈弗曼,一个在几乎所有讲数据结构的书中都有出现过的人物,他的鼎鼎大名想必就不用我多说了。这一次来给大家讲解一下哈弗曼树的构建与哈弗曼编码的基本原理,有什么用呢?别急,还是先学会创建一棵哈弗曼树吧。 哈弗曼树又称最优二叉树,最优二叉树就是带权路径长度WPL最小的二叉树,那么我们就得搞清几个概念: 1. 路径长度:从树中的一个结点到另一个结点之间的分支构成这两个结点的路径,路径上...

abc6772的博客 413

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

C++ 哈弗曼树类 创建哈弗曼树、输出哈弗曼树、输出哈弗曼编码

#include <stdlib.h> #include <iostream> int *findMin(struct TreeNode *trees,int length); using namespace std; struct huffmanCode{ int *p; int start; }; struct TreeNode{ int wight; int...

一个懒惰的程序员 512

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

C 实现哈弗曼树

构造哈弗曼树: 假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为: (1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点); (2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,...

chijiankao3210的博客 176

快速掌握哈弗曼树

哈弗曼树的基本定义 哈弗曼树又称最优数,是一类带权路径长最短的树。 看看里面涉及的概念: (1)路径:从树的一个节点到另一个节点之间的分支构成了这两个节点之间的路径 (2)路径长度:路径上的分支数目 (3)树的路径长度:从树根到每一个节点的路径长度之和 (4)权:这个在数学上有相似的定义,可以相似的理解 (5)节点的带权路径长度:树中所有带权路径长度之和 (6)哈弗曼树:假设有n个叶子节点的二叉树...

weixin_43978453的博客 363

哈弗曼树与哈弗曼编码(实现)

哈弗曼树与哈弗曼编码 历史背景 1951年,霍夫曼在MIT攻读博士学位,他和修读信息论课程的同学得选择是完成学期报告还是期末考试。导师Robert Fano出的学期报告题目是:查找最有效的二进制编码。由于无法证明哪个已有编码是最有效的,霍夫曼放弃对已有编码的研究,转向新的探索,最终发现了基于有序频率二叉树编码的想法,并很快证明了这个方法是最有效的。使用自底向上的方法构建二叉树避免了次优算法香农-范...

= = 855

哈弗曼树 C语言

#include #include #include #define N 4 //带权值的叶子节点个数或者是需要编码的字符数 #define M 2*N-1//n个叶子节点构造的哈弗曼树有2n-1个结点(因为该树只有叶子和度为2的结点) #define MAX 10000 typedef struct {     unsigned int weight; //权值只

sinat_40432951的博客 634

关于哈弗曼树的问题

<br />因为要考试了,所以我的编程也要放放了,不过每天还要多少看点,这连着今天搞的哈弗曼树今天终于能用代码实现了,不过又是参考别人的代码,然后自己写的,不是自己的,不过自己已经理解是怎么回事了,首先,还是说说我对哈弗曼树的一些看法吧:<br />哈弗曼树我现在所会的只是建立和编码,至于解码,到现在为止不会,不过,我还是想分享一下我自己对这两面的理解,首先,对于树的建立,要涉及到选取结点的问题,一,选择两个未选的两个权值最小的结点,这个涉及到一个函数的问题,至于,怎么来写,我想还是自己仔细想想,这个并不难

笨牛dashan的专栏 334

[数据结构]哈弗曼树

[数据结构]哈弗曼树 哈夫曼树应用实例——哈夫曼编码 关键:要设计长度不等的编码,则必须使任一字节的编码都不是另一字符的编码的前缀–前缀编码。 译码过程: 分解接收字符串,遇“0”向左,遇“1”向右,一旦达到叶子结点,则译出一个字符,反复由根出发,直到译码完成。 特点:每一码都不是另一码的前缀,绝不会译错。 哈弗曼树的构造 哈弗曼树:带权路径长度最小的树。 相关术语: 路径:由一结点到另一结点间的...

weixin_45326969的博客 397

哈弗曼树总结

哈弗曼树总结介绍

小码农想做大架构的博客 999
上一篇: 索引失效和注意事项
下一篇: spring boot 基础问题
ka_ko
博客等级 码龄11年 168粉丝 94原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值