服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言进阶练习二叉树的递归遍历

C语言进阶练习二叉树的递归遍历

2023-02-09 15:37配的上了吗 C/C++

树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样。树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构都可用树形象表示,本篇

二叉树的前中后序遍历

所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。

遍历 是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:

1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。

2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。

3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

前序遍历示意图

C语言进阶练习二叉树的递归遍历

// 二叉树前序遍历
void PreOrder(BTNode* root)
{
	if (root == nullptr)
	{
		cout << "# ";
		return;       // 空的话结束递归,输出#来表示这是一个空结点
	}
	cout << root->data << " ";
	PreOrder(root->left);
	PreOrder(root->right);
}
// 二叉树中序遍历
void InOrder(BTNode* root)
{
	if (root == nullptr)
	{
		cout << "# ";
		return;
	}
	InOrder(root->left);
	cout << root->data << " ";
	InOrder(root->right);
}
// 二叉树后序遍历
void PostOrder(BTNode* root)
{
	if (root == nullptr)
	{
		cout << "# ";
		return;
	}
	PostOrder(root->left);
	PostOrder(root->right);
	cout << root->data << " ";
}

其实前中后序遍历的区别,只是在于,对这个结点进行某些操作的时机,是在遍历其左右子树之前,之中还是之后。这个操作由具体要解决的问题决定。上方例子中是以打印为例。并且左子树的遍历通常都在其右子树遍历之前。

就是,把每个非空的根节点看作一个二叉树,进行同样的操作就是二叉树的递归遍历。这些二叉树的递归遍历之间有一定的顺序。递归的结束条件是,这个结点为空,为空则不进行下一步递归。形如结点3,它的左右子树为空,在这里结束此处的递归,然后返回给上一层。

 

遍历二叉树求二叉树的结点个数

int count = 0;
void TreeSize1(BTNode* root)
{
	if (root == nullptr)
		return;
	++::count;
	TreeSize1(root->left);
	TreeSize1(root->right);
}
int TreeSize2(BTNode* root)
{
	if (root == NULL)
		return 0;
	return 1 + TreeSize2(root->left) + TreeSize2(root->right);
}

两种遍历方式,显然第二种更好,其实可以直接从递归,然后第一次递归到底部,开始思考这个计算过程。

如下图,递归至3结点时,3结点返回1+leftsize+rightsize 显然其左右返回0,所以3结点返回1,2结点的左返回1,然后求2结点的右个数,显然返回0,2结点返回给1结点2,至此,1结点的左返回2,然后求1结点的右,4结点的左返回1,右返回1,4结点返回给1结点3,所以最终1结点返回1+2+3 = 6。 当然,5和6结点都是求左右加1的这么一个步骤。

C语言进阶练习二叉树的递归遍历

 

遍历二叉树求二叉树的叶子结点个数

int LeafTreeNode(BTNode* root)
{
	if (root == nullptr)
	{
		return 0;
	}
	else if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	else
	{
		return LeafTreeNode(root->left) + LeafTreeNode(root->right);
	}
}

也是非常好理解的,不是叶子,不是空,代表其左右子树至少有一个子树不为空,则返回其左右子树的叶子节点个数,典型的分治思想。如下图,对于1结点,返回其左右子树的叶子节点个数之和即可,空返回0是防止结点2的右子树,这样2结点才能正确地返回给1结点1。

C语言进阶练习二叉树的递归遍历

递归求二叉树的第k层的结点个数

int TreeKLevel(BTNode* root, int k)   //求第k层
{
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return TreeKLevel(root->left, k - 1) + TreeKLevel(root->right, k - 1);
}

递归的结束条件是,当这个结点是空,不管k是不是1,都结束递归,另一个情况就是,此结点k是1,且不是空,表示这个结点就是所求的目标节点,无论结点下方是否还有结点都结束递归。

 

求二叉树中data为x的结点

BTNode* TreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	BTNode* retleft = TreeFind(root->left, x);
	if (retleft)
		return retleft;
	BTNode* retright = TreeFind(root->right, x);
	if (retright)
		return retright;
	return NULL;
}

C语言进阶练习二叉树的递归遍历

典型的前序遍历,每到一个根节点,先判断是否为空,非空则判断是否为目标结点,不是的话,就先去其左子树找,左子树没有则去右子树找,右子树没有则表示这颗二叉树中无目标节点,返回NULL。这个流程对于每颗二叉树都适用。

因为只是求出一个值为x的结点,所以若当前结点是x,或者其左子树有x,都会结束递归。不难理解。

 

求二叉树的深度

int  TreeDepth(BTNode* root)
{
	if (root == NULL)
		return 0;
	int leftdepth = TreeDepth(root->left);
	int rightdepth = TreeDepth(root->right);
	return 1 + leftdepth > rightdepth ? leftdepth : rightdepth;
}

C语言进阶练习二叉树的递归遍历

对于1结点,返回1+左右子树更深的那个子树,其实完全可以递归至3然后往回思考,注意每一个结点都是递归求左子树的深度之后才会递归求右子树的深度。

到此这篇关于C语言进阶练习二叉树的递归遍历的文章就介绍到这了,更多相关C语言二叉树内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/i777777777777777/article/details/125042819

延伸 · 阅读

精彩推荐
  • C/C++C++实现万年历源代码

    C++实现万年历源代码

    这篇文章主要介绍了C++实现万年历源代码,可以直接在VC6.0编译运行,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一...

    jxccy8885072021-08-26
  • C/C++makefile如何调用静态库的方法实现

    makefile如何调用静态库的方法实现

    这篇文章主要介绍了makefile如何调用静态库的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友...

    wch_NUDT7192021-10-15
  • C/C++关于C++静态数据成员的实现讲解

    关于C++静态数据成员的实现讲解

    今天小编就为大家分享一篇关于关于C++静态数据成员的实现讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小...

    Engineer-Bruce_Yang8502021-07-13
  • C/C++记逆向小白的第一次vbsedit 9爆破及内存补丁制作过程

    记逆向小白的第一次vbsedit 9爆破及内存补丁制作过程

    这篇文章主要介绍了记逆向小白的第一次vbsedit 9爆破及内存补丁制作过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要...

    patanka9802021-11-02
  • C/C++原创的C语言控制台小游戏

    原创的C语言控制台小游戏

    本文给大家分享的是个人原创设计的一个C语言控制台小游戏,非常的简单,但是挺好玩的,推荐给大家,有需要的小伙伴也可以自由扩展下。...

    OliverChu8762021-02-23
  • C/C++C++实现LeetCode(148.链表排序)

    C++实现LeetCode(148.链表排序)

    这篇文章主要介绍了C++实现LeetCode(148.链表排序),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    Grandyang12142021-12-07
  • C/C++C语言实现合并字符串

    C语言实现合并字符串

    今天小编就为大家分享一篇C语言实现合并字符串,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    grey_csdn9662021-08-10
  • C/C++C++数据结构之堆详解

    C++数据结构之堆详解

    本文详细讲解了C++数据结构之堆,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    CairBin12032022-11-04