【数据结构】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); }}
}

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

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

相关文章

阿里云服务器租用收费标准价格表(2024年更新)

2024年最新阿里云服务器租用费用优惠价格表,轻量2核2G3M带宽轻量服务器一年61元,折合5元1个月,新老用户同享99元一年服务器,2核4G5M服务器ECS优惠价199元一年,2核4G4M轻量服务器165元一年,2核4G服务器30元3…

Gitee入门之工具的安装

一、gitee是什么? Gitee(码云)是由开源中国社区在2013年推出的一个基于Git的代码托管平台,它提供中国本土化的代码托管服务。它旨在为个人、团队和企业提供稳定、高效、安全的云端软件开发协作平台,具备代码质量分析、…

React18原理: 核心包结构与两大工作循环

React核心包结构 1 ) react react基础包,只提供定义 react组件(ReactElement)的必要函数一般来说需要和渲染器(react-dom,react-native)一同使用在编写react应用的代码时, 大部分都是调用此包的api比如, 我们定义组件的时候,就是它提供的class Demo ext…

springboot198基于springboot的智能家居系统

基于Springboot的智能家居系统 **[摘要]**社会和科技的不断进步带来更便利的生活,计算机技术也越来越平民化。二十一世纪是数据时代,各种信息经过统计分析都可以得到想要的结果,所以也可以更好的为人们工作、生活服务。智能家居是家庭的重要…

【排序算法】C语言排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)

目录 什么是排序?1、桶排序 概念思路demo运行效果 2、冒泡排序 动图演示概念思路demo运行效果 3、选择排序 动图演示概念思路demo运行结果 4、插入排序 动图演示概念思路demo运行效果 5、快速排序 动图演示概念思路demo运行结果 什么是排序? 排序&…

“分布式透明化”在杭州银行核心系统上线之思考

导读 随着金融行业数字化转型的需求,银行核心系统的升级改造成为重要议题。杭州银行成功上线以 TiDB 为底层数据库的新一代核心业务系统,该实践采用应用与基础设施解耦、分布式透明化的设计开发理念,推动银行核心系统的整体升级。 本文聚焦…

easyx搭建项目-永七大作战(割草游戏)

永七大作战 游戏介绍: 永七大作战 游戏代码链接:永七大作战 提取码:ABCD 不想水文了,直接献出源码,表示我的诚意

Shellcode免杀对抗(Python)

Shellcode Python免杀,绕过360安全卫士、火绒安全、Defender Python基于cs/msf的上线 cs 执行代码2种可供选择 执行代码 1: rwxpage ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40) ctypes.windll.kernel32.RtlMoveMemory…

静态时序分析:SDC约束命令set_clock_transition详解

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 在静态时序分析:SDC约束命令create_clock详解一文的最后,我们谈到了针对理想(ideal)时钟,可以使用set_clock_transition命令直…

【VSCode】使用笔记

目录 快捷键系列 相关插件 相关文档链接 快捷键系列 调出终端 ctrl 或者是ctrlJ 结束进程 ctrlc 注释 ctrlkc 取消注释 ctrlku 上下移动代码 alt方向键 多行光标ctrlalt方向键 快速跳过某个单词 ctrl方向键 相关插件 1.每次修改后,自动保存启动项目 相…

2.12:C语言测试题

1.段错误:申请堆区内存未返回,str指向NULL 2.段错误:局部变量,本函数结束,p也释放 3.越界访问,可能正常输出hello,可能报错 4.可能段错误,释放后,str未指向NULL&#x…

【旧文更新】【优秀毕设】人脸识别打卡/签到/考勤管理系统(OpenCV+最简基本库开发、可移植树莓派 扩展网络图像推流控制 验证码及Excel邮件发送等功能)

【旧文更新】【优秀毕设】人脸识别打卡/签到/考勤管理系统(OpenCV最简基本库开发、可移植树莓派 扩展网络图像推流控制 验证码及Excel邮件发送等功能) 文章目录 关于旧文新发毕设结构主页面验证码识别效果管理页面人脸信息采集管理实时数据更新签到结果…

CSS 不同颜色的小圆角方块组成的旋转加载动画

<template><!-- 创建一个装载自定义旋转加载动画的容器 --><view class="spinner"><!-- 定义外部包裹容器,用于实现整体旋转动画 --><view class="outer"><!-- 定义四个内部小方块以形成十字形结构 --><view clas…

sqlserver对已有的表插入列

现有如下的一个表&#xff1b; 现在要插入一个 人员id 列&#xff1b;如下图在设计视图的行首单击&#xff0c;选择 插入列&#xff1b; 然后添加一个 人员id 列&#xff1b; 保存&#xff0c;出现下图提示&#xff0c;不能保存设计&#xff1b; 这就直接使用sql语句更改&#…

leetcode hot100爬楼梯

在本题目中&#xff0c;要求爬第n阶有多少种爬法&#xff0c;并且每次只能爬1个或者2个&#xff0c;这明显是动态规划的问题&#xff0c;我们需要用动态规划的解决方式去处理问题。动态规划就是按照正常的顺序由前向后依次推导。而递归则是从结果往前去寻找&#xff08;个人理解…

单片机学习笔记---LED呼吸灯直流电机调速

目录 LED呼吸灯 直流电机调速 模型结构 波形 定时器初始化函数 中断函数 主程序 上一节讲了电机的工作原理&#xff0c;这一节开始代码演示&#xff01; 我们上一篇说Ton的时间长Toff时间短电机会快&#xff0c;Ton的时间短Toff时间长电机会慢 并且我们还要保证无论Ton和…

小游戏和GUI编程(6) | 基于 SFML 的井字棋

小游戏和GUI编程(6) | 基于 SFML 的井字棋 0. 简介 使用 SFML 实现井字棋(tic-tac-toe), 规划如下: 了解规则&#xff0c; 使用命令行实现(已经实现了)使用 SFML&#xff0c;提供极简的交互(预计 1 小时)制作 SVG 图像&#xff0c; 美化界面(预计 1 小时) 1. 基于命令行的实…

分省年度数据集(1990-2021年)

一、数据介绍 数据名称&#xff1a;分省年度数据集&#xff08;1990-2021年&#xff09; 数据来源&#xff1a;国家统计局-分省年度数据 数据范围&#xff1a;1990-2021年&#xff0c;包括31个省份 指标数量 &#xff1a;2981个指标 数据整理&#xff1a;自主整理 更新时…

线性代数的本质 2 线性组合、张成的空间、基

基于3Blue1Brown视频的笔记 一种新的看待方式 对于一个向量&#xff0c;比如说&#xff0c;如何看待其中的3和-2&#xff1f; 一开始&#xff0c;我们往往将其看作长度&#xff08;从向量的首走到尾部&#xff0c;分别在x和y上走的长度&#xff09;。 在有了数乘后&#xff0…

建造者模式-Builder Pattern

原文地址:https://jaune162.blog/design-pattern/builder-pattern/ 引言 现在一般大型的业务系统中的消息通知的形式都会有多种,比如短信、站内信、钉钉通知、邮箱等形式。虽然信息内容相同,但是展现形式缺不同。如短信使用的是纯文本的形式,钉钉使用的一般是Markdown的形…