【数据结构】二叉树的递归思想

目录

1.关于二叉树的遍历

1. 先序遍历 中序遍历 后续遍历

2.关于二叉树的其他函数实现

1.二叉树节点的个数,

2.二叉树叶子的个数,

3.二叉树 的深度

4.第 k 层 二叉树节点的个数;

3.二叉树递归OJ题

1.单值二叉树

2.相同的树

3.另一颗子树


1.关于二叉树的遍历

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

二叉树的遍历有 四种 方法,分别是 前序遍历 中序遍历 后续遍历 以及 层序遍历;

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

4.  层序遍历 设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

1.我们先简单的定义一个 二叉树;

像这样的二叉树: 

代码实现:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef struct BinaryTreeNode
{
	int data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

BTNode* CreatTree()
{
	BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
	assert(n1);
	BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
	assert(n2);
	BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
	assert(n3);
	BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
	assert(n4);
	BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
	assert(n5);
	BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
	assert(n6);

	BTNode* n7 = (BTNode*)malloc(sizeof(BTNode));
	assert(n7);

	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;
	n5->data = 5;
	n6->data = 6;
	n7->data = 7;

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n3->left = NULL;
	n3->right = n7;
	n4->left = n5;
	n4->right = n6;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;


	n7->left = NULL;
	n7->right = NULL;
	return n1;
}

1. 先序遍历 中序遍历 后续遍历

这里的遍历运用到了 递归的思想 

// 先序遍历
void FrontBT(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%d ", root->data);
	FrontBT(root->left);
	FrontBT(root->right);
}

// 中序遍历
void MidBT(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	FrontBT(root->left);
	printf("%d ", root->data);
	FrontBT(root->right);
}

// 后序遍历
void BackBT(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	BackBT(root->left);
	BackBT(root->right);
	printf("%d ", root->data);
}

 这里我们以后序遍历为例,用下图来说明递归的过程:


运行结果如下:

2.关于二叉树的其他函数实现

1.二叉树节点的个数,

static int count = 0;
int TreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return;
	}
	count++;
	TreeSize(root->left);
	TreeSize(root->right);
	return count;
}

2.二叉树叶子的个数,

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

3.二叉树 的深度

int TreeHeight(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int ldp = TreeHeight(root->left);
	int rdp = TreeHeight(root->right);
	return ldp > rdp ? ldp + 1 : rdp + 1;
}

4.第 k 层 二叉树节点的个数;

// 第 k 层 节点个数   -> 转换从 左右子树的问题
int TreeKLeavel(BTNode* root, int k)
{
	if (root == NULL)
	{
		return;
	}
	static int count = 0;
	k--;
	if (k == 0)
	{
		if (root != NULL)
		{
			count++;
		}
		return;
	}
	TreeKLeavel(root->left, k);
	TreeKLeavel(root->right, k);
	return count;
}

// 这里 第k 层节点个数 还可以这样写
int TreeKLeavel(BTNode* root, int k)
{
	assert(k > 0);
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return TreeKLeavel(root->left, k - 1) + TreeKLeavel(root->right, k - 1);
}

3.二叉树递归OJ题

1.单值二叉树

思路 :

一棵树的所有节点都有相同的值,当且仅当对于树上的每一条边的两个端点,它们都有相同的值(这样根据传递性,所有节点都有相同的值)。

因此,我们可以对树进行一次深度优先搜索。当搜索到节点 x 时,我们检查 x 与 x 的每一个子节点之间的边是否满足要求。例如对于左子节点而言,如果其存在并且值与 x 相同,那么我们继续向下搜索该左子节点;如果值与 x 不同,那么我们直接返回false。

bool isUnivalTree(struct TreeNode* root){
    if(root == NULL)
    {
        return true;
    }
    if(root->left && root->val != root->left->val)
    {
        return false;
    }
    if(root->right && root->val != root->right->val)
    {
        return false;
    }
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

2.相同的树

 思路:

如果两个二叉树都为空,则两个二叉树相同。如果两个二叉树中有且只有一个为空,则两个二叉树一定不相同。

如果两个二叉树都不为空,那么首先判断它们的根节点的值是否相同,若不相同则两个二叉树一定不同,若相同,再分别判断两个二叉树的左子树是否相同以及右子树是否相同。这是一个递归的过程,因此可以使用深度优先搜索,递归地判断两个二叉树是否相同。

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

3.另一颗子树

 思路:

这一题相当于 上一题的延申,利用 判断 原树的 每个节点 是否与 suRoot 相等 就可以解决

bool isSameTree(struct TreeNode* p, struct TreeNode* q){
    if(p == NULL&& q == NULL)
    {
        return true;
    }
    if((p == NULL && q != NULL) ||( q== NULL && p != NULL ))
    {
        return false;
    }
    if(p->val != q ->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);
    // 左右子树有一个为 真 就为真
}
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值