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

目录
  • 二叉树的前中后序遍历
  • 遍历二叉树求二叉树的结点个数
  • 遍历二叉树求二叉树的叶子结点个数
  • 求二叉树中data为x的结点
  • 求二叉树的深度

二叉树的前中后序遍历

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

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

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

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

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

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

前序遍历示意图

// 二叉树前序遍历
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的这么一个步骤。

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

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。

递归求二叉树的第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;
}

典型的前序遍历,每到一个根节点,先判断是否为空,非空则判断是否为目标结点,不是的话,就先去其左子树找,左子树没有则去右子树找,右子树没有则表示这颗二叉树中无目标节点,返回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;
}

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

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

(0)

相关推荐

  • C语言二叉树常见操作详解【前序,中序,后序,层次遍历及非递归查找,统计个数,比较,求深度】

    本文实例讲述了C语言二叉树常见操作.分享给大家供大家参考,具体如下: 一.基本概念 每个结点最多有两棵子树,左子树和右子树,次序不可以颠倒. 性质: 1.非空二叉树的第n层上至多有2^(n-1)个元素. 2.深度为h的二叉树至多有2^h-1个结点. 满二叉树:所有终端都在同一层次,且非终端结点的度数为2. 在满二叉树中若其深度为h,则其所包含的结点数必为2^h-1. 完全二叉树:除了最大的层次即成为一颗满二叉树且层次最大那层所有的结点均向左靠齐,即集中在左面的位置上,不能有空位置. 对于完全二叉

  • 通俗易懂讲解C语言与Java中二叉树的三种非递归遍历方式

    详解二叉树的三种非递归遍历方式(附C.java源码) 前言 二叉树的递归遍历方式很简单,三种递归遍历方式的区别,只是printf放的位置不一样而已,这里就不多讲了.把前序遍历代码贴在这里: //结点 struct Node { int val; struct Node* left, * right; }; //前序遍历 void pre(Node* root) { if (root == null) return; printf("%d ",root->val); pre(roo

  • C语言二叉树的非递归遍历实例分析

    本文以实例形式讲述了C语言实现二叉树的非递归遍历方法.是数据结构与算法设计中常用的技巧.分享给大家供大家参考.具体方法如下: 先序遍历: void preOrder(Node *p) //非递归 { if(!p) return; stack<Node*> s; Node *t; s.push(p); while(!s.empty()) { t=s.top(); printf("%d\n",t->data); s.pop(); if(t->right) s.pus

  • C语言数据结构之二叉树的非递归后序遍历算法

    C语言数据结构之二叉树的非递归后序遍历算法 前言: 前序.中序.后序的非递归遍历中,要数后序最为麻烦,如果只在栈中保留指向结点的指针,那是不够的,必须有一些额外的信息存放在栈中. 方法有很多,这里只举一种,先定义栈结点的数据结构 typedef struct{Node * p; int rvisited;}SNode //Node 是二叉树的结点结构,rvisited==1代表p所指向的结点的右结点已被访问过. lastOrderTraverse(BiTree bt){ //首先,从根节点开始,

  • C语言非递归后序遍历二叉树

    本文实例为大家分享了C语言非递归后序遍历二叉树的具体代码,供大家参考,具体内容如下 法一:实现思路:一个栈 先按 根->右子树->左子树的顺序访问二叉树.访问时不输出.另一个栈存入前一个栈只进栈的结点. 最后输出后一个栈的结点数据. #include<stdio.h> #include<stdlib.h> typedef struct TreeNode{ char element; struct TreeNode *left,*right; }Tree,*BTree;

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

    目录 二叉树的前中后序遍历 遍历二叉树求二叉树的结点个数 遍历二叉树求二叉树的叶子结点个数 求二叉树中data为x的结点 求二叉树的深度 二叉树的前中后序遍历 所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次.访问结点所做的操作依赖于具体的应用问题. 遍历 是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础. 按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历: 1. 前序遍历(Preorder Traversal

  • 用Python实现二叉树、二叉树非递归遍历及绘制的例子

    前言 关于二叉树的实现与遍历,网上已经有很多文章了,包括C, C++以及JAVA等.鉴于python做为脚本语言的简洁性,这里写一篇小文章用python实现二叉树,帮助一些对数据结构不太熟悉的人快速了解下二叉树.本文主要通过python以非递归形式实现二叉树构造.前序遍历,中序遍历,后序遍历,层次遍历以及求二叉树的深度及叶子结点数.其他非递归形式的遍历,想必大多人应该都很清楚,就不再声明.如果你用C或者C++或者其他高级语言写过二叉树或者阅读过相关方面代码,应该知道二叉树的非递归遍历避不开通过栈

  • C++实现二叉树非递归遍历方法实例总结

    一般来说,二叉树的遍历是C++程序员在面试中经常考察的,其实前中后三种顺序的遍历都大同小异,自己模拟两个栈用笔画画是不难写出代码的.现举一个非递归遍历的方法如下,供大家参考. 具体代码如下: class Solution { public: vector<int> preorderTraversal(TreeNode *root) { vector<int> out; stack<TreeNode*> s; s.push(root); while(!s.empty()

  • java二叉树的非递归遍历

    二叉树的递归遍历比较简单,这里就不聊了.今天主要聊聊二叉树的非递归遍历,主要借助于"栈"后进先出的特性来保存节点的顺序,先序遍历和中序遍历相对来说比较简单,重点理解后序遍历. 1. 先看看节点类型: //二叉树的节点类型 private class Node{ int data; //节点值 Node leftChild; //左孩子 Node rightChild; //右孩子 public Node(int data) { this.data=data; } } 2.先序遍历. 非

  • 二叉树先序遍历的非递归算法具体实现

    在前面一文,说过二叉树的递归遍历算法(二叉树先根(先序)遍历的改进),此文主要讲二叉树的非递归算法,采用栈结构 总结先根遍历得到的非递归算法思想如下: 1)入栈,主要是先头结点入栈,然后visit此结点 2)while,循环遍历当前结点,直至左孩子没有结点 3)if结点的右孩子为真,转入1)继续遍历,否则退出当前结点转入父母结点遍历转入1) 先看符合此思想的算法: 复制代码 代码如下: int PreOrderTraverseNonRecursiveEx(const BiTree &T, int

  • C语言进阶二叉树的基础与销毁及层序遍历详解

    单值二叉树 难度简单 如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树. 只有给定的树是单值二叉树时,才返回true:否则返回false. 示例 1: 输入:[1,1,1,1,1,null,1]输出:true 示例 2: 输入:[2,2,2,5,2]输出:false 提示: 给定树的节点数范围是[1, 100]. 每个节点的值都是整数,范围为[0, 99]. 解1: 最简单易懂的解法,先序遍历一遍,把每个节点都和那个根节点的val值相比.最后判断flag是否为真,若为假,则表明树中有

  • C语言实现线索二叉树的定义与遍历示例

    本文实例讲述了C语言实现线索二叉树的定义与遍历.分享给大家供大家参考,具体如下: #include <stdio.h> #include <malloc.h> typedef char TElemType; // 二叉树的二叉线索存储表示 typedef enum{ Link, Thread }PointerTag; // Link(0):指针,Thread(1):线索 typedef struct BiThrNode { TElemType data; struct BiThrN

随机推荐