目录
一、相同的树
二、单值二叉树
三、对称二叉树
四、树的遍历
前序遍历
中序遍历
后序遍历
五、另一颗树的子树
六、二叉树的遍历
七、翻转二叉树
八、平衡二叉树
链接:100. 相同的树 - 力扣(LeetCode)
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
if (p == NULL && q == NULL)
return true;
if (p == NULL || q == NULL)
return false;
if (p->val != q->val)
return false;
return isSameTree(p->left, q->left)
&& isSameTree(p->right, q->right);
}
链接:965. 单值二叉树 - 力扣(LeetCode)
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);
}
思路:左子树的左节点与右子树的右节点比较,左子树的右节点和右子树的左节点比较
bool _isSymmetric(struct TreeNode* leftRoot, struct TreeNode* rightRoot) {
if (leftRoot == NULL && rightRoot == NULL)
return true;
if (leftRoot == NULL || rightRoot == NULL)
return false;
if (leftRoot->val != rightRoot->val)
return false;
return _isSymmetric(leftRoot->left, rightRoot->right)
&& _isSymmetric(leftRoot->right, rightRoot->left);
}
bool isSymmetric(struct TreeNode* root) {
return _isSymmetric(root->left, root->right);
}
OJ是允许我们额外根据需要创建函数的,原函数的参数只有一个,不能满足同时判断两个节点的是否相等的要求,所以我们创建递归函数_isSymmetric(),用来判断左右子树是否对称。
链接:144. 二叉树的前序遍历 - 力扣(LeetCode)
int TreeSize(struct TreeNode* root) {
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
void _preorder(struct TreeNode* root, int* a, int* i) {
if (root == NULL)
return;
a[(*i)++] = root->val;
_preorder(root->left, a, i);
_preorder(root->right, a, i);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = TreeSize(root);
int* a = (int*)malloc(*returnSize * sizeof(int));
int i = 0;
_preorder(root, a, &i);
return a;
}
题中要求我们将前序遍历的结果存到数组中并输出数组,那么我们需要创建一个数组插入数据,同时我们也需要数组的大小,所以我们增加了
- TreeSize函数统计树的节点个数,
- _preorder递归函数将节点插入数组。
preorderTraversal函数中:
_preorder函数中:
94. 二叉树的中序遍历 - 力扣(LeetCode)
int TreeSize(struct TreeNode* root) {
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
void _inorder(struct TreeNode* root, int* a, int* i) {
if (root == NULL)
return;
_inorder(root->left, a, i);
a[(*i)++] = root->val;
_inorder(root->right, a, i);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = TreeSize(root);
int* a = (int*)malloc(*returnSize * sizeof(int));
int i = 0;
_inorder(root, a, &i);
return a;
}
145. 二叉树的后序遍历 - 力扣(LeetCode)
int TreeSize(struct TreeNode* root) {
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
void _postorder(struct TreeNode* root, int* a, int* i) {
if (root == NULL)
return;
_postorder(root->left, a, i);
_postorder(root->right, a, i);
a[(*i)++] = root->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = TreeSize(root);
int* a = (int*)malloc(*returnSize * sizeof(int));
int i = 0;
_postorder(root, a, &i);
return a;
}
链接:572. 另一棵树的子树 - 力扣(LeetCode)
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
if (p == NULL && q == NULL)
return true;
if (p == NULL || q == 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);
}
调用 isSameTree 辅助判断子树是否相等:
isSubtree函数:
root
是 NULL
,那么它不可能包含任何子树,函数返回 false
。isSameTree(root, subRoot)
返回 true
,说明在当前的节点上,root
和 subRoot
完全相同,那么 subRoot
当然是 root
的子树,函数返回 true
。root
的左子树和右子树中查找 subRoot
。subRoot
是 root
左子树或右子树的子树,函数就返回 true
。链接:二叉树遍历_牛客题霸_牛客网 (nowcoder.com)
我们需要根据给出的先序(前序)遍历反推出树的样子,例如下图,我们可以动手试一试:
注意:这道题需要写出主函数,并不像力扣提供接口。
首先我需要创建二叉树的结构体和相关函数:
#include
#include
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
BTNode* BuyNode(BTDataType x)
{
BTNode* node=(BTNode*)malloc(sizeof(BTNode));
if(node==NULL){
perror("malloc fail");
return NULL;
}
node->data=x;
node->left=node->right=NULL;
return node;
}
然后进行二叉树的创建:
- 该函数接收两个参数,一个是字符串a,另一个是指向整型变量i的指针,用于记录当前处理到字符串a的哪个位置。
- 当前位置数组元素为 # 表示元素值为空,更新数组索引到下一个位置,返回NULL
- 当前位置元素不为空则为其开辟空间,为树创建新节点,更新数组索引到下一个位置。
- 递归调用CreateTree函数分别创建该节点的左右子树。
- 最后返回该节点的指针。
在main函数中:
- 先定义了一个字符数组a,用于存储输入的字符串,
- 然后调用CreateTree函数创建二叉树,将根节点的指针赋值给root,
- 最后调用InOrder函数对二叉树进行中序遍历,并输出换行符。
BTNode* CreateTree(char* a,int* i)
{
if(a[*i]=='#'){
(*i)++;
return NULL;
}
BTNode* root=BuyNode(a[*i]);
(*i)++;
root->left=CreateTree(a, i);
root->right=CreateTree(a, i);
return root;
}
void InOrder(BTNode* root)
{
if(root==NULL)
return;
InOrder(root->left);
printf("%c ",root->data);
InOrder(root->right);
}
int main() {
char a[1000];
scanf("%s",a);
int i=0;
BTNode* root=CreateTree(a,&i);
InOrder(root);
printf("\n");
return 0;
}
链接:226. 翻转二叉树 - 力扣(LeetCode)
truct TreeNode* invertTree(struct TreeNode* root) {
if(root==NULL)
return NULL;
struct TreeNode* left=invertTree(root->left);
struct TreeNode* right=invertTree(root->right);
root->left=right;
root->right=left;
return root;
}
链接:110. 平衡二叉树 - 力扣(LeetCode)
第一种:求出左右子树高度进行判断比较。
height函数用于计算二叉树的高度,它采用递归的方式计算左右子树的高度,然后返回左右子树高度的较大值加1,表示当前节点的高度。
isBalanced函数则是用于判断二叉树是否平衡,它首先判断当前节点是否为空,如果为空则返回true,否则通过 abs 函数计算左右子树的高度差的绝对值,如果高度差大于1,则返回false,否则递归判断左右子树是否平衡。
int height(struct TreeNode* root){
if(root == NULL)
return 0;
int leftHeight = height(root->left);
int rightHeight = height(root->right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
bool isBalanced(struct TreeNode* root) {
if (root == NULL) {
return true;
}
int leftHeight = height(root->left);
int rightHeight = height(root->right);
if (abs(leftHeight - rightHeight) > 1) {
return false;
}
return isBalanced(root->left) && isBalanced(root->right);
}
第二种与第一种功能方法一样,但这种方式更简洁
同样首先写出求树高度的函数,但这里使用三目运算符使函数更简洁。(fmax返回两个参数中较大的那个。)
int maxDepth(struct TreeNode* root){
return root ? 1 + fmax(maxDepth(root->left) , maxDepth(root->right)) : 0;
}
bool isBalanced(struct TreeNode* root){
if(root == NULL)
return true;
int left = maxDepth(root->left);
int right = maxDepth(root->right);
return abs(left - right) < 2
&& isBalanced(root->left)
&& isBalanced(root->right);
}