【数据结构(十·树结构的实际应用)】赫夫曼树(2)

2023-12-10 17:28

本文主要是介绍【数据结构(十·树结构的实际应用)】赫夫曼树(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1. 基本介绍
  • 2. 赫夫曼树的创建
    • 2.1. 思路分析
    • 2.2. 代码实现


1. 基本介绍

  1. 给定 n 个权值作为 n 个叶子结点,构造一棵二叉树,若该树的 带权路径长度(wpl) 达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree), 还有的书翻译为霍(赫)夫曼树
  2. 赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

几个重要的概念:
    ① 路径路径长度:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为 1,则从根结点到第 L 层结点的路径长度为 L-1。
    ② 结点的权带权路径长度:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
    ③ 树的带权路径长度:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为 WPL(weighted path length) ,权值越大的结点离根结点越近的二叉树才是最优二叉树。

WPL 最小的就是赫夫曼树
    在这里插入图片描述

2. 赫夫曼树的创建

问题:
    给一个数列 {13, 7, 8, 3, 29, 6, 1},要求转成一颗赫夫曼树.

2.1. 思路分析

    ① 从小到大进行排序, 将每一个数据,每个数据都是一个节点 , 每个节点可以看成是一颗最简单的二叉树
    ② 取出根节点权值最小的两颗二叉树
    ③ 组成一颗新的二叉树, 该新的二叉树的根节点的权值是前面两颗二叉树根节点权值的和
    ④ 再将这颗新的二叉树,以根节点的权值大小 再次排序, 不断重复 1-2-3-4 的步骤,直到数列中,所有的数据都被处理,就得到一颗赫夫曼树

图解:

① 从小到大进行排序{1, 3, 6, 7, 8, 13, 29}, 将每一个数据,每个数据都是一个节点 , 每个节点可以看成是一颗最简单的二叉树
在这里插入图片描述

② 取出根节点权值最小的两颗二叉树,即1和3
在这里插入图片描述

③ 组成一颗新的二叉树, 该新的二叉树的根节点的权值是前面两颗二叉树根节点权值的和(1+3=4)

在这里插入图片描述

④ 再将上面这颗新的二叉树,以根节点的权值大小 再次排序:取出上面 以根节点为4和6的二叉树,重复③步骤

在这里插入图片描述

⑤ 不断重复上述操作,直到数列中,所有的数据都被处理,就得到一颗赫夫曼树
    (1)重复第一次

在这里插入图片描述

    (2)重复第二次

在这里插入图片描述

    (3)重复第三次

在这里插入图片描述

    (4)重复第四次(完成)

在这里插入图片描述

2.2. 代码实现

package huffmantree;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public class HuffmanTree {public static void main(String[] args) {// TODO Auto-generated method stubint arr[] = { 13, 7, 8, 3, 29, 6, 1 };Node root = createHuffmanTree(arr);// 测试preOrder(root);//}// 编写一个前序遍历的方法public static void preOrder(Node root) {if (root != null) {root.preOrder();} else {System.out.println("是空树,不能遍历~");}}// 创建赫夫曼树方法/*** * @param arr 需要创建成赫夫曼树的数组* @return 创建好后的赫夫曼树的root节点*/public static Node createHuffmanTree(int[] arr) {// 第一步:为了操作方便// 1. 遍历arr数组// 2. 将arr的每个元素构成一个Node// 3. 将Node放入到ArrayList中List<Node> nodes = new ArrayList<>();for (int value : arr) {nodes.add(new Node(value));}// 处理的过程是一个循环的过程while (nodes.size() > 1) {// 排序:从小到大Collections.sort(nodes);System.out.println("nodes = " + nodes);// 取出根节点权值最小的两个二叉树// 1. 取出权值最小的节点(二叉树)Node leftNode = nodes.get(0);// 2. 取出第二小的节点(二叉树)Node rightNode = nodes.get(1);// 3. 构建一个新的二叉树Node parent = new Node(leftNode.value + rightNode.value);parent.left = leftNode;parent.right = rightNode;// 4. 从ArrayList删除处理过的二叉树nodes.remove(leftNode);nodes.remove(rightNode);// 5. 将parent加入到nodesnodes.add(parent);}// 返回赫夫曼树的root节点return nodes.get(0);}}//创建节点类
//为了让Node对象持续排序Collections集合排序
//让Node实现Comparable接口
class Node implements Comparable<Node> {int value;// 节点权值Node left;// 指向左节点Node right;// 指向右节点// 写一个前序遍历public void preOrder() {System.out.println(this);if (this.left != null) {this.left.preOrder();}if (this.right != null) {this.right.preOrder();}}public Node(int value) {this.value = value;}@Overridepublic String toString() {return "Node [value=" + value + "]";}@Overridepublic int compareTo(Node o) {// TODO Auto-generated method stub// 表示从小到大排序return this.value - o.value;}}

运行结果:

在这里插入图片描述

这篇关于【数据结构(十·树结构的实际应用)】赫夫曼树(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/477793

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

zoj3820(树的直径的应用)

题意:在一颗树上找两个点,使得所有点到选择与其更近的一个点的距离的最大值最小。 思路:如果是选择一个点的话,那么点就是直径的中点。现在考虑两个点的情况,先求树的直径,再把直径最中间的边去掉,再求剩下的两个子树中直径的中点。 代码如下: #include <stdio.h>#include <string.h>#include <algorithm>#include <map>#

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

AI行业应用(不定期更新)

ChatPDF 可以让你上传一个 PDF 文件,然后针对这个 PDF 进行小结和提问。你可以把各种各样你要研究的分析报告交给它,快速获取到想要知道的信息。https://www.chatpdf.com/

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。