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

这篇具有很好参考价值的文章主要介绍了【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

二叉树

一个二叉树是一个有穷的结点集合。
它是由根节点和称为其左子树和右子树的两个不相交的二叉树组成的。
二叉树可具有以下5种形态。
【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历),数据结构,C\C++,数据结构,算法

性质

  1. 一个二叉树第i层的最大结点数为 2 i − 1 2^{i-1} 2i1, i ≥ 1 i \geq 1 i1
    每层最大结点可以对应完美二叉树(满二叉树),其所有分支结点都存在左右子树,并且所有叶结点都在同一层上。
    【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历),数据结构,C\C++,数据结构,算法
  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的存储单元下标。
【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历),数据结构,C\C++,数据结构,算法
【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历),数据结构,C\C++,数据结构,算法

链式存储

虽然顺序存储的空间利用率高,计算简单,但是其不适于一般的二叉树
如图为给定的二叉树。给出了从上至下、从左至右的层序存储的对应结点编号,其中灰色结点是为了满足顺序存储要求而增加的“虚”结点,可以在相应的存储单元存放一个特殊的数值,以区别于其他“实结点”。【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历),数据结构,C\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;
	}

}
层序遍历

层序遍历是按照树的层次,从第一层的根结点开始向下逐层访问每个结点,对每一层的结点按照从左到右的顺序访问。
可以设置一个队列结构,遍历从根节点开始,首先将根节指针入队,然后执行以下操作:文章来源地址https://www.toymoban.com/news/detail-830670.html

  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); }

	}
}

到了这里,关于【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】树,二叉树,满二叉树,完全二叉树的定义和二叉树的基本操作

    🎊专栏【数据结构】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【勋章】 大一同学小吉,欢迎并且感谢大家指出我的问题🥰 目录 ⭐树 🏳️‍🌈定义  🏳️‍🌈注意 🍔树的基本术语 ⭐二叉树 🏳️‍🌈定义 🎆二叉树和树的区别 🏳️‍🌈二叉树

    2024年02月05日
    浏览(51)
  • 数据结构和算法学习记录——平衡二叉树(基本介绍、平衡因子、平衡二叉树的定义、平衡二叉树的高度)

    目录 基本介绍 平衡因子 平衡二叉树  平衡二叉树的高度  什么是平衡二叉树? 以一个例子来解释一下: 搜索树结点按不同的插入次序,将会导致不同的深度和平均查找长度ASL   在二叉搜索树中查找一个元素:  (a)要找到Jan,需要查找一次;要找到Feb,需要查找两次;

    2023年04月26日
    浏览(49)
  • 【数据结构】二叉树性质巩固

    🚀write in front🚀 📜所属专栏:初阶数据结构 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!! 关注我,关注我,关注我 , 你们将会看到更多的优质内容!!   在学习完二叉树以后,我

    2023年04月20日
    浏览(25)
  • 【C语言/数据结构】二叉树(层序遍历|判断完全二叉树|性质)

     🌈个人主页: 秦jh__https://blog.csdn.net/qinjh_?spm=1010.2135.3001.5343 🔥 系列专栏: 《数据结构》https://blog.csdn.net/qinjh_/category_12536791.html?spm=1001.2014.3001.5482 ​ ​​​ 目录  层序遍历  层序遍历函数实现 判断二叉树是否为完全二叉树 二叉树性质        💬 hello! 各位铁子们大

    2024年01月24日
    浏览(37)
  • 二叉树的概念|满二叉树与完全二叉树|二叉树的性质|二叉树的存储结构

    在数据结构中树的用途其实并不大,用得更多的其实是二叉树。所以在本章我们将详细讲解二叉树。 一颗二叉树是结点的一个 有限集合 ,该集合: 或者为空 或者由一个根节点加上两颗(互不相交)别称为左子树和右子树的二叉树组成 如图我们可知, 二叉树的特点: 二叉

    2024年01月21日
    浏览(33)
  • 数据结构进阶篇 之 【二叉树】详细概念讲解(带你认识何为二叉树及其性质)

    有朋自远方来,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,鞭数十,驱之别院 1.1 二叉树中组分构成名词概念 1.2 二叉树的结构概念 1.3 特殊的二叉树 2.1 顺序存储 2.2 链式存储 前言: 在你的想象中如果有一个“二叉树”会是什么样子呢? 顾名思义,现实中的二叉树我们

    2024年04月13日
    浏览(29)
  • 数据结构初阶之二叉树性质练习与代码练习

    个人主页:点我进入主页 专栏分类:C语言初阶      C语言程序设计————KTV       C语言小游戏     C语言进阶 C语言刷题       数据结构初阶    Linux 欢迎大家点赞,评论,收藏。 一起努力,共赴大厂。 目录 1.前言 2.性质练习 3.代码练习  3.1单值二叉树 3.2检查两颗树

    2024年02月04日
    浏览(32)
  • 【数据结构】树、二叉树的概念和二叉树的顺序结构及实现

    之前我们学习了顺序表、链表以及栈和队列这些数据结构,但这些数据结构都是线性的(一对一)。接下来要学习 非线性的数据结构——树(二叉树) ,相比前面的,树的结构更加复杂,话不多说,直接进入正题吧。 树是一种 非线性的数据结构 ,它是 一对多(也有可能是

    2024年02月07日
    浏览(30)
  • 【数据结构】二叉树的链式结构

    学习链式二叉树要知道三种遍历方式,便于对二叉树的节点以及左子树和右子树进行操作。 前序遍历:根、左子树、右子树 中序遍历:左子树、根、右子树 后序遍历:左子树、右子树、根 以下图为例: 得到的结果: 前序遍历:1 2 3 4 5 6 中序遍历:3 2 1 5 4 6 后序遍历:3 2

    2024年02月08日
    浏览(40)
  • 数据结构——二叉树的链式结构

      个人主页 : 日刷百题 系列专栏 : 〖C语言小游戏〗〖Linux〗〖数据结构〗  〖C语言〗 🌎 欢迎各位 → 点赞 👍+ 收藏 ⭐️+ 留言 📝  ​ 这里我们使用先序遍历的思想来创建二叉树,这里的内容对于刚接触二叉树的朋友可能有些难理解,不妨先看完下面的二叉树各种遍历

    2024年02月05日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包