数据结构--》解锁数据结构中树与二叉树的奥秘(二)

        数据结构中的树与二叉树,是在建立非线性数据结构方面极为重要的两个概念。它们不仅能够模拟出生活中各种实际问题的复杂关系,还常被用于实现搜索、排序、查找等算法,甚至成为一些大型软件和系统中的基础设施。

        无论你是初学者还是进阶者,本文将为你提供简单易懂、实用可行的知识点,帮助你更好地掌握树和二叉树在数据结构和算法中的重要性,进而提升算法解题的能力。接下来让我们开启数据结构与算法的奇妙之旅吧。

目录

二叉树的线索化

堆的定义及其建立

树与森林

霍(哈)夫曼树


二叉树的线索化

线索化二叉树(Threaded Binary Tree)是一种对二叉树进行改造的方法,使得二叉树的遍历更加高效。在线索化二叉树中,除了存储左右子节点的指针外,还存储了一些额外的线索信息,用于快速定位前驱和后继节点。

中序线索化二叉树:将二叉树的空指针域利用起来,指向该节点的中序遍历的前驱节点和后继节点。

中序线索二叉树的存储:

先序线索化二叉树:将二叉树的空指针域利用起来,指向该节点的中序遍历的前驱节点和后继节点。 

先序线索二叉树的存储: 

后序线索化二叉树:将二叉树的空指针域利用起来,指向该节点的中序遍历的前驱节点和后继节点。  

先序线索二叉树的存储: 

下面是使用C语言实现先序、中序、后续线索化的代码示例:

#include <stdio.h>
#include <stdlib.h>// 定义二叉树节点结构
typedef struct Node {int data;struct Node* left;struct Node* right;int isThreaded; // 标志位,用于线索化
} Node;// 创建新节点
Node* createNode(int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->left = NULL;newNode->right = NULL;newNode->isThreaded = 0;return newNode;
}// 先序线索化
void preorderThreading(Node* root, Node** prev) {if (root == NULL) {return;}if (*prev != NULL && (*prev)->right == NULL) {(*prev)->right = root;  // 将前驱节点的右指针指向当前节点(*prev)->isThreaded = 1; // 将前驱节点的线索标志位置为1}if (root->left == NULL) {root->left = *prev;  // 将当前节点的左指针指向前驱节点root->isThreaded = 1; // 将当前节点的线索标志位置为1}*prev = root;if (!root->isThreaded) {preorderThreading(root->left, prev);}preorderThreading(root->right, prev);
}// 中序线索化
void inorderThreading(Node* root, Node** prev) {if (root == NULL) {return;}inorderThreading(root->left, prev);if (*prev != NULL && (*prev)->right == NULL) {(*prev)->right = root;  // 将前驱节点的右指针指向当前节点(*prev)->isThreaded = 1; // 将前驱节点的线索标志位置为1}if (root->left == NULL) {root->left = *prev;  // 将当前节点的左指针指向前驱节点root->isThreaded = 1; // 将当前节点的线索标志位置为1}*prev = root;inorderThreading(root->right, prev);
}// 后续线索化
void postorderThreading(Node* root, Node** prev) {if (root == NULL) {return;}postorderThreading(root->left, prev);postorderThreading(root->right, prev);if (*prev != NULL && (*prev)->right == NULL) {(*prev)->right = root;  // 将前驱节点的右指针指向当前节点(*prev)->isThreaded = 1; // 将前驱节点的线索标志位置为1}if (root->left == NULL) {root->left = *prev;  // 将当前节点的左指针指向前驱节点root->isThreaded = 1; // 将当前节点的线索标志位置为1}*prev = root;
}int main() {// 创建二叉树Node* root = createNode(1);root->left = createNode(2);root->right = createNode(3);root->left->left = createNode(4);root->left->right = createNode(5);// 先序线索化Node* prev = NULL;preorderThreading(root, &prev);// 中序线索化prev = NULL;inorderThreading(root, &prev);// 后续线索化prev = NULL;postorderThreading(root, &prev);return 0;
}

回顾重点,其主要内容整理成如下内容:   

堆的定义及其建立

堆是一种特殊的完全二叉树,它具有以下两个特性: 

1)堆中任意节点的值都必须满足堆的性质:对于大根堆(或最大堆),每个节点的值都大于等于其子节点的值;对于小根堆(或最小堆),每个节点的值都小于等于其子节点的值。

2)堆中的二叉树总是完全填满的,即除了最后一层,其他层都是满的,且最后一层从左到右连续。

举个例子:

一个堆可以用一个一维数组来描述:

自顶向下建堆法:方法通过插入堆然后通过上滤方式(下与上比较,下比上大,下与上互换位置):

自下而上建堆法:方法是对每个父结点进行下滤(上与下比较,上比下大,上与下互换位置):

树与森林

树的存储表示

双亲表示法(顺序存储):用一个一维数组来存储树的所有节点,同时利用另外一个一维数组来存储每个节点的双亲节点。使用顺序存储双亲表示法时,可以方便地通过节点的下标查找其双亲节点,也可以根据节点的双亲节点编号快速查找该节点在数组中的位置。但是,插入和删除操作相对较为复杂,需要进行元素的移动,而且相比链式存储,需要额外的空间存储双亲节点编号信息。

如果想增一个数据结点,我们只需要在空白的位置写入这个结点,并且记录其与双亲结点的关系:

如果想删除一个结点可以采用以下两种方式。

方案一:删除的元素的双亲结点设为-1,表示该位置是空的

方案二:把尾部的元素填充到删除的结点上面:

如果删除的是一个父结点,需要查找其下面所有子孙节点并全部删除,如果之前采用过方案一的方式的话会导致会多遍历一个空数据从而导致遍历的速度变慢:

孩子表示法(顺序+链式存储):使用顺序存储孩子表示法时,可以通过节点的指针或索引直接访问其孩子节点,不需要遍历整个数组。对于叶子节点,可以使用特殊值(如-1)表示没有孩子节点。相比于双亲表示法,顺序存储孩子表示法节省了存储空间。

孩子兄弟表示法(链式存储): 孩子兄弟表示法适用于表示一般的树结构,而不仅限于二叉树。它节省了存储空间,并提供了一种紧凑且高效的方式来表示树。这种表示法常用于一些树的应用,如表达式树、文件系统的目录结构等。同时,由于链式结构的特性,插入和删除节点也相对较容易。

树和二叉树的相互转化:

森林与二叉树的转换

森林转换为二叉树的方式:左序列是父子关系、右序列是兄弟关系。具体转换如下:

回顾重点,其主要内容整理成如下内容:   

树和森林的遍历

树的先根遍历:

树的后根遍历:

树的层次遍历:

森林的先序遍历:

森林的中序遍历:

霍(哈)夫曼树

了解概念

结点的权:有某种现实含义的数值(如:表示结点的重要性等)

结点的带权路径长度:从树的根到该结点的路径长度(经过的边数)与该结点上权值的乘积:

举出以下的例子进行相应说明:

注意:在含有n个带权叶结点的二叉树中,其中带权路径长度(WPL)最小的二叉树称为哈夫曼树,也称最优二叉树。 因此我们可以根据这个特点对哈夫曼树进行构造:

哈夫曼编码

回顾重点,其主要内容整理成如下内容:    

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

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

相关文章

Spring Cloud--Nacos+@RefreshScope实现配置的动态更新

原文网址&#xff1a;Spring Cloud--NacosRefreshScope实现配置的动态更新_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍SpringCloud整合Nacos使用RefreshScope实现动态更新配置。 官网 Nacos Spring Cloud 快速开始 动态更新的介绍 动态更新的含义&#xff1a;修改应…

【09】基础知识:React组件的生命周期

组件从创建到死亡它会经历一些特定的阶段。 React 组件中包含一系列勾子函数&#xff08;生命周期回调函数 <> 生命周期钩子函数 <> 生命周期函数 <> 生命周期钩子&#xff09;&#xff0c;会在特定的时刻调用。 我们在定义组件时&#xff0c;会在特定的生…

挖机技术哪家强

挖机技术哪家强&#xff0c;中国山东找蓝翔&#xff0c;开挖机是我曾经的梦想&#xff0c;每个男人心中都有一台自己的挖机&#xff0c;近半年做的项目就是关于挖机销售CRM&ERP系统&#xff0c; 今天我们聊聊关于挖机的基本知识。 注&#xff1a;此文并非广告&#xff0c;…

Mybatis学习笔记注解/xml映射/动态SQL%%%Mybatis教程

介绍 Mybatis 是一款优秀的持久层框架&#xff0c;用于简化 JDBC 的开发 MyBatis中文网 Mybatis 入门 快速入门 步骤 创建 SpringBoot 工程、数据库表 user、实体类 User引入 Mybatis 相关依赖&#xff0c;配置 Mybatis&#xff08;数据库连接信息&#xff09;编写 SQL 语…

金x软件有限公司安全测试岗位面试

目录 一、自我介绍 二、你是网络空间安全专业的&#xff0c;那你介绍下网络空间安全这块主要学习的东西&#xff1f; 三、本科专业是网络工程&#xff0c;在嘉兴海视嘉安智城科技有限公司实习过&#xff0c;你能说下干的工作吗&#xff1f;&#xff08;没想到问的是本科实习…

二十四、【参考素描三大面和五大调】

文章目录 三种色面(黑白灰)五种色调 这个可以参考素描对物体受光的理解&#xff1a;素描调子的基本规律与素描三大面五大调物体的明暗规律 三种色面(黑白灰) 如下图所示&#xff0c;我们可以看到光源是从亮面所对应的方向射过来的,所以我们去分析图形的时候&#xff0c;首先要…

【算法练习Day19】二叉搜索树的最近公共祖先二叉搜索树中的插入操作删除二叉搜索树中的节点

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 二叉搜索树的最近公共祖先叉…

vue七牛云视频直传

完成后样式&#xff1a; 下面的代码是我自己项目里面用到的&#xff0c;一些判断看自己情况去掉&#xff0c;用的是element-ui组件 安装 uuid 库。你可以使用 npm 或 yarn 来完成安装。在终端中执行以下命令&#xff1a; npm install uuidhtml部分 <el-upload class&quo…

Google zxing 生成带logo的二维码图片

环境准备 开发环境 JDK 1.8SpringBoot2.2.1Maven 3.2 开发工具 IntelliJ IDEAsmartGitNavicat15 添加maven配置 <dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.4.0</version> </…

2023年09月 C/C++(七级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 Python编程&#xff08;1~6级&#xff09;全部真题・点这里 第1题&#xff1a;红与黑 有一间长方形的房子&#xff0c;地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上&#xff0c;只能向相邻的黑色…

新式茶饮品牌如何写出生活感软文

居民消费水平的提升使新式茶饮品牌的市场不断扩张&#xff0c;在竞争激烈的茶饮市场中&#xff0c;品牌提高知名度的主要方式之一就是软文营销&#xff0c;而生活感软文是茶饮软文中较为常见的类型&#xff0c;它能有效拉进品牌与消费者之间的距离&#xff0c;那么新式茶饮品牌…

24字符串-kmp寻找重复子串

目录 字符串匹配——kmp算法 LeetCode之路——459. 重复的子字符串 分析&#xff1a; 字符串匹配——kmp算法 强烈建议参考Carl的讲解&#xff1a; 视频讲解版&#xff1a;帮你把KMP算法学个通透&#xff01;&#xff08;理论篇&#xff09;(opens new window) 视频讲解版&…

近地面无人机植被定量遥感与生理参数反演

目录 专题一 近十年近地面无人机植被遥感文献分析、传感器选择、观测方式及质量控制要点 专题二 辐射度量与地物反射特性 专题三 无人机遥感影像辐射与几何处理 专题四 光在植被叶片与冠层中的辐射传输机理及平面模型应用 专题五 植被覆盖度与叶面积指数遥感估算 更多应用…

【开源】给ChatGLM写个,Java对接的SDK

作者&#xff1a;小傅哥 - 百度搜 小傅哥bugstack 博客&#xff1a;bugstack.cn 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; 大家好&#xff0c;我是技术UP主小傅哥。 清华大学计算机系的超大规模训练模型 ChatGLM-130B 使用效果非常牛&…

「网络编程」网络层协议_ IP协议学习_及深入理解

「前言」文章内容是网络层的IP协议讲解。 「归属专栏」网络编程 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、IP协议简介二、IP协议报头三、IP网段划分&#xff08;子网划分&#xff09;四、特殊的IP地址五、IP地址的数量限制六、私有IP地址和公网IP地址七、路由八、分…

【Python】Python语言基础(中)

第十章 Python的数据类型 基本数据类型 数字 整数 整数就是整数 浮点数 在编程中&#xff0c;小数都称之为浮点数 浮点数的精度问题 print(0.1 0.2) --------------- 0.30000000000000004 ​​1.可以通过round()函数来控制小数点后位数 round(a b)&#xff0c;则表示…

spring6使用启用Log4j2日志框架

文章目录 Log4j2日志概述1. 引入Log4j2依赖2. 加入日志配置文件3. 测试 Log4j2日志概述 在项目开发中&#xff0c;日志十分的重要&#xff0c;不管是记录运行情况还是定位线上问题&#xff0c;都离不开对日志的分析。日志记录了系统行为的时间、地点、状态等相关信息&#xff…

[Python小项目] 从桌面壁纸到AI绘画

从桌面壁纸到AI绘画 一、前言 1.1 确认问题 由于生活和工作需要&#xff0c;小编要长时间的使用电脑&#xff0c;小编又懒&#xff0c;一个主题用半年的那种&#xff0c;所以桌面壁纸也是处于常年不更换的状态。即时改变主题也是在微软自带的壁纸中选择&#xff0c;而这些自…

LaTeX 公式与表格绘制技巧

LaTeX 公式与绘图技巧公式基本可以分为 单一公式单一编号单一公式按行编号单一公式多个子编号单一公式部分子编号分段公式现在给出各自的代码单一公式单一编号 公式1&#xff1a;equationaligned\begin{equation}\begin{aligned}a&bc\\b&a2\\c&b-3\end{aligned}\en…

如何使用前端包管理器(如npm、Yarn)?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…