【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历)

二叉树

一个二叉树是一个有穷的结点集合。
它是由根节点和称为其左子树和右子树的两个不相交的二叉树组成的。
二叉树可具有以下5种形态。
在这里插入图片描述

性质

  1. 一个二叉树第i层的最大结点数为 2 i − 1 2^{i-1} 2i1, i ≥ 1 i \geq 1 i1
    每层最大结点可以对应完美二叉树(满二叉树),其所有分支结点都存在左右子树,并且所有叶结点都在同一层上。
    在这里插入图片描述
  2. 深度为k的二叉树有最大结点总数: 2 k − 1 2^k-1 2k1, k ≥ 1 k \geq 1 k1
    1 + 2 + . . . + 2 k − 1 = 2 k − 1 1 + 2 + ... +2^{k-1} = 2^k-1 1+2+...+2k1=2k1
  3. 对任何非空的二叉树 T n T_n Tn,若 n 0 n_0 n0是叶结点的个数, n 2 n_2 n2是度为2的非叶结点的个数,则: n 0 = n 2 + 1 n_0 = n_2 +1 n0=n2+1
    一颗二叉树:总结点数 = 叶节点 + 度为1的结点 + 度为2的结点
    又:总结点数 = 总边数+1
    且:总边数 = 2 ∗ 2* 2度为2的结点 + 度为1的结点
    由此得到: n 0 = n 2 + 1 n_0 = n_2 +1 n0=n2+1
  4. 具有n个结点的完全二叉树的深度k为 ⌊ l o g 2 n ⌋ + 1 \lfloor log_2{n} \rfloor +1 log2n+1
    (1) 满二叉树时:
    k深度: 结点 2 k − 1 2^k-1 2k1
    n = 2 k − 1 n = 2^k-1 n=2k1 k = l o g 2 n + 1 k = log_2{n+1} k=log2n+1
    (2)最底层只有一个结点
    k深度: 结点 2 k − 1 2^{k-1} 2k1
    解得: k = l o g 2 n + 1 k = log_2{n} +1 k=log2n+1
    l o g 2 ( n + 1 ) ≤ k ≤ l o g 2 n + 1 log_2{(n+1)} \leq k \leq log_2n +1 log2(n+1)klog2n+1
    则具有n个结点的完全二叉树的深度k为 ⌊ l o g 2 n ⌋ + 1 \lfloor log_2{n} \rfloor +1 log2n+1

存储结构

顺序存储

这种结构是川一组连续的存储单元(比如数组)存储二叉树结点的数据,结点的父子系是通过它们相对位置来反映的,而不需要任何附加的存储单元来存放指针,通常情况下顺序存储结构用于完全二叉树
具体实现是从树的根结点开始,从上层至下层,每层从左到右,依次给结点编号并将数据存放到一个数组的对应单元中。
结点C的父结点是结点B,它的左孩子是结点w,右孩子是结点K。C结点存储单元的下标是4,将其除以2得到它的父结点B的存储单元下标,而将其乘以2则是它的左孩子w存储单元的下标,当然将其乘2再加1则是它右孩子K的存储单元下标。
在这里插入图片描述
在这里插入图片描述

链式存储

虽然顺序存储的空间利用率高,计算简单,但是其不适于一般的二叉树
如图为给定的二叉树。给出了从上至下、从左至右的层序存储的对应结点编号,其中灰色结点是为了满足顺序存储要求而增加的“虚”结点,可以在相应的存储单元存放一个特殊的数值,以区别于其他“实结点”。图4.10(c)则是最终的存储结果。
可以看到,5个结点的二叉树,顺序存储需要13个存储单元,超过一半的存储空间浪费掉了。更有甚者,对一个深度为h的右斜二叉树来讲,需要2-1个存储单元,而实际上该斜二叉树只有k个结点。

另外,二叉树的顺序存储方式避免不了顺序存储的固有缺点,即不易实现增加、删除操作。因此,二叉树的顺序存储方式适用于一定的条件,对于不需要修改的完全二叉树,是一种较好的选择。
实际上,二叉树的最常用表示方法是用链表表示,每个结点由数据和左右指针三个数据成员组成。

结构定义

typedef int ElementType;
typedef struct TNode* Position;
typedef Position BinTree;
struct TNode {
	ElementType Data;//结点数据
	BinTree Left; //指向左子树
	BinTree Right; //指向右子树
};

操作实现

遍历

我们用L,V,R分别表示遍历左分支L,访问结点V,遍历右分支R,那么可以有以下6种情况:LVR,LRV,VLR,VRL,RLV,RVL。
规定:访问左分支在右分支之前,只剩下:LVR, LRV, VLR。
我们按照V的位置分别将其命名为:中序遍历,后序遍历,先序遍历

中序遍历

对树的任一结点的访问是在先遍历完其左子树后进行的,访问此结点后,在对其右子树遍历
遇到每个结点,其遍历过程

  1. 中序遍历左子树
  2. 访问根节点
  3. 中序遍历右节点
void InorderTraveral(BinTree BT) {
	if (BT) {
		InorderTraveral(BT->Left);
		printf("%d\n, BT->Data");
		InorderTraveral(BT->Right);
	}
}
后序遍历

对结点的左右子树先进行遍历,然后才对此结点访问。遍历是从根节点开始,遇到每个结点时,其遍历过程是:

  1. 后序遍历其左子树
  2. 后序遍历其右子树
  3. 访问根节点
void PostorderTraversal(BinTree BT) {
	if (BT) {
		PostorderTraversal(BT->Left);
		printf("%d\n, BT->Data");
		PostorderTraversal(BT->Right);
	}
}
先序遍历

对结点的访问是在其左、右子树遍历之前进行的。遍历是从根节点开始,遇到每个结点时,其遍历过程是:

  1. 访问根结点
  2. 先序遍历其左子树
  3. 先序遍历其右子树
void PreorderTraversal(BinTree BT) {
	if (BT) {
		printf("%d\n, BT->Data");
		PreorderTraversal(BT->Left);
		PreorderTraversal(BT->Right);
	}
}

非递归遍历

在沿左子树深入时,进入一个结点就将其压入堆栈。
若是先序遍历,则在入栈之前访问之;当沿左分支深入不下去时,则返回,即从堆栈中弹出前面压入的结点;
若为中序遍历,则此时访同该结点,然后从该结点的右子树继续深入;
若为后序遍历,则将此结点二次入栈,然后从该结点的右子树继续深入,与前面类同,仍为进入一个结点入栈一个结点,深入不下去再返回,直到第二次从栈里弹出该结点,才访问之。

对于非递归中序遍历,遇到一个节点就将其压栈,并去遍历其左子树;当左子树结束后,从栈顶弹出结点并访问它,然后按其右指针再去中序遍历该节点的右子树。

void InorderTraversalUn(BinTree BT) {
	BinTree T;
	Stack S = CreateStack(100);
	T = BT;
	while (T || !IsEmpty(S)) {
		while (T) {
			Push(S, T);
			T = T->Left;

		}
		T = Pop(S);
		printf("%d\n, T->Data");
		T = T->Right;
	}

}
层序遍历

层序遍历是按照树的层次,从第一层的根结点开始向下逐层访问每个结点,对每一层的结点按照从左到右的顺序访问。
可以设置一个队列结构,遍历从根节点开始,首先将根节指针入队,然后执行以下操作:

  1. 从队列取出一个元素
  2. 访问该元素所指向的结点
  3. 若元素所指向的结点的左右孩子非空,将其左、右孩子的指针入队。
    不断执行这三步,直到队列为空。
void LevelorderTraversal(BinTree BT) {
	Queue Q;
	BinTree T;
	T = BT;
	Q = CreateQueue(100);
	AddQ(Q, T);
	while (!IsEmptyQ(Q)) {
		T = DeleteQ(Q);
		printf("%d\n, T->Data");
		if (!T->Left) { AddQ(Q, T->Left); }
		if (!T->Right) { AddQ(Q, T->Right); }

	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

可视化锻炼日记ExerciseDiary

什么是 ExerciseDiary ? ExerciseDiary 是带有 GitHub 风格的年度可视化的锻炼日记。 安装 在群晖上以 Docker 方式安装。 在注册表中搜索 exercisediary ,选择第一个 aceberg/exercisediary,版本选择 latest。 本文写作时, lat…

互联网时代的文学复兴:中文诗词大数据分析 | 开源日报 No.170

chinese-poetry/chinese-poetry Stars: 45.4k License: MIT 最全的中文诗歌古典文集数据库,包含 5.5 万首唐诗、26 万首宋诗、2.1 万首宋词和其他古典文集。数据来源于互联网。该开源项目旨在通过 JSON 格式分发,方便用户开始自己的项目,并借…

从零开始实现一个三维绘图系统

文章目录 框架布局绘图函数源代码 框架 本文的目标是实现一个下图所示的系统,通过指定 x , y , z x,y,z x,y,z的表达式,以实现三维绘图的目的。这个需求其实此前也实现过,见此文,但其内容比较驳杂,并不利于快速实现&a…

VBA中表示单元格样式A1、R1C1和R[1]C[1]之间的区别

《VBA之Excel应用》(版权10178983)是非常经典的,是我推出的第七套教程,定位于初级,目前是第一版修订。这套教程从简单的录制宏开始讲解,一直到窗体的搭建,内容丰富,实例众多。大家可…

springboot189基于SpringBoot电商平台的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计,课程设计参考与学习用途。仅供学习参考, 不得用于商业或者非法用途,否则,一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

java-类与对象

一、类与对象 二、快速入门 三、类与对象的区别和联系 四、对象在内存中的存在形式

跟着pink老师前端入门教程-day27

三、变量 (一)变量概述 1、什么是变量 白话:变量就是一个装东西的盒子 通俗:变量是用于存放数据的容器,通过变量名获取数据,甚至数据可以修改 2、变量在内存中的存储 本质:变量是程序在内存…

原型模式-Prototype Pattern

原文地址:https://jaune162.blog/design-pattern/prototype-pattern/ 引言 在Java中如果我们想要拷贝一个对象应该怎么做?第一种方法是使用 getter和setter方法一个字段一个字段设置。或者使用 BeanUtils.copyProperties() 方法。这种方式不仅能实现相同类型之间对象的拷贝,…

解决vitepress首次加载慢(从40秒到1秒的倔强)

前言:在艰难的博客系统升级之路 这篇博客中我有提到vitepress首次加载非常耗时的问题,之前也在网上搜索时发现也有很多人说这个“问题”,但是在折腾了这么一段时间后,发现这也许本身不是vitepress的问题,而是我的启动方…

「递归算法」:两两交换链表中的节点

一、题目 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示例 1: 输入:head [1,2,3,4] 输出&#xf…

Harris关键点检测原理简介

一、2D Harris 二、 3D Harris Harris关键点检测以及SAC-IA粗配准-CSDN博客

Docker部署Springboot项目

一、把Springboot项目打成jar包 (一)右键项目文件,点击Open Module Settings (二)选中Artifacts,点击中间的加号(Project Settings->Artifacts->JAR->From modules with dependencies…

WordPress站点如何实现发布文章即主动推送到百度快速收录和普通收录?

我们在WordPress后台成功发布文章之后,如果靠搜索引擎来抓取的话,可能会比较慢,所以十分有必要将我们成功发布的文章马上提交到百度、必应等搜索引擎中。下面boke112百科就跟大家说一说WordPress站点如何实现发布文章即主动推送到百度快速收录…

【Spring源码解读 底层原理高级进阶】【上】探寻Spring内部:BeanFactory和ApplicationContext实现原理讲解

🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《Spring 狂野之旅:底层原理高级进阶》 &#x1f680…

各类有关于花卉的深度学习数据集

花卉的识别和分类在深度学习过程中是最常见的使用的案例,因此各类有关花卉分类、识别、计数的图像数据集是大家都常用的数据集。最近收集到各类有关花卉的各类数据集分享给大家!! 1、16种花常见的图像数据集 数据说明:我们看到我…

简单的edge浏览器插件开发记录

今天在浏览某些网页的时候,我想要屏蔽掉某些信息或者修改网页中的文本的颜色、背景等等。于是在浏览器的控制台中直接输入JavaScript操作dom完成了我想要的功能。但是每次在网页之间跳转该功能都会消失,我需要反复复制粘贴js脚本,无法实现自动…

二、ActiveMQ安装

ActiveMQ安装 一、相关环境二、安装Java8三、下载安装包四、启动五、其他命令六、开放端口七、后台管理 一、相关环境 环境:Centos7.9安装ActiveMQ版本:5.15.9JDK8 二、安装Java8 安装教程:https://qingsi.blog.csdn.net/article/details/…

OpenCV-38 图像金字塔

目录 一、图像金字塔 1. 高斯金字塔 2. 拉普拉斯金字塔 一、图像金字塔 图像金字塔是图像中多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单的结构。简单来说,图像金字塔是同一图像不同分辨率的子图…

Qt for android : Qt6.6.2 搭建 环境

环境说明 参考Qt助手: Assistant 6.6.2 (MinGW 11.2.0 64-bit) ***Gradle : Gradle wrapper, version 8.3***JDK11 SDK Tools / NDK 25.1.8937393 参考 Qt For Android : Qt5.13.1 Qt for android: Qt6.4搭建环境遇到的几个问题

前方预警!2024年七大网络安全威胁

新颖创新技术的兴起和迅速采用已极大地改变了各行各业的全球网络安全和合规格局,比如生成式人工智能、无代码应用程序、自动化和物联网等新技术。 网络犯罪分子正转而采用新的技术、工具和软件来发动攻击,并造成更大的破坏。因此,《2023年网…