二叉树的递归实现及例题

目录

遍历方式

示例

原理

前序遍历示例

二叉树的节点个数

原理

层序遍历

原理

这样做的目的是

判断完全二叉树

例题

​编辑

思路

代码


遍历方式

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

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

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

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

示例

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

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

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

相关推荐
励志成为嵌入式工程师31 分钟前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉1 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer1 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
wheeldown2 小时前
【数据结构】选择排序
数据结构·算法·排序算法
观音山保我别报错3 小时前
C语言扫雷小游戏
c语言·开发语言·算法
TangKenny4 小时前
计算网络信号
java·算法·华为
景鹤4 小时前
【算法】递归+深搜:814.二叉树剪枝
算法
iiFrankie4 小时前
SCNU习题 总结与复习
算法
Dola_Pan5 小时前
C++算法和竞赛:哈希算法、动态规划DP算法、贪心算法、博弈算法
c++·算法·哈希算法
小林熬夜学编程5 小时前
【Linux系统编程】第四十一弹---线程深度解析:从地址空间到多线程实践
linux·c语言·开发语言·c++·算法