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

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

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

目录

二叉树的线索化

堆的定义及其建立

树与森林

霍(哈)夫曼树


二叉树的线索化

线索化二叉树(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.hqwc.cn/news/131019.html

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

相关文章

【排序算法】选择排序

文章目录 一&#xff1a;基本介绍1.1 概念1.2 算法思想1.3 思路分析图1.4 思路分析1.5 总结1.5.1 选择排序一共有数组大小-1轮排序1.5.2 每一轮排序&#xff0c;又是一个循环&#xff0c;循环的规则如下&#xff08;在代码中实现&#xff09;&#xff1a; 二&#xff1a;代码实…

微信小程序在TS模板下引入TDesign组件

介绍 TDesign 是腾讯官方出品的一款微信小程序组件库。本文介绍如何在新建ts空白模板下引入TDesign库 步骤 新建一个空白项目&#xff0c;这里可以选择TS-基础模板 新建项目目录结构如图所示&#xff1a; 注意这里其实小程序的文件都存放在miniprogram文件夹下&#xff0c;…

vue3+ts项目02-安装eslint、prettier和sass

创建项目 项目创建 安装eslint yarn add eslint -D生成配置文件 npx eslint --init安装其他插件 yarn add -D eslint-plugin-import eslint-plugin-vue eslint-plugin-node eslint-plugin-prettier eslint-config-prettier eslint-plugin-node babel/eslint-parser vue-e…

qt判断当前日期的当月的最后一天是几号

1、拖个dateTimeEdit在界面上&#xff0c;同时来判断输入的时间的最后一天的日期是什么&#xff1f; int year,month;int monthArr[12]{31,28,31,30,31,30,31,31,30,31,30,31};QDateTime time ui->dateTimeEdit->dateTime();year time.toString("yyyy").toIn…

配置接口策略路由

【微|信|公|众|号&#xff1a;厦门微思网络】 【微思网络www.xmws.cn&#xff0c;成立于2002年&#xff0c;专业培训21年&#xff0c;思科、华为、红帽、ORACLE、VMware等厂商认证及考试&#xff0c;以及其他认证PMP、CISP、ITIL等】 组网需求 如图1所示&#xff0c;缺省情况下…

第83步 时间序列建模实战:Catboost回归建模

基于WIN10的64位系统演示 一、写在前面 这一期&#xff0c;我们介绍Catboost回归。 同样&#xff0c;这里使用这个数据&#xff1a; 《PLoS One》2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with Renal Syndr…

简单好用的CHM文件阅读器 CHM Viewer Star最新 for mac

CHM Viewer Star 是一款适用于 Mac 平台的 CHM 文件阅读器软件&#xff0c;支持本地和远程 CHM 文件的打开和查看。它提供了直观易用的界面设计&#xff0c;支持多种浏览模式&#xff0c;如书籍模式、缩略图模式和文本模式等&#xff0c;并提供了丰富的功能和工具&#xff0c;如…

数字人解决方案——ER-NeRF实时对话数字人模型训练与项目部署

前言 1、算法概述 ER-NeRF是基于NeRF用于生成数字人的方法&#xff0c;可以达到实时生成的效果。具体来说&#xff0c;为了提高动态头部重建的准确性&#xff0c;ER-NeRF引入了一种紧凑且表达丰富的基于NeRF的三平面哈希表示法&#xff0c;通过三个平面哈希编码器剪枝空的空间…

STM32:GPIO模拟SPI驱动ADS8361

ADS8361是TI公司开发的一款模拟量输入芯片。ADS8361有四种工作模式&#xff0c;本文主要针对模式三进行通信驱动。官方方案使用两路SPI来通信&#xff0c;一路SPI Master&#xff0c;一路SPI Slave。我在使用STM32主控芯片的两路SPI进行通信的时候&#xff0c;发现只有SPI Mast…

ES6 class类的静态方法static有什么用

在项目中&#xff0c;工具类的封装经常使用静态方法。 // amap.jsimport AMapLoader from amap/amap-jsapi-loader; import { promiseLock } from triascloud/utils; /*** 高德地图初始化工具*/ class AMapHelper {static getAMap window.AMap? window.AMap: promiseLock(AM…

【1】MongoDB的安装以及连接

今天是2023年10月11日&#xff0c;MongoDB最新版本是7.0.2 最近闲着没事学习一下MongoDB这个NoSQL数据库&#xff0c;有时间就顺手记录一下我学习的笔记吧~ 学习笔记来自黑马程序员《MongoDB基础入门到高级进阶&#xff0c;一套搞定mongodb》 配套资料&#xff1a;点此资料链接…

AMEYA360分享:村田电子搭载了Onsemi公司IoT设备专用IC的新Bluetooth® Low Energy模块开始量产

近年来&#xff0c;所有远程监控、远程控制的用例均要求具备可无线连接的电池驱动IoT设备&#xff0c;而长寿命电池与安全的数据通信功能是其关键。为此&#xff0c;在IoT边缘设备的设计方面&#xff0c;最大的课题是要提高功率效率和安全性。 Type 2EG由于无线与内置微处理器两…