大数据最新宿友用一把王者的时间入门了【二叉树】,你又懂多少呢?乌拉(2),2024年最新字节跳动大数据开发面试

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

同学们不懂的地方一定要画图去理解!!

🎄3. 中序遍历

中遍历结果为:H D I B E J A F K C G

1️⃣ 动画演示:👇🏻

请添加图片描述

2️⃣代码实现💡:

void InOrder(BTNode\* root)
{
	if (root == NULL)// 递归中遇到NULL,返回上一层节点
	{
		printf("# ");
		return;
	}
	InOrder(root->left);// 递归遍历左子树
	printf("%d ", root->data);
	InOrder(root->right);// 递归遍历右子树
}

❗递归展开图(以下图为例):
画图很重要,不理解就要去画图✅

在这里插入图片描述

还是刚刚的递归图,只是改变了访问顺序中序:左子树——根——右子树

🌍此处的递归结果:# 3 # 2 # 1 # 5 # 4 # 6 #

在这里插入图片描述

🎄4. 后序遍历

1️⃣ 动画演示:👇🏻

请添加图片描述

2️⃣代码实现💡:

void PostOrder(BTNode\* root)
{
	if (root == NULL)// 递归中遇到NULL,返回上一层节点
	{
		printf("# ");
		return;
	}
	PostOrder(root->left);// 递归遍历左子树
	PostOrder(root->right);// 递归遍历右子树
	printf("%d ", root->data);
}

❗递归展开图(还是以下图为例):

在这里插入图片描述

还是要去画递归展开图,只是改变了访问顺序后序:左子树——右子树——根

🌍此处的递归结果:# # 3 # 2 # # 5 # # 6 4 1

在这里插入图片描述

ps:递归展开图多画就能理解,才方便后序更难的二叉树。

🎄5. 层序遍历

1️⃣ 演示:👇🏻

在这里插入图片描述

2️⃣🎇思路讲解:

请添加图片描述

  • 借助一个队列实现:先进先出
  • 上一层带下一层,先进去的先出,每次循环出一个

3️⃣代码实现💡:

void LevelOrder(BTNode\* root)
{
	Quene q;
	QueneInit(&q);
	if (root)
	{
		QuenePush(&q, root);
	}
	while (!QueneEmpty(&q))
	{
		BTNode\* front = QueneFront(&q);
		printf("%d ", front->data);
		QuenePop(&q);
		if (front->left)
		{
			QuenePush(&q, front->left);
		}
		if (front->right)
		{
			QuenePush(&q, front->right);
		}
	}
	printf("\n");
	QueneDestroy(&q);
}

在这里插入图片描述
完全一样

🐾探究二叉树节点个数以及高度

🎄1.二叉树节点个数

定义一个Count,计算结点的个数,那么Count是全局变量还是局部变量?

答案:全局变量!不然每次递归各自加各自的Count,无意义。

💡代码实现遍历法

//遍历
int count = 0;
void BinaryTreeSize1(BTNode\* root)
{
	if (root == NULL)
	{
		return;
	}
	++count;
	BinaryTreeSize1(root->left);
	BinaryTreeSize1(root->right);//此处为前序,其实前中后序都是可以的
}

同一棵树在我第两次调用的时候,发现第二次的结果不同于第一次

在这里插入图片描述

📌很简单,第二次是在第一次调用的基础上累加的。所以最好的方式是:每次调用之前,都给count初始化为0

到这里大家是不是以为已经解决了?其实这里还有个大问题:linux中的多线程
如果这个函数被多线程去调用就会出错,也就是并发,两个线程都调用这个函数,会加在同一个count上,也就出错了。

那有没有更好的方法呢❓ 答案肯定是有的✅

💡代码实现分治思路

//分治思想
int BinaryTreeSize2(BTNode\* root)
{
	return root == NULL ? 0 : BinaryTreeSize2(root->left) + BinaryTreeSize2(root->right) + 1;
}

如果大家对这个方法不熟悉,可以画一下栈帧展开图🙌

🎄2. 二叉树叶子节点个数

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

这个理解起来还可以吧🤏拿捏~

🎄3. 二叉树第k层节点个数

大家看到k层是不是想到了层序遍历呢?

但这和层序遍历没有关系,还是要用子问题的思维去解题~转化成:

  • 求左子树的第k-1层+求右子树的第k-1层

💡代码实现

int TreeKLevel(BTNode\* root, int k)
{
	assert(root);
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return TreeKLevel(root->left,k-1) + TreeKLevel(root->right,k-1);
}

ps:注意递归的时候只能用k-1而不是 k–

  • 因为递归到时候,递归了左子树,之后还要递归右子树,若使用了k–,递归左树的时候k已经自减减少了,再回来求右树时候的k已经是错的k了,所以要保证k不能变

🎄4. 二叉树查找值为x的结点

第一次写:(错误写法)

BTNode\* BinaryTreeFind(BTNode\* root, BTDataType x)
{
	if (root->data == x)
		return root;
	if (root == NULL)
		return NULL;
	if (BinaryTreeFind(root->left, x))
		return BinaryTreeFind(root->left, x);
	if (BinaryTreeFind(root->right, x))
		return BinaryTreeFind(root->right, x);
	return NULL;
}

这种写法,我们发现如果我们找到了结点,返回值的时候还要再递归一次,太费劲了

好比我们写博客,写到一半,电脑死机了,还要重新写的感觉😈

💡代码实现(最好的方式💯)

BTNode\* BinaryTreeFind(BTNode\* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	BTNode\* left = BinaryTreeFind(root->left, x);
	if (left)
		return left;
	BTNode\* right = BinaryTreeFind(root->right, x);
	if (right)
		return right;//每一次return都是回到上一层
	return NULL;
}

🎄5.求二叉树的高度

二叉树的深度改怎么样求呢?

一样利用分治的思想来实现

  • 左右分别递归,返回上一层加1,再比较左右树高度

🎇思路讲解:

在这里插入图片描述

💡代码实现

int TreeDepth(BTNode\* root)
{
	if (root == NULL)
		return 0;
	int leftDepth = TreeDepth(root->left);
	int RightDepth = TreeDepth(root->right);
	
	return leftDepth > RightDepth ? leftDepth+1 : RightDepth+1;
}

🎄6.销毁二叉树

销毁用什么序列呢?

后序!

  • 若使用前序遍历的话,删除了节点还能找到左右子树么?
  • 可以是可以,但还要指针保存起来,比较麻烦

💡代码实现

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

RightDepth+1;
}


### 🎄6.销毁二叉树


销毁用什么序列呢?



> 
> **后序!**
> 
> 
> 


* 若使用前序遍历的话,删除了节点还能找到左右子树么?
* 可以是可以,但还要指针保存起来,比较麻烦


💡**代码实现**




[外链图片转存中...(img-v3I2F2JN-1715776740206)]
[外链图片转存中...(img-gDYnw0U4-1715776740207)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值