《数据结构》学习系列——树(下)

系列文章目录

目录

  • 树和森林的遍历
    • 树的遍历
    • 森林的遍历
    • 基本算法
      • 递归先根遍历树
      • 迭代先根遍历树
      • 树和森林的层次遍历
  • 压缩与哈夫曼树
    • 文件编码
    • 扩充二叉树
      • 哈夫曼树和哈夫曼编码
        • 哈夫曼树的基本思路
        • 哈夫曼编码


树和森林的遍历

树的遍历

  • 先根遍历:先访问树的根结点,然后依次先根遍历每颗子树
  • 后根遍历:先依次后根遍历每颗子树,然后访问树的根结点

在这里插入图片描述在这里插入图片描述

森林的遍历

  • 先根遍历森林:
    • 访问森林中第一棵树的根节点
    • 先根遍历第一棵树中的诸子树
    • 先根遍历其余的诸树(森林)

森林的先根遍历与其对应的二叉树先根遍历相同
在这里插入图片描述

  • 后根遍历森林:
    • 后根遍历第一棵树的诸子树
    • 访问森林中第一棵树的根节点
    • 后根遍历其余诸树(森林)

森林的后根遍历序列与其对应的二叉树的中根遍历序列一致
在这里插入图片描述

基本算法

递归先根遍历树

PreOrder(t)
{if t == NULL return;print(Data(t));GFC(t,child); // 找到t的第一个子节点while chile != NULL{PreOrder(child);GNB(child,child);}
}

迭代先根遍历树

思路
(1)若结点p不为空,访问结点p,将结点p压入栈,并将其大儿子结点设为结点p;反复执行(1),直至结点p为空
(2)从栈中弹出一个结点,将其设为结点p,若它有大兄弟结点,则将其大兄弟结点压入栈,且将该兄弟结点设为结点p;否则,反复执行(2),直
至弹出的结点有大兄弟结点或栈空以至无结点可弹出
(3)反复执行(1)和(2),直至栈为空

伪代码

NPO(t)
{create(s);p = t;bool flag = True;while flag or S非空{flag = False;while p != NULL;{print(Data(p));Push(S,p);p = FierstChlid(p)}while p != NULL and S 非空;Pop(S,p);p = NextBrother}
}

在这里插入图片描述

树和森林的层次遍历

LevelOrder(t)
{CREATE(Q);Q = t;	// 根节点入队列while not IsEmpty(Q){p = Q;while p != NULL{print(Data(p));if FirstChild(p) != NULL  Q = FirstChild(p);p = NextBrother(p);}}
}

压缩与哈夫曼树

文件编码

  • 假设有一个文件仅包含7种字符:a、e、i、s、t、sp(空格)和nl(换行),且文件中有10个a,15个e,12个i,3个s,4个t,13个sp,1个nl

  • 因为「 log ⁡ 2 7 \log_27 log27]=3,所以,每个字符都至少由一个3位的二进制串表示。于是文件的总位数至少应该是:10×3+15×3+12×3+3×3+4×3+13×3+1×3=174

  • 在实际应用的一些大文件中,字符被使用的比率是非平均的,即有些字符出现的次数较多,而有些字符出现的次数却非常少。
    如果所有字符都由等长的二进制码表示,将会造成空间浪费

  • 如何才能减少不必要的空间浪费

  • 文件压缩的通常策略:采用不等长的二进制码,令文件中出现频率高的字符的编码尽可能短

    • 采用不等长编码又可能会产生多义性。例如:如果用01表示a,10表示b,1001表示c,那么对于编码1001,我们无法确定它表示字符c,还是表示字符串ba,其原因是b的编码与c的编码的开头(前缀)部分相同
    • 为避免出现多义性,必须要求字符集中任何字符的编码都不是其它字符的编码的前缀,满足这个条件的编码被称为前缀码。显然,等长编码是前缀码
  • 怎样的前缀码才能使文件的总编码长度最短

    • 设组成文件的字符集A={a1,a2,…,an},其中,a的编码长度为 I i I_i Ii;a出现的次数为 c i c_i ci。要使文件的总编码最短,就必须要确定 I i I_i Ii,使得取最小值
      ∑ i = 0 n c i I i \sum_{i=0}^nc_iI_i i=0nciIi
  • 如何设计出总编码最短的前缀码

    • 哈夫曼算法

扩充二叉树

定义
为了使问题的处理更为方便,每当原二叉树中出现空子树时,就增加特殊的结点——空树叶,由此生成的二叉树称为扩充二叉树

  • 扩充二叉树中每个圆形结点都有两个子结点,每一个方形结点都没有子结点
  • 规定空二叉树的扩充二叉树为只有一个方形结点。以下称圆形结点为内结点,方形结点为外结点0

在这里插入图片描述

  • 扩充二叉数的外通路长度定义为从根到每个外结点的路径长度之和,内通路长度定义为从根到每个结点的路径长度之和

在这里插入图片描述

  • 给扩充二叉树的n个外结点分别赋上一个实数权。扩充二叉树的加权外通路长度定义为:
    W P L = ∑ i = 0 n w i L i WPL = \sum_{i=0}^nw_iL_i WPL=i=0nwiLi
    其中n表示外结点的个数, w i w_i wi L i L_i Li分别表示外结点 k i k_i ki的权值和根到 k i k_i ki的路径长度

  • 在外结点权值分别为 w 0 , w 1 , . . . , w n − 1 w_0,w_1, ... ,w_{n-1} w0,w1,...,wn1的所有扩充二叉树中,加权外通路长度最小的扩充二叉树称为最优二叉树‘

哈夫曼树和哈夫曼编码

  • 文件编码问题就变成构造最优二叉树问题,每个外结点代表一个字符,其权值代表该字符的频率,从根到外结点的路径长度就是该字符的编码长度
  • 为求得最优二叉树,哈夫曼巧妙的设计了哈夫曼算法,通过哈夫曼算法可以建立一棵哈夫曼树,从而为压缩文本文件建立了哈夫曼编码
哈夫曼树的基本思路
  1. 根据给定的n个权值 w 1 w_1 w1, w 2 w_2 w2,…, w n w_n wn构成n棵二叉树的森林F={ T 1 , T 2 , … , T n T_1,T_2,…,T_n T1,T2,,Tn},其中每棵二叉树 T i T_i Ti中都只有一个权值为 w i w_i wi的根结点,其左、右子树均为空
  2. 在森林F中选出两棵根结点权值最小的树作为一棵新树的左、右子树,且置新树的根结点的权值为其左、右子树上根结点的权值之和
  3. 从F中删除构成新树的那两棵树,同时把新树加入F中
  4. 重复第2和第3步,直到F中只含有一棵树为止,此树便是哈夫曼树

例子
在这里插入图片描述

哈夫曼编码

将哈夫曼树每个分支结点的左分支标上0,右分支标上1,把从根结点到每个叶结点的路径上的标号连接起来,作为该叶结点所代表字符的编码,这样得到的编码称为哈夫曼编码

  • 定理:在外结点权值分别为 w 0 , w 1 , … , w n − 1 w_0,w_1,…,w_{n-1} w0,w1,,wn1的扩充二叉树中,由哈夫曼算法构造出的哈夫曼树的带权路径长度最小,因此哈夫曼为最优二叉树
  • 根据该定理可知,对于所有的编码,哈夫曼编码使文件的总编码长度最短。实际上,哈夫曼算法的应用广,这里只是以哈夫曼编码为例来说明哈夫曼算法。由观察可知,字符集中的字符所在的结点均是哈夫曼树中的外结点
  • 哈夫曼树中没有度为1的结点

示例
在这里插入图片描述
在构造哈夫曼树的过程中,没有一片树叶是其他树叶的祖先,所以每个叶结点对应的编码不可能是其他叶结点对应的编码前缀。由此可知哈夫曼编码是二进制的前缀码

哈夫曼树中每个结点的结构
在这里插入图片描述
其中,LLINK和RLINK为链接域,INFO为信息域,Weight为全值

伪代码

Huffman(H,m,t)
{for (i = 1; i<=m;i++){LLINK(H[i]) = RLINK(H[i]);RLINK(H[i]) = NULL;}for (i = 1,i<m;i++){t = new;P1 = H[i];P2 = H[i+1];Weight(t) = Weight(P1) + Weight(P2);LLINK(t) = P1;RLINK(t) = P2;}j = i+2;while (Weight(t)>Weight(H[j])){H[j-1] = H[j];j = j+1;H[j-1] = t;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

想作弊❓用这个发起考试,根本没法作弊

&#x1f389; 推荐一款超实用的在线考试神器 —— 土著刷题✨ 如果你正在寻找一个既方便又高效的在线考试平台&#xff0c;那么“土著刷题”小&#x1f34a;序绝对值得一试&#xff01;它不仅完全免费&#xff0c;而且操作简单&#xff0c;非常适合用来组织线上测试。 &#x…

使用Angular构建动态Web应用

&#x1f496; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4bb; Gitee主页&#xff1a;瑕疵的gitee主页 &#x1f680; 文章专栏&#xff1a;《热点资讯》 使用Angular构建动态Web应用 1 引言 2 Angular简介 3 安装Angular 4 创建Angular项目 5 设计应用结构 6 创建组件 7 …

「Java SPI机制应用快速入门」: 一种JDK内置的服务提供发现机制

文章目录 什么是SPISPI机制的应用使用方法使用规范 入门案例 什么是SPI SPI首先是一种机制&#xff0c;这个机制叫&#xff1a;服务提供发现机制。那是谁来负责发现呢&#xff1f;当然是JDK内置的服务帮助我们发现啦。发现了帮助我们去调用&#xff0c;我们要做的就是在中间去…

2024护理类科技核心期刊汇总(最新版)

2024年9月中国科技核心期刊目录&#xff08;2024年版&#xff09;正式公布&#xff0c;13本护理类期刊入选。常笑医学整理了这13本护理类科技核心期刊的详细参数&#xff0c;以及投稿经验&#xff0c;供大家在论文投稿时参考&#xff0c;有需要的赶紧收藏&#xff01; 1.《中华…

SwiftUI(四)- 布局(VStack、HStack、ZStack)

引言 页面的搭建和布局在应用开发中几乎占据了一半的代码量。定于iOS开发而言&#xff0c;相较于其它平台&#xff0c;UIKit的布局方式显得相对局限&#xff0c;通常只有绝对布局和相对布局两种方案。而在Flutter或者Android开发中&#xff0c;布局选项更为丰富&#xff0c;比…

【mod分享】极品飞车9冬日mod,支持光追,想体验一把冬天的Rockport市吗

各位好&#xff0c;今天小编给大家带来一款新的高清重置魔改MOD&#xff0c;本次高清重置的游戏叫《极品飞车9最高通缉》。 《极品飞车&#xff1a;最高通缉》作为一款2005年的游戏&#xff0c;《极品飞车&#xff1a;最高通缉》的画面效果还是可以的&#xff0c;效果全开之后…

【状态机DP】力扣1186. 删除一次得到子数组最大和

给你一个整数数组&#xff0c;返回它的某个 非空 子数组&#xff08;连续元素&#xff09;在执行一次可选的删除操作后&#xff0c;所能得到的最大元素总和。换句话说&#xff0c;你可以从原数组中选出一个子数组&#xff0c;并可以决定要不要从中删除一个元素&#xff08;只能…

手机拍证件照,换正装有领衣服及底色的方法

证件照在我们的职业生涯的关键节点是经常会用到的&#xff0c;比如毕业入职、人事档案建立、升迁履历、执业资格考试和领证等&#xff0c;这些重要的证件照往往要求使用正装照&#xff0c;有时候手头没有合适的衣服&#xff0c;或者原先的证件照背景色不符合要求&#xff0c;就…

numpy——数学运算

一、标量——矢量 import numpy as npa 3.14 b np.array([[9, 5], [2, 7]])print(a) print(b)# ---------- 四则运算 ---------- print(a b) # np.add print(a - b) # np.subtract print(a * b) # np.multiply print(a / b) # np.divide 二、矢量——矢量 import nump…

优选算法精品课--双指针算法(2)

双指针算法&#xff08;2&#xff09; 1、有效三角形的个数1.1 题目解析1.2 思路解析1.3 代码实现 2、和为s的两个数2.1 题目解析2.2 思路解析2.3 代码实现 3、三数之和3.1 题目解析3.2 思路解析3.3 代码实现 4、四数之和4.1 题目解析4.2 思路解析4.3 代码实现 5 总结 1、有效三…

4个提取音频办法,轻松实现视频转音频!

在信息爆炸的时代&#xff0c;视频内容以其直观、生动的特点占据了互联网的大半江山。然而&#xff0c;在某些场景下&#xff0c;我们可能更倾向于只听取音频部分&#xff0c;无论是驾驶途中听讲座、跑步时享受音乐视频中的纯音乐的场景&#xff0c;还是为了节省流量和存储空间…

Python continue和break

continue的作用是&#xff1a; 中断所在循环的当次执行&#xff0c;直接进入下一次 break的作用是&#xff1a; 直接结束所在的循环 注意事项&#xff1a; continue和break&#xff0c;在for和while循环中作用一致 在嵌套循环中&#xff0c;只能作用在所在的循环上&#x…

【01初识】-初识 RabbitMQ

目录 学习背景1- 初识 MQ1-1 同步调用什么是同步调用&#xff1f;小结&#xff1a;同步调用优缺点 1-2 异步调用什么是异步调用&#xff1f;小结&#xff1a;异步调用的优缺点&#xff0c;什么时候使用异步调用&#xff1f; 1-3 MQ 技术选型 学习背景 异步通讯的特点&#xff…

300元蓝牙耳机性价比高的有哪些?学生平价蓝牙耳机推荐

你是否正在为选择一款性价比高的蓝牙耳机而烦恼&#xff1f;是否希望找到一款既适合学生使用&#xff0c;又能在预算内满足需求的蓝牙耳机&#xff1f;300元蓝牙耳机性价比高的有哪些&#xff1f;如果你有这样的需求&#xff0c;那么下面我将为大家提供一些有益的参考&#xff…

中间件安全(三)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 前言: 本文主要讲解apache命令执行漏洞&#xff08;cve_2021_41773&#xff09;。 靶场链接&#xff1a;Vulfocus 漏洞威胁分析平台 一&#xff0c;漏洞简介。 cve_2021_41773漏洞…

【STM32外设及其应用】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

pyvideotrans 最佳AI翻译软件

文章目录 体验视频翻译配音工具主要用途和功能预打包版本(仅win10/win11可用&#xff0c;MacOS/Linux系统使用源码部署)MacOS源码部署Linux 源码部署Window10/11 源码部署源码部署问题说明使用教程和文档语音识别模型:视频教程(第三方)软件预览截图相关联项目致谢 体验 不错&a…

【含开题报告+文档+PPT+源码】基于SpringBoot的健康知识学习分享平台的设计与实现

开题报告 随着人们生活水平的提高和健康意识的增强&#xff0c;健康知识在日常生活中的重要性日益凸显。传统的健康知识获取途径如书籍、讲座等虽然具有一定的效果&#xff0c;但存在信息更新慢、交互性差等局限性。同时&#xff0c;互联网的普及和移动互联网的发展为人们提供…

【算法刷题指南】双指针

&#x1f308;个人主页&#xff1a; 南桥几晴秋 &#x1f308;C专栏&#xff1a; 南桥谈C &#x1f308;C语言专栏&#xff1a; C语言学习系列 &#x1f308;Linux学习专栏&#xff1a; 南桥谈Linux &#x1f308;数据结构学习专栏&#xff1a; 数据结构杂谈 &#x1f308;数据…

前端零基础入门到上班:【Day1】什么是前端?

本来打算开付费专栏 但是想起那句话 赠人玫瑰手留余香 引言1. 什么是前端&#xff1f;1.1 前端的定义1.2 前端的三大核心技术1.3 前端框架和工具 2. 什么是后端&#xff1f;2.1 后端的定义2.2 后端的组成要素2.3 后端框架和工具 3. 前后端的区别4. 什么是前后端分离&#xff1f…