二叉树的遍历及相关衍生

这篇具有很好参考价值的文章主要介绍了二叉树的遍历及相关衍生。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

如标题所示,在这里我们要研究的是二叉树的遍历。

为什么不讲二叉树的增删查改?
在实际使用过程中,二叉树的增删查改没有多大作用,二叉树是作为一种数据结构,不是用来存储数据,更多的是用来进行搜索

赫赫有名的红黑树和B树,都是其的限制优化的产物之一。

但是身为小白的博主现在只能先从最基本的遍历开始玩起。

博主刚学C++一点,为了练习和熟悉,所以用的是C++,但是也没多熟练,还是有C的老习惯,请各位多多海涵

二叉树的遍历

建树

我们想要学习对树的遍历,首先就要有一颗树。

所以我们先要进行一次快速的建树
二叉树的遍历及相关衍生
我们要建立这样一颗树

可以看出我们在设计类的变量时,需要设置三个
1:存储数据的int
2:存放右子节点的指针
3:存放左子节点的指针

class tree
{
public:
	tree* inittree(int x, tree* left, tree* right)
	{
		tree* ptr = (tree*)malloc(sizeof(tree));
		assert(ptr);
		ptr->_data = x;
		ptr->_left = left;
		ptr->_right = right;
		return ptr;
	}
private:
	int _data;
	tree* _left;
	tree* _right;
};
int main()
{
	tree t1;
	tree* ptr3=t1.inittree(3, nullptr, nullptr);
	tree* ptr2=t1.inittree(2, ptr3, nullptr);
	tree* ptr6 = t1.inittree(6, nullptr, nullptr);
	tree* ptr5 = t1.inittree(5, nullptr, nullptr);
	tree* ptr4 = t1.inittree(4, ptr5, ptr6);
	tree* ptr1 = t1.inittree(1, ptr2, ptr4);
}

没错,建树就是这么简单直接,因为我们主要来学习他的遍历,所以建树这些繁琐的事情快速解决就好了。

二叉树的遍历

看名字,所谓遍历,就是将二叉树中的数据全部访问一遍

二叉树的遍历及相关衍生
如果我们要实现这颗二叉树的遍历,想必大家都多少听过,二叉树和递归算法脱不了一点关系。

虽然有些人听到递归就有点小怕,但是如果把思路理解了以后,递归可比迭代快太多了。

当我们进行遍历的时候,有这样三种操作

1:访问根,就是遍历的历,对根存储的数据进行访问。
2:走向左子树,
3:走向右子树
二叉树的遍历及相关衍生
设计的都是先访问左子树,再访问右子树
这应该是约定俗成的把,虽然先右到左也没什么区别,但是从左往右还是看着赏心悦目一点。

所以纠结的只有根的访问顺序,这样就牵扯到遍历的差别了。

遍历的分类

前根遍历
顾名思义,就是先根后左右
先根后左右
这里我们先将
1:访问根
2:访问左子树
3:访问右子树
这样设定好
二叉树的遍历及相关衍生
二叉树的遍历及相关衍生
因为递归是对函数的重复调用,作用对象是每一个节点,所以到了左子树的节点后,要对子节点进行同样与根节点的操作
即先访问节点数据,在进行左子树和右子树的访问。
二叉树的遍历及相关衍生
这里为了方便看清,就在第一个第二个第三个节点加了前缀,1.1就是第一个节点访问根。

这里当第三个节点访问左右子树为空后,直接进行返回。

剩下两个遍历类型为

中根遍历

即先访问左子树,访问根,再访问右子树

后根遍历

即先访问左右子树,再访问根。

就不多讲了。

代码部分

void Traversaltree(tree* root)
	{
		if (root == nullptr)
		{
			cout << " NULL";
			return;
		}
		//访问根的部分按照遍历存放
		//访问根的代码按照具体情况而定

//访问根放这-前根
		printtree(root->_left);
//访问根放这-中根
		printtree(root->_right);
//访问根放这-后根
	}

遍历根的应用

打印树中的每个数据

由于我们这个二叉树不是完全二叉树这种特殊树,所以用数组打印时,就会导致残缺不堪
二叉树的遍历及相关衍生
就比如打印这颗树

代码部分

void printtree(tree* root)
	{
		if (root == nullptr)
		{
			cout << " NULL";
			return;
		}
		//前根遍历打印
		cout << " " << root->_data; 
		printtree(root->_left);
		printtree(root->_right);
	}

遍历计算树节点个数

代码部分

	int  sizetree(tree* root)
	{
		if (root == nullptr)
			return 0;
		return sizetree(root->_left)
		 + sizetree(root->_right) + 1;

	}

按照代码画图

二叉树的遍历及相关衍生
先是通过sizetree(root->_left),从根节点不断访问左子树,然后节点继续访问它的左子树,直到节点的左子树为空。
当访问到3节点时,在进行左子树为NULL后返回0

随后执行sizetree(root->_right),对3节点的右子树进行访问,为空,返0。

执行return sizetree(root->_left) + sizetree(root->_right) + 1;
返回 {(左子树的返回)0+(右子树的返回)0 + 1=1}

这个时候重新返回了2节点,
二叉树的遍历及相关衍生

对于二节点,收到了左子树的返回1,右子树为空,返回0

返回给1节点的访问左子树的返回值为
(2节点访问左子树返回值) 1+(2节点访问左子树返回值) 0 +1=2

解释到这,就可以推测出整个递归运行的逻辑了。

计算二叉树的深度

故名思义,就是计算二叉树的深度。

为了更能体现作用,所以将之前的树重新接了一下
二叉树的遍历及相关衍生

思路

这里我们采用直接思考解决方法,直接写代码
不通过想象它的一次一次递归的执行方式去写代码
这样更加快速,当然等会还是会解释递归的执行思路的。

这里我们先不看整个二叉树,我们先来看,对于单一的一个子节点来说
当它接收到来自左边和右边的深度后
将右边和左边的深度进行比较
如果左边较大,则返回左边深度+1值
如果右边较大,则返回右边深度+1值

为什么要+1?
因为返回深度的话还要把自己的深度+1

这样我们就可以试着写出一个代码了

if (root == nullptr)
     return 0;
return heighttree(root->_left) > 
heighttree(root->_right)
?
 heighttree(root->_left) + 1 
:
 heighttree(root->_right) + 1;

这样运行一下,发现还真可以计算,但是如果你深度进行观察这个代码,就会发现这个写法太挫了
当我们进行比较后,不停进行右子树和左子树访问后

在进行三目操作符执行后,居然还要进行左子树和右子树的访问,这样时间复杂度直接从On变到了On^2

其实要解决这个问题也很简单,加个计数的就好,接下来的是最优的代码。

代码部分

int heighttree(tree* root)
	{
		if (root == nullptr)
			return 0;
		int left=heighttree(root->_left);
		int right=heighttree(root->_right);
		return left > right ? left + 1 : right + 1;	
	}

二叉树的遍历及相关衍生

首先不断执行int left=heighttree(root->_left);

不停访问左子树,到节点3时,左子树为空
赋值int left=0,之后执行int right=heighttree(root->_right);

访问到6节点,再执行6的左子树访问,到5节点

5节点左右为空,left right皆为0
进行三目操作符比较后,执行return right+1

此时回到6节点
6节点的左子树访问返回,进行赋值int left=1
右子树为空,所以int right=0
进行三目操作符比较后,执行return left+1

返回到 3节点
得到int right=2
left=0进行比较,返回right+1

…………
解释了两个三个节点操作过程就可以看出整个的递归逻辑了。

第k层个数

顾名思义,给定一个k,求第k层有几个节点

这里直接上代码了,因为难度和前面大差不差

//第k层个数
	int treeklevel(tree* root,int k)
	{
		if (root == nullptr)
			return 0;
		if (k == 1)
			return 1;
		return treeklevel(root->_left,k-1) 
		+ treeklevel(root->_right,k-1);
	}

结束

本人画图和解释的精力和能力有限,可能讲的也不是很清楚,正好又碰上递归这个难题,所以请各位多多海涵文章来源地址https://www.toymoban.com/news/detail-428947.html

到了这里,关于二叉树的遍历及相关衍生的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【LeetCode】102. 二叉树的层序遍历、107. 二叉树的层序遍历 II

     作者:小卢 专栏:《Leetcode》 喜欢的话:世间因为少年的挺身而出,而更加瑰丽。                                  ——《人民日报》 102. 二叉树的层序遍历 给你二叉树的根节点  root  ,返回其节点值的  层序遍历  。 (即逐层地,从左到右访问所有节点)  示例:

    2024年02月13日
    浏览(31)
  • 【LeetCode】105. 从前序与中序遍历序列构造二叉树,106. 从中序与后序遍历序列构造二叉树,144. 二叉树的前序遍历非递归实现,94. 二叉树的中序遍历非递归实现,145. 二叉树的后序

    给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的 先序遍历 , inorder 是同一棵树的 中序遍历 ,请构造二叉树并返回其根节点。 示例 输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7] 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的

    2024年02月04日
    浏览(28)
  • 二叉树 | 二叉树的前序遍历问题

    二叉树的前序遍历问题描述 提供二叉树的根节点 root ,返回它节点值的 前序   遍历。 二叉树的前序遍历是一种深度优先遍历(DFS)的方式,其遍历顺序为:先访问根节点,然后递归地对左子树进行前序遍历,最后递归地对右子树进行前序遍历。 二叉树的定义 在Java中,二

    2024年02月01日
    浏览(34)
  • 二叉树题目:二叉树的中序遍历

    标题:二叉树的中序遍历 出处:94. 二叉树的中序遍历 3 级 要求 给你二叉树的根结点 root texttt{root} root ,返回其结点值的中序遍历。 示例 示例 1: 输入: root   =   [1,null,2,3] texttt{root = [1,null,2,3]} root = [1,null,2,3] 输出: [1,3,2] texttt{[1,3,2]} [1,3,2] 示例 2: 输入: root   =  

    2024年02月09日
    浏览(41)
  • 二叉树OJ题进阶(二叉树层序遍历、根据二叉树创建字符串、判断完全二叉树、二叉树的构建及遍历、二叉树的最近公共祖先(2种))

    1.思路 用队列写: 1.从上到下,从左到右的顺序 2.非递归的方法:使用队列来完成 3.cur充当根结点,当cur不为空的时候,cur进入队列,队列不为空,cur弹出队列打印 4.如果cur的左边不为空,左边进队,右边不为空,右边进队 5.此时队列不为空,弹出队头(也就是cur的左边)打

    2024年02月05日
    浏览(31)
  • 树的前序遍历与中序遍历构造二叉树和树的中序遍历与后序遍历构造二叉树

    目录 一.树的前序遍历与中序遍历构造二叉树 1.题目描述 2.问题分析 3.代码实现 二.树的中序遍历与后序遍历构造二叉树 1.题目描述 2.问题分析 3.代码实现 三.问题思考 给定两个整数数组  preorder 和 inorder  ,其中  preorder 是二叉树的 先序遍历 , inorder  是同一棵树的 中序遍

    2023年04月15日
    浏览(34)
  • 算法练习第13天|递归实现 144.二叉树的前序遍历(opens new window)145.二叉树的后序遍历(opens new window)94.二叉树的中序遍历

    二叉树的存储方式:链式存储和顺序存储。链式存储用指针,顺序存储用数组。其结构如下图所示。 链式存储: 顺序存储: 顺序存储时,若父节点下表为i,则其左孩子下标为 2*i + 1,右孩子下标为2*i + 2. 二叉树主要有两种遍历方式: 深度优先遍历:先往深走,遇到叶子节点

    2024年02月22日
    浏览(40)
  • 二叉树题目:二叉树的层序遍历 II

    标题:二叉树的层序遍历 II 出处:107. 二叉树的层序遍历 II 4 级 要求 给你二叉树的根结点 root texttt{root} root ,返回其结点值自底向上的层序遍历(即从左到右,按从叶结点所在层到根结点所在层逐层遍历)。 示例 示例 1: 输入: root   =   [3,9,20,null,null,15,7] texttt{root = [3

    2024年02月11日
    浏览(29)
  • 二叉树的递归遍历与迭代遍历(图示)

    本文将讲述二叉树递归与迭代的相关知识。 🕺作者: 迷茫的启明星 专栏:【数据结构从0到1】 相关文章:《数据结构二叉树的链式存储讲解及前中后序遍历和层次遍历》 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇 码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要,有

    2024年02月04日
    浏览(38)
  • 二叉树的遍历(递归法)

    递归的三要素: ①确定递归函数的参数和返回值 ②确定终止条件 ③确定单层递归的逻辑 以前序遍历为例: 1、确定递归函数的参数和返回值: 参数中需要传入list来存放节点的数值,除了这一点就不需要再处理什么数据了也不需要有返回值,因此递归函数的返回类型就是v

    2024年01月17日
    浏览(61)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包