二叉树的递归实现及例题

目录

遍历方式

示例

原理

前序遍历示例

二叉树的节点个数

原理

层序遍历

原理

这样做的目的是

判断完全二叉树

例题

​编辑

思路

代码


遍历方式

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

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

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

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

示例

复制代码
// 通过前序遍历的数组"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);
}

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

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

相关推荐
天选之女wow19 分钟前
【代码随想录算法训练营——Day58】图论——117.软件构建、47. 参加科学大会
算法·图论
第七序章25 分钟前
【C + +】C + + 11(中)——Lambda 表达式 + 可变参数模板
c语言·c++·算法·1024程序员节
我是苏苏5 小时前
C#高级:程序查询写法性能优化提升策略(附带Gzip算法示例)
开发语言·算法·c#
sali-tec6 小时前
C# 基于halcon的视觉工作流-章56-彩图转云图
人工智能·算法·计算机视觉·c#
黑岚樱梦10 小时前
代码随想录打卡day23:435.无重叠区间
算法
Kuo-Teng10 小时前
Leetcode438. 找到字符串中所有字母异位词
java·算法·leetcode
gihigo199811 小时前
MATLAB使用遗传算法解决车间资源分配动态调度问题
算法·matlab
墨染点香11 小时前
LeetCode 刷题【138. 随机链表的复制】
算法·leetcode·链表
却道天凉_好个秋11 小时前
目标检测算法与原理(一):迁移学习
算法·目标检测·迁移学习