数据结构界的终极幻神----树

news2025/1/15 20:02:52

目录

一.数的概念和分类

种类

二.重点概念

哈希树:

二叉树的线索化

什么是线索化

为什么要线索化

特殊的查找树

完全二叉树

三.手撕完全二叉树(堆)

重点讲解

向上搜索算法

向下搜索算法


一.数的概念和分类

树(tree)是包含 n(n≥0) [2] 个节点,当 n=0 时,称为空树,非空树中

条边的有穷集,在非空树中:

(1)每个元素称为节点(node)。

(2)有一个特定的节点被称为根节点或树根(root)。

(3)除根节点之外的其余数据元素被分为个互不相交的集合,其中每一个集合本身也是一棵树,被称作原树的子树(subtree)。

树也可以这样定义:树是由根节点和若干颗子树构成的。树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的节点,所定义的关系称为父子关系。父子关系在树的节点之间建立了一个层次结构。在这种层次结构中有一个节点具有特殊的地位,这个节点称为该树的根节点,或称为树根。

树中的节点具有明显的层级关系,并且一个节点可以对应多个节点。 我们可以形式地给出树的递归定义如下:

单个节点是一棵树,树根就是该节点本身。

是树,它们的根节点分别为

。用一个新节点

作为

的父亲,则得到一棵新树,节点n就是新树的根。我们称

为一组兄弟节点,它们都是节点

的子节点。我们还称

为节点n的子树。

空集合也是树,称为空树。空树中没有节点;

孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;

节点的度:一个节点含有的子节点的个数称为该节点的度;

叶节点或终端节点:度为0的节点称为叶节点;

非终端节点或分支节点:度不为0的节点;

双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;

兄弟节点:具有相同父节点的节点互称为兄弟节点;

树的度:一棵树中,最大的节点的度称为树的度;

节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;

树的高度或深度:树中节点的最大层次;

堂兄弟节点:双亲在同一层的节点互为堂兄弟;

节点的祖先:从根到该节点所经分支上的所有节点;

子孙:以某节点为根的子树中任一节点都称为该节点的子孙;

森林:由

棵互不相交的树的集合称为森林。

种类

无序树:树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树;

有序树:树中任意节点的子结点之间有顺序关系,这种树称为有序树;

二叉树:每个节点最多含有两个子树的树称为二叉树;

满二叉树:叶节点除外的所有节点均含有两个子树的树被称为满二叉树;

完全二叉树:除最后一层外,所有层都是满节点,且最后一层缺右边连续节点的二叉树称为完全二叉树;

二叉搜索树:满足左子节点比父节点小,右子节点比父节点大

哈夫曼树(最优二叉树):带权路径最短的二叉树称为哈夫曼树或最优二叉树。

二.重点概念

哈希树:

其实在数据结构中哈希树的概念并不怎么被认可,不过在区块链中确实有这种概念

哈希树,也称为默克尔树(Merkle Tree),是一种树形数据结构,用于在计算机科学中高效地验证和组织数据。哈希树特别适用于需要快速查找和验证大量数据的情况,如在区块链技术中。

哈希树的每个节点都包含数据的哈希值,这使得它可以用于数据完整性的验证。树的根节点包含整个数据结构的哈希值,即默克尔根(Merkle Root)。如果数据结构中的任何部分发生更改,会导致默克尔根变化,从而能够检测到这些更改。

哈希树在密码学和安全领域有着广泛的应用,特别是在数字签名和加密货币(如比特币)中,它用于确保交易记录的安全性和不可篡改性。

二叉树的线索化

什么是线索化

线索化的步骤:

根据某种遍历序列(前、中后序遍历),先确定下来每个节点的前驱和后继。
对于每个节点来说,他的左右指针可能没有指向节点(值为NULL),这时候我们可以运用这些“空闲”的指针。比如:左指针如果有空闲,就用这个指针指向这个节点对应遍历序列的前驱,右指针如果有空闲,就用这个指针指向这个节点对应遍历序列的后继。(注意:遍历序列中一头一尾是没有前驱或者后继的,所以如果指针有空闲,我们还是当它指向的是孩子,而不是前驱或者后继)
对于每个节点都实现了步骤2后,线索化完成

为什么要线索化

我们来线索化主要有两个原因

从空间上来说
对于一颗有n个节点二叉树,每个节点都有两个指针,这一棵树的所有节点总共有2n个指针。对于除了根节点以外的节点,每个节点都对应着一个指向其的指针,有且仅有这些指针是非空的,共有(n-1)个指针,那么空值指针就有n+1个,这个数量是很大的,对于空间的浪费也比较多
从遍历实现上
在我们用二叉树的递归遍历时,会遇到两个问题,一是:遍历需要的时间较多;二是:递归时候不断创建函数副本,对于内存来说也有一定压力。如果我们只用先进行一次递归遍历实现线索化,之后通过线索来遍历,能大大减少遍历时间和内存风险。
或者栈等数据结构来保持遍历的状态。而线索化后的二叉树可以通过线索(即额外的指针)直接找到前驱和后继节点,从而无需用额外的空间。这样可以提高遍历的效率和性能。
原文链接:https://blog.csdn.net/m0_74222411/article/details/132240822

我们常听到有的人说线索二叉树,但其实这种说法并不准确,准确来说应该是二叉树的线索化

特殊的查找树

但所有子节点都比父节点大时,就会破会树状结构,这是就引入了一些新的树形结构AVL树,红黑树

完全二叉树

通俗来讲就是,该结构的n-1层都被填满,最后一层可以不满,但从左至右不能有空位,必须按位置顺序排列,不能两个子节点中间空一个节点的位置

而满二叉树则是一种特殊的完全二叉树,堆则是完全二叉树

堆分为大堆和小堆

大堆即父节点的数据大于子节点,小堆反之

三.手撕完全二叉树(堆)

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
typedef int HeapDataType;
typedef struct Heap
{
	HeapDataType* data;
	int size;
	int capacity;
}HP;
void initHP(HP* php)
{
	assert(php);
	php->data = NULL;
	php->size = 0;
	php->capacity = 0;
}
void destroyHP(HP* php)
{
	assert(php);
	free(php->data);
	php->capacity = 0;
	php->size = 0;
}
void Swap(HeapDataType* x, HeapDataType* y)
{
	HeapDataType temp = *x;
	*x = *y;
	*y = temp;
}
void adjustUP(HeapDataType* p, int size, HeapDataType data)
{
	int child = size;
	int parent = (child - 1) / 2;
	while (parent >= 0)
	{
		if (p[parent] < p[child])
		{
			Swap(&p[parent], &p[child]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else break;
	}
}
void pushHP(HP* php, HeapDataType data)
{
	assert(php);
	if (php->capacity == php->size)
	{
		int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
		HeapDataType* tmp = (HeapDataType*)realloc(php->data, sizeof(HeapDataType) * newcapacity);
		if (tmp == NULL)
			return;
		php->data = tmp;
		php->capacity = newcapacity;
	}
	php->data[php->size] = data;
	php->size++;
	adjustUP(php->data, php->size - 1, data);
}
bool isEmpty(HP* php)
{
	assert(php);
	return php->size == 0;
}
HeapDataType topHP(HP* php)
{
	assert(php);
	assert(!isEmpty(php));
	return php->data[0];
}
void adjustDown(HeapDataType* p, int size, HeapDataType data)
{
	int parent = 0;
	int child = parent * 2 + 1;
	if (p[child] < p[child + 1])
		child++;
	while (child <= size)
	{
		if (child + 1 <= size && p[parent] < p[child])
		{
			Swap(&p[parent], &p[child]);
			parent = child;
			child = child * 2 + 1;
			if (p[child] < p[child + 1])
				child++;
		}
		else break;
	}
}
void popHP(HP* php)
{
	assert(php);
	assert(!isEmpty(php));
	Swap(&php->data[0], &php->data[php->size - 1]);
	php->size--;
	adjustDown(php->data, php->size, php->data[0]);
}

重点讲解

向上搜索算法

在我们插入新的数据到该结构时(这里以小堆为例),我们需要判断子节点是否会比父节点还小,如果是,则要将子节点与父节点进行交换,直到不是

向下搜索算法

与向上搜索算法同理,应用于删除第一个节点

首先将第一个数据和最后一个数据交换位置,然后让新的第一个数据向下(因为这个数据为父节点,有可能比下面的某个子节点小),这是我们有两个选择,与左节点交换还是右节点,答案是最小的那个,这样才能保证最后被换上来的父节点最小

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习笔记 DeepFakes和换脸技术简述

一、简述 人脸检测一直是 2000 年代初的主要研究课题。差不多二十年后,这个问题基本上得到了解决,并且人脸检测在大多数编程语言中都可以作为库使用。甚至换脸技术也不是什么新鲜事,并且已经存在了好些年了。 早在2016年左右就有基于OpenCV进行面部交换的方式了,主要是基于…

安卓玩机工具推荐----高通芯片9008端口读写分区 备份分区 恢复分区 制作线刷包 工具操作解析

上期解析了下adb端口备份分区的有关操作 安卓玩机工具推荐----ADB状态读写分区 备份分区 恢复分区 查看分区号 工具操作解析 在以往的博文中对于高通芯片机型的分区读写已经分享了很多。相关类似博文 安卓备份分区----手动查询安卓系统分区信息 导出系统分区的一些基本操作 …

【C++】C/C++内存管理详解

个人主页 &#xff1a; zxctscl 文章封面来自&#xff1a;艺术家–贤海林 如有转载请先通知 目录 1. 前言2. C/C内存分布3. C语言中动态内存管理方式4. C中动态内存管理4.1 new/delete操作内置类型4.2 new和delete操作自定义类型 5. operator new与operator delete函数5.1 oper…

【MySQL】not in遇上null的坑

今天遇到一个问题&#xff1a; 1、当 in 内的字段包含 null 的时候&#xff0c;正常过滤&#xff1b; 2、当 not in 内的字段包含 null 的时候&#xff0c;不能正常过滤&#xff0c;即使满足条件&#xff0c;最终结果也为 空。 测试如下&#xff1a; select * from emp e;当…

SoundTouch对音频处理(Android)

SoundTouch对音频处理&#xff08;Android&#xff09; SoundTouch介绍 SoundTouch 是一个用于音频处理的开源库&#xff0c;主要用于改变音频的速度、音调和音量等特征。您可以在项目中使用 SoundTouch 库来实现音频处理的功能&#xff0c;比如变速播放、音高变化、混响效果…

设计模式之模版方法实践

模版方法实践案例 实践之前还是先了解一下模版方法的定义 定义 模板方法模式是一种行为设计模式&#xff0c;它定义了一个骨架&#xff0c;并允许子类在不改变结构的情况下重写的特定步骤。模板方法模式通过在父类中定义一个模板方法&#xff0c;其中包含了主要步骤&#xf…

绳牵引并联机器人动态避障方法

绳牵引并联机器人在受限空间中如何躲避动态障碍物&#xff0c;是个有挑战的课题。 来自哈尔滨工业大学&#xff08;深圳&#xff09;的熊昊老师团队&#xff0c;开展了一项有趣的研究&#xff0c;论文《Dynamic Obstacle Avoidance for Cable-Driven Parallel Robots With Mob…

MySQL实战45讲——30答疑文章(二):用动态的观点看加锁

目录 不等号条件里的等值查询 等值查询的过程 怎么看死锁&#xff1f; 怎么看锁等待&#xff1f; update 的例子 小结 上期问题时间 提示 文章摘自林晓斌老师《MySQL实战45讲》&#xff0c;作为笔记而用&#xff0c;故有加一些自己的理解。在第[20]和[21]篇文章中&…

【Python】3. 基础语法(2) -- 语句篇

顺序语句 默认情况下, Python 的代码执行顺序是按照从上到下的顺序, 依次执行的. print("1") print("2") print("3")执行结果一定为 “123”, 而不会出现 “321” 或者 “132” 等. 这种按照顺序执行的代码, 我们称为 顺序语句. 这个顺序是很关…

2-web端管理界面使用rabbitmq

Web管理界面可以直接操作RabbitMQ&#xff0c;下面进行操作并记录步骤 1、添加交换器&#xff1a; Add a new exchange 中&#xff0c;Name是交换器名称&#xff0c;Type是交换器类型&#xff0c;有direce、fanout、heders、topic 4种。 这里先只填Name和选个类型&#xff0c;…

BurpSuite2024.2.1

1.更新介绍 此版本引入了特定的API 扫描功能&#xff0c;并将 Bambdas 合并到 Logger 捕获过滤器中。我们还改进了 DOM Invader 和 Burp Suite 导航记录器的功能&#xff0c;并进行了许多其他改进和错误修复。 API扫描 我们引入了特定的 API 扫描功能。您现在可以上传 OpenAP…

C语言数据结构(6)——队列

欢迎来到博主的专栏——C语言进阶指南 博主ID&#xff1a;代码小豪 文章目录 队列顺序结构的队列顺序队列的初始化顺序队列的入队列操作判断队列是否为空顺序队列的出队列操作顺序队列操作的所有代码 链式结构的队列链式队列的初始化链式队列的初始化链式队列的入队列操作链式…

Python读取.csv/.txt文件并画图

文章目录 读取.txt文件并画出每列数据读取.csv文件并画出每列数据python绘图的基本知识补充 读取.txt文件并画出每列数据 main.ipynb //注意文件类型为.ipynbimport matplotlib.pyplot as plt import numpy as npdata np.loadtxt(result.txt) fig plt.figure(dpi100,figsize…

TabLayout预览不了?

<TableLayoutandroid:layout_width"wrap_content"android:layout_height"wrap_content"/> 当然预览不了了&#xff0c;这其实不是我要的控件。 而实际需要的是TabLayout 不是TableLayout &#xff01;&#xff01;&#xff01; <com.google.an…

浅析extern关键字

C中extern关键字的使用 文章目录 C中extern关键字的使用前言正文1. C与C编译区别2. C调用C函数3. C中调用C函数 总结 前言 ​ C 是一种支持多范式的编程语言&#xff0c;它既可以实现面向对象的编程&#xff0c;也可以实现泛型编程和函数式编程。C 还具有与C语言的兼容性&…

2024.3.4 JAVA 复习

Java环境搭建 1、JDK和JRE的概述 JDK&#xff1a;Java开发工具包(Java Development Kit), 包含开发工具 和 JRE. 常用的开发工具: javac, java JRE&#xff1a;Java运行时环境(Java Runtime Environment), 包含运行Java程序时所需的核心类库和 JVM. 核心类库: java.lang, jav…

YTM32同步串行通信引擎SPI外设详解(slave part)

YTM32同步串行通信引擎SPI外设详解&#xff08;slave part&#xff09; 文章目录 YTM32同步串行通信引擎SPI外设详解&#xff08;slave part&#xff09;IntroductionPricinple & Mechinism引脚信号Slave从机工作模式发送/命令FIFO和接收FIFOMatch匹配接收功能硬件片选和内…

windows环境下编译调试x265工程

1、在具备visual studio软件情况下&#xff0c;源码和工具下载 下载x265源码&#xff1a;https://github.com/videolan/x265 下载cmake:https://cmake.org/download/ 2、生成x265的工程项目 在自己cmake目录下&#xff0c;找到cmake-gui.exe&#xff0c;安装目录的bin习&#x…

CC攻击的特征和防护措施

随着互联网的快速发展&#xff0c;网络攻击日益频繁。在目前的各种网络攻击中&#xff0c;CC攻击是一种常见的网络攻击手段之一。CC攻击&#xff08;也称为DDoS攻击&#xff09;是指通过大量请求或恶意流量向目标网站或服务器发送请求&#xff0c;以使其服务不可用。可能大家都…

【Leetcode每日一题】 前缀和 - 连续数组(难度⭐⭐)(30)

1. 题目解析 题目链接&#xff1a;525. 连续数组 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 核心在于计算题目所给数组是否存在连续子数组使得数组里头0和1的数量相同&#xff0c;存在返回连续子数组最长长度即可&#xff0c…