一:二叉树节点问题
(1)二叉树所有节点
- 要算出二叉树的节点个数我们可以遍历二叉树,不为空就将大小加一
- 所以我们可以这么写代码:
void TreeSize(BTNode* root,int*size)//所有节点的个数
{
if (root == NULL)
{
return;
}
(*size)++;
TreeSize(root->left,size);
TreeSize(root->right,size);
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
- 前序遍历二叉树。如果节点为空直接返回,否则将size++
- 但我们还可以用分治的思想来计算二叉树节点的个数
- 总节点个数=左子树节点个数+右子树节点个数+1(加一是因为根不为空,根为空直接返回0)
- 这样我们的代码就可以简化成一行
int TreeSize(BTNode* root)
{
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
(2)二叉树第k层节点
-
计算第k层节点个数继续利用分治思想
-
根的第k层的节点个数=左子树的k-1层的节点个数+右子树的k-1层的节点个数
-
当k==1时,节点个数返回1,节点为空返回0
-
代码如下
int TreeKLevelSize(BTNode* root, int k)//第k层节点个数
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return TreeKLevelSize(root->left, k - 1) + TreeKLevelSize(root->right, k - 1);
}
(3)二叉树叶子节点
- 先来回忆一下叶子节点的定义是什么
- 度为0的节点称为叶子节点
- 而整个二叉树的叶子节点个数怎么算呢
- 对了,就是左子树有的叶子节点个数加上右子树有的叶子节点个数
- 所以判断节点是否是叶子节点时需要判断左树节点和右树节点是否均为空
- 如果根为NULL,就返回0
- 如果左右子树节点均为NULL,说明此节点为叶子节点,返回1
- 不满足上述两种情况说明还没找到叶子节点,继续递归
- 代码如下:
int TreeLeafSize(BTNode* root)//叶子节点个数
{
if (root == NULL)
{
return 0;
}
else
{
if (root->left == NULL && root->right ==NULL)
{
return 1;
}
else
{
return (TreeLeafSize(root->left) + TreeLeafSize(root->right));
}
}
}
二:查找二叉树节点
- 查找二叉树与前面的写法有些许不同,我们需要创建变量保存我们的返回值
- 思想也很简单,如果根为空返回空,如果根的值和找到值一样就返回根、
- 如果不一样就往左子树和右子树找,知道找到空节点为止
- 而找到的节点我们有可能在很下面才找到,所以需要一层一层的返回,就有必要创建变量存储每次函数调用的返回值了
- 我们创建变量ret存储左子树的返回值,如果不是空说明找到了,直接返回ret,不用找右子树了
- 如果ret为空我们就继续查找右子树,并且不论ret为何值直接返回
- 因为如果ret为我们查找的值直接返回ret就找到了,如果没找到ret就是NULL,我们最终返回的也是NULL
BTNode* TreeFind(BTNode* root, BTDataType x)//查找二叉树节点
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BTNode* ret=TreeFind(root->left, x);
if (ret != NULL)
{
return ret;
}
ret=TreeFind(root->right, x);
return ret;
}
三:翻转二叉树
- 翻转二叉树就是将每个左右子树的节点交换一下
- 示例如下:
- 思路也并不复杂,先新建变量保存右子树,之后将左子树翻转后赋给右子树
- 然后再将右子树翻转后赋给左子树
- 最终返回root
BTNode* InvertTree(BTNode* root)//翻转二叉树
{
if (root == NULL)
{
return NULL;
}
BTNode* right = root->right;
root->right = InvertTree(root->left);
root->left = InvertTree(right);
return root;
}
四:判断两个二叉树是否相等
- 如果两个二叉树为NULL,返回true
- 一个为Null一个不为NULL,返回false
- 两个根的值不相等,返回false
- 如果上述均不满足,就继续判断左子树和右子树是否相等
- 因为要左右子树均相等才能说明两个二叉树这个节点相等,所以直接要用&&连接
- 每个节点均相同最后才会返回true,有一个不同就会返回false
bool isSameTree(BTNode* p, BTNode* q)//判断两个二叉树是否相等
{
if (p == NULL && q == NULL)
{
return true;
}
if (p == NULL || q == NULL)
{
return false;
}
if (p->data != q->data)
{
return false;
}
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
五:判断是否子树
- 这里假设两个二叉树均不为空
- 要判断一个树是否是另一个树的子树,就需要遍历这个树,将每个子树与其比较是否相等
- 正好需要用到上一个函数来判断两个二叉树是否相等
- 首先如果根为空,而两个树均不为空,说明母树已经到底了,直接返回false
- 如果根不为空就将其与另一个树比较,相同的话直接返回true
- 不同的话用左子树和右子树与其比较,只要有相同就返回true
bool isSubtree(BTNode* root, BTNode* subRoot)
{
if (root == NULL)
{
return false;
}
if (isSameTree(root, subRoot) == true)
{
return true;
}
return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}