暴力数据结构之二叉树(初阶)

递归是一种很重要的思想,他可以帮助我们将大问题细分为许多个小问题,从而拆解问题,使得问题简单化,本篇博客主要利用的就是递归的思想,将整棵树的问题拆解为许多个根节点与左右子树的简单问题。

 1. 二叉树遍历

总体核心思路:核心逻辑为递归调用,即分治思想,将问题不断拆解,从初始根节点与左右子树依次向下分解,直到叶子结点不可再分。 

1.1 前序遍历

前序遍历主要是以 先根节点 再左子树 再右子树为逻辑遍历, 以例图为例

前序遍历后为:A B D NULL NULL NULL C NULL E NULL NULL

BTNode* BuyNode(int x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		return NULL;
	}

	node->data = x;
	node->left = NULL;
	node->right = NULL;

	return node;
}
void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	printf("%d ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}
1.2 中序遍历

核心逻辑:以左子树 根节点 右子树的顺序遍历

中序遍历后结果为:NULL D NULL B NULL A NULL C NULL E NULL

void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}
1.3 后序遍历

核心逻辑:以左子树 右子树 根节点 的顺序遍历

中序遍历后结果为:NULL NULL D NULL B NULL NULL NULL E C A

void BehendOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}

	BehendOrder(root->left);
	BehendOrder(root->right);
	printf("%d ", root->data);
}

2. 树的计算

2.1 计算全部节点个数

计算全部节点就是遍历整棵树后计算所有节点即可,不递归的方法就是使用全局变量或者传一个指针参数,这二者均有局限,所以主要介绍递归。

非递归:

int size = 0;
int TreeSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	else
		++size;

	TreeSize(root->left);
	TreeSize(root->right);

	return size;
}

void TreeSize(BTNode* root, int* psize)
{
	if (root == NULL)
		return 0;
	else
		++(*psize);

	TreeSize(root->left, psize);
	TreeSize(root->right, psize);
}

递归:依旧是将大问题分解为小问题,然后直到无法分解为止,将遍历整棵树看做遍历一个根节点与左子树和右子树,逐层拆解。


int TreeSize(BTNode* root)
{
	return root == NULL ? 0 :
		TreeSize(root->left) + TreeSize(root->right) + 1;
}
2.2 计算叶子节点个数

首先空树没有叶子节点,直接返回返回0,是叶子结点返回1,不是叶子结点就递归返回他的左子树与右子树,逐层拆解到叶子节点。

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);
}
2.3 计算树的高度

这里保存左右子树的高度,防止递归导致栈溢出。即分别求左子树与右子树的告诉,返回较大的值加一。

但是可以使用fmax来取出二者较大值,也是一种新思路。

 有效率问题
int TreeHeight(BTNode* root)
{
	if (root == NULL)
		return 0;

	return TreeHeight(root->left) > TreeHeight(root->right) ?
		TreeHeight(root->left) + 1 : TreeHeight(root->right) + 1;
}

int fmax(int x, int y)
{
	return x > y ? x : y;
}

int TreeHeight(BTNode* root)
{
	if (root == NULL)
		return 0;

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

	int leftHeight = TreeHeight(root->left);
	int rightHeight = TreeHeight(root->right);

	return leftHeight > rightHeight ?
		leftHeight + 1 : rightHeight + 1;
}
2.4 计算第K层的节点数

递归:空树返回空,第零层即只有根节点返回1,其余的拆解为左子树与右子树的问题,依次递归。

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

3. Leetcode 练习

965.单值二叉树

思路解析: 判断是否为单值二叉树就是判断所有节点的值是否相同。但是依次遍历判断有些麻烦,所以这里可以使用反证法,即只要找到不符合的节点就直接返回false,并结合递归的方法,将大问题分解为小问题。

具体解析:首先空树符合单值二叉树,直接返回true,其次判断左子树,先判断是否存在,之后判断其节点对应的值是否与根节点对应的值相同,右子树同理,最后返回递归的值。

bool isUnivalTree(struct TreeNode* root)
{
    if(root == NULL)
       return true;

    if(root->left && root->left->val != root->val)
       return false;

    if(root->right && root->right->val != root->val)
       return false;

    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

  • 27
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值