二叉树的递归实现及例题

目录

遍历方式

示例

原理

前序遍历示例

二叉树的节点个数

原理

层序遍历

原理

这样做的目的是

判断完全二叉树

例题

​编辑

思路

代码


遍历方式

二叉树的遍历方式可分为:

前序遍历:先访问根,访问左子树,在访问右子树

中序遍历:先访问左子树,在访问根,最后访问右子树

后序遍历:先访问左子树,再访问右子树,最后访问根

示例

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi) {
	if (*pi >= n || a[*pi] == '#') {
		(*pi)++;
		return NULL;
	}
	BTNode* mn = (BTNode*)malloc(sizeof(BTNode));
	mn->_data = a[*pi];
	(*pi)++;
	mn->_left = BinaryTreeCreate(a, n, pi);
	mn->_right = BinaryTreeCreate(a, n, pi);;
	return mn;
}

原理

首先判断当前节点是否为空,如果为空则return NULL

如果不为空

判断当前遍历方式

我们以前序遍历为例

先创建一个节点,将值赋给当前节点完成赋值给根的操作

然后在设置该节点的左子树与右子树

最后返回当前节点的指针实现递归操作

前序遍历示例

void BinaryTreePrevOrder(BTNode* root) {
	if (root == NULL)
		return;
	printf("%c", root->_data);
	BinaryTreePrevOrder(root->_left);
	BinaryTreePrevOrder(root->_right);
}

如果当前为空则返回,输出当前结点的值,访问左子树,访问右子树

二叉树的节点个数

int BinaryTreeSize(BTNode* root) {
	if (root == NULL)
		return 0;
	return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right)+1;
}

原理

同样先设置终止条件:

当前节点为空返回0

如果当前节点不为空,则返回左子树的节点个数与右子树的节点个数加上当前节点本身的1即可实现递归操作

层序遍历

按从左往右,从上到下的顺序访问每个节点

void BinaryTreeLevelOrder(BTNode* root) {
	Queue mn;
	QueueInit(&mn);
	BTNode* now = root;
	QueuePush(&mn, now);
	while (!(QueueEmpty(&mn))) {
		printf("%c", QueueFront(&mn)->_data);
		now = QueueFront(&mn);
		if(now->_left)
			QueuePush(&mn, now->_left);
		if (now->_right)
			QueuePush(&mn, now->_right);
		QueuePop(&mn);
	}
	QueueDestroy(&mn);
}

原理

先创建队列

将根节点放入队列

然后进入循环开始拆分

如果当前节点的左右子树不为空则将左右子树进入队列

每次循环都要先将队首元素输出同时删去队首元素

这样接下来的节点便会被一个一个访问到

这样做的目的是

节点被拆分的顺序是从上到下,先拆根,再拆根的左子树,再拆根的右子树

我们可以发现

这样便是从上到下,从左到右的顺序访问每一个节点

判断完全二叉树

int BinaryTreeComplete(BTNode* root) {
	Queue mn;
	QueueInit(&mn);
	BTNode* now = root;
	QueuePush(&mn, now);
	int tag = 0;
	while (!(QueueEmpty(&mn))) {
		printf("%c", QueueFront(&mn)->_data);
		now = QueueFront(&mn);
		if (tag && (now->_left || now->_right))
			return 0;
		if (now->_right && !now->_left)
			return 0;
		if (now->_left)
			QueuePush(&mn, now->_left);
		if (now->_right)
			QueuePush(&mn, now->_right);
		else
			tag = 1;
		QueuePop(&mn);
	}
	QueueDestroy(&mn);
	return 1;
}

与层序遍历是同样的操作,但是不同的是多了很多判断条件

但是最核心的内容始终是

如果没有左节点就存在右节点那么该树就不是完全二叉树

例题

链接:. - 力扣(LeetCode)

思路

我们可以先写一个函数用来判断两棵树是否相同,然后与原函数进行递归调用即可

代码

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    if (q == NULL && p == NULL)
        return true;
        if (p == NULL || q == NULL)
        return false;
    if (q->val != p->val)
        return false;
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
    if(root==NULL)
    return false;
    if(isSameTree(root,subRoot))
    return true;
    return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}

判断两棵树是否相同只需先判断当前节点是否相同,相同的话递归调用左右子树,只要左右子树也相同那么两棵树就相同

判断是否为子树只要采取一种遍历方式,只要当前节点不为空那么就判断当前节点开始的树是否与目标树相同,不同的话就拿左右子树进行判断,只要左右子树中存在与目标树相同的子树那么目标树即为原树的子树

相关推荐
闻缺陷则喜何志丹6 分钟前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
Lenyiin24 分钟前
01.02、判定是否互为字符重排
算法·leetcode
鸽鸽程序猿40 分钟前
【算法】【优选算法】宽搜(BFS)中队列的使用
算法·宽度优先·队列
Jackey_Song_Odd40 分钟前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
Watermelo61744 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
乐之者v1 小时前
leetCode43.字符串相乘
java·数据结构·算法
A懿轩A2 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
古希腊掌管学习的神2 小时前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
云边有个稻草人2 小时前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
半盏茶香2 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法