首页 > 编程语言 >算法与数据结构——二叉树

算法与数据结构——二叉树

时间:2024-09-02 17:25:46浏览次数:8  
标签:node 遍历 TreeNode 算法 二叉树 数据结构 节点 left

二叉树

二叉树(binary tree)是一种非线性数据结构,代表“祖先”与“后代”之间的派生关系,体现了“一分为二”的分治逻辑。与链表类似,二叉树的基本单元是节点,每个节点包含值、左子节点引用和右子节点引用。

struct TreeNode{
	int val;					// 节点值
	TreeNode *left;		// 左子结点指针
	TreeNode *right;	// 右子节点指针
	TreeNode(int x) :val(x), left(nullptr), right(nullptr){}
};

每个节点都有两个引用(指针),分别指向左子节点(left-child node)右子节点(right-child node),该节点被称为这两个子节点的父节点(parent node)。当给定一个二叉树节点时,我们将该节点的左子节点及其以下节点形成的树称为该节点的左子树(left subtree),同理可得右子树(right subtree)

在二叉树中,除叶子节点外,其他所有节点都包含子节点和非空子树。如图所示,如果将“节点2”视为父节点,则其左子节点和右子节点分别是“节点4”和“节点5”,左子树是“节点4及其以下节点形成的树”,右子树是“节点5及其以下节点形成的树”。

二叉树常见术语

  • 根节点(root node):位于二叉树顶层的节点,没有父节点。
  • 叶节点(leaf node):没有子节点的节点,其两个指针均指向nullptr
  • 边(edge):连接两个节点的线段,即节点引用(指针)。
  • 节点所在的层(level):从顶至底递增,根节点所在层为1。
  • 节点的度(degree):节点的子节点的数量。在二叉树中,度的取值范围是0、1、2。
  • 二叉树的高度(height):从根节点到最远叶节点所经过的边的数量。
  • 节点的深度(depth):从根节点到该节点所经过的边的数量。
  • 节点的高度(height):从距离该节点最远的叶节点到该节点所经过的边的数量。

二叉树基本操作

初始化二叉树

与链表类似,首先初始化节点,然后构建引用(指针)。

	/*初始化二叉树*/
	// 初始化节点
	TreeNode* n1 = new TreeNode(1);
	TreeNode* n2 = new TreeNode(2);
	TreeNode* n3 = new TreeNode(3);
	TreeNode* n4 = new TreeNode(4);
	TreeNode* n5 = new TreeNode(5);

	// 构建节点之间的引用(指针)
	n1->left = n2;
	n1->right = n3;
	n2->left = n4;
	n2->right = n5;

插入与删除节点

与链表类似,在二叉树中插入与删除节点可以通过修改指针来实现。下图给出了一个示例:

	/*插入与删除节点*/
	TreeNode *P = new TreeNode(0);
	// 在 n1 -> n2 之间插入节点 P
	n1->left = P;
	P->left = n2;
	// 删除 P 节点
	n1->left = n2;

注意:插入节点可能会改变二叉树的原有逻辑结构,而删除节点通常意味着删除该节点及其所有子树。因此,在二叉树中,插入与删除通常是由一套操作配合完成的,以实现有实际意义的操作。

常见的二叉树类型

完美二叉树

如图所示,完美二叉树(perfect binary tree)所有层的节点都被完全填满。在完美二叉树中,叶节点的度为0,其余所有节点的度都为2;若树高度为h,则节点总数为2h+1 - 1,呈现标准的指数级关系,反映了自然界中常见的细胞分裂现象。

完全二叉树

如图所示,完全二叉树(complete binary tree)只有最底层的节点未被填满,且最底层节点尽量靠左填充。

完满二叉树

如图所示,完满二叉树(full binary tree)除了叶节点之外,其余所有节点都有两个子节点。

平衡二叉树

如图所示,平衡二叉树(balanced binary tree)中任意节点的左子树和右子树的高度之差的绝对值不超过1。

二叉树的退化

如图展示了二叉树的理想结构与退化结构。当二叉树的每层节点都被填满时,达到“完美二叉树”;而当所有节点都偏向一侧时,二叉树退化为“链表”。

  • 完美二叉树是理想情况,可以充分发挥二叉树“分治”的优势。
  • 链表则是另一个极端,各项操作都变为线性操作,时间复杂度退化至O(n)

二叉树遍历

从物理结构的角度来看,树时一种基于链表的数据结构,因此其遍历方式是通过指针逐个访问节点。然而,树是一种非线性数据结构,这使得遍历树比遍历链表更加复杂,需要借助搜索算法来实现。

二叉树常见的遍历方式包括层序遍历、前序遍历、中序遍历和后序遍历等。

层序遍历

层序遍历(level-order traversal)从顶部到底部逐层遍历二叉树,并在每一层按照从左往右的顺序访问节点。

层序遍历本质上属于广度优先遍历(breadth-first traversal),也称广度优先搜索(breadth-first search, BFS),它体现一种“一圈一圈向外扩展”的逐层遍历方式。

代码实现

广度优先遍历通常借助“队列来实现”。队列遵循“先进先出”的规则,而广度优先遍历则遵循“逐层推进”的规则,两者背后的思想是一致的。

vector<int> levelOrder(TreeNode *root){
	// 初始化队列,加入根节点
	queue<TreeNode *> que;
	que.push(root);
	// 返回一个vector用于打印
	vector<int> vec;
	while (!que.empty()){
		TreeNode *node = que.front();
		que.pop(); // 节点出队
		vec.push_back(node->val); // 保存节点值
		if (node->left != nullptr){
			que.push(node->left);		//左子结点入队
		}
		if (node->right != nullptr){
			que.push(node->right);		// 右子节点入队 
		}
	}
	return vec;
}

复杂度分析

  • 时间复杂度O(n):所有节点被访问一次,使用O(n)时间,其中n为节点数量
  • 空间复杂度为O(n):在最差情况喜爱,即满二叉树时,遍历到最底层之前,队列中最多同时存在(n + 1)/ 2 个节点,占用O(n)空间。

前序、中序、后序遍历

相应地,前序、中序和后序遍历都属于深度优先遍历(depth-first traversal),也称深度优先搜索(depth-first search,DFS),它体现了一种“先走到尽头,再回溯继续”的遍历方式。

下图展示了对二叉树进行深度优先遍历的工作原理。深度优先遍历就像时绕着整棵二叉树的外围“走”一圈,在每个节点都会遇到三个位置,分别对应前序、中序和后序遍历。

标签:node,遍历,TreeNode,算法,二叉树,数据结构,节点,left
From: https://www.cnblogs.com/1873cy/p/18392848

相关文章

  • 助力移动道路交通环保治理,打赢蓝天保卫战,基于YOLO家族最新端到端实时算法YOLOv10全系
    在快速发展的现代社会中,工业化的步伐虽推动了城市的繁荣,但环保问题也随之成为我们不得不面对的重大挑战。特别是在移动道路交通领域,路边与路面裸土堆积、道路扬尘等问题,不仅影响城市形象,更对空气质量与居民健康构成了严重威胁。面对这一现状,传统的监测治理手段已难以满足高效、......
  • 深入探讨人工智能算法:理论与实践
    引言人工智能(ArtificialIntelligence,简称AI)已经成为当今科技领域的热点话题,广泛应用于各行各业,从智能手机的语音助手到自动驾驶汽车,无不彰显其强大的潜力和影响力。而在AI的核心,支撑这一切的正是各种各样的AI算法。本文将深入探讨几种常见的AI算法,结合实际例证和代码,帮助......
  • Java 实现二叉树展平为链表
    Java实现二叉树展平为链表前言问题背景解决方案代码实现代码分析结论使用原地算法(O(1)空间复杂度)将二叉树展平为链表问题描述解决方案代码实现代码分析优化思路结论前言在处理二叉树数据结构时,有时需要将其转换成一种特殊的形态,即链表。这种转换可以简化某些......
  • 16.STL-常用遍历算法
    常用遍历算法for_each用于遍历有返回值可以绑定参数进行输出transform搬运注意:目标容器要有容量#define_CRT_SECURE_NO_WARNINGS#include<iostream>usingnamespacestd;#include<vector>#include<algorithm>#include<functional>classMyPrint{publi......
  • 21.STL-常用集合算法
    常用集合算法set_intersection算法求两个set集合的交集set_union算法求两个set集合的并集set_difference算法求两个set集合的差集注意:两个集合必须是有序序列#define_CRT_SECURE_NO_WARNINGS#include<iostream>usingnamespacestd;#include<vector>#include<algori......
  • 【C语言】数据结构-栈(顺序表实现)
    文章目录前言1.什么是栈2.栈的实现3.敲代码!3.1头文件3.2函数实现4.知识巩固,来道OJ!结语前言在之前的数据结构学习中,我们学习了顺序表、链表这两种结构顺序表:博客链接1单链表:博客链接2链表OJ:博客链接3除了单链表以外,还有一个结构,是双向带头循环链表。这个链表的形式如下头节点的......
  • java采用base64算法加密用户名和密码
    这里做简单记录来记录整个过程。1.首先引入前端base64.js(这里我就直接放到代码块里)2.使用base64在登陆界面加密用户名和密码3.在后端构建base64解密文件,并解密前端的用户名和密码代码如下:1.base64.js代码(创建js文件保存即可用)/*!*jquery.base64.js0.1-https://github.......
  • (算法)数据流中的第K⼤元素————<堆>
    1.题⽬链接:703.数据流中的第K⼤元素2.题⽬描述:3.解法(优先级队列):算法思路:我相信,看到TopK问题的时候,兄弟们应该能⽴⻢想到「堆」,这应该是刻在⻣⼦⾥的记忆。 C++算法代码:classKthLargest{public://创建一个小根堆priority_queue<int,vector<int>,gre......
  • (算法)最后⼀块⽯头的重量————<堆>
    1.题⽬链接:1046.最后⼀块⽯头的重量2.题⽬描述:3.解法(利⽤堆):算法思路:其实就是⼀个模拟的过程:•每次从⽯堆中拿出最⼤的元素以及次⼤的元素,然后将它们粉碎;•如果还有剩余,就将剩余的⽯头继续放在原始的⽯堆⾥⾯重复上⾯的操作,直到⽯堆⾥⾯只剩下⼀个元素,或者没有元......
  • redis-数据结构数据类型
    redis常见数据类型作者:xxxRedis共有5种基本数据类型:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。数据类型底层数据结构应用场景StringSDS它可以存储任何数据-字符串、整数、浮点值、JPEG图像、序列化的Ruby对象或您希望它承载的任何其他......