【Data Structure】Classic Exercises of Binary Tree

965. Single-valued binary tree

Ideas:

1. If the tree is empty, return true because the rules are not violated.

2. Compare the value of the root node and the right subtree of the left subtree, and return false if they are not equal.

3. Pre-order traversal can be implemented recursively, that is, the left subtree is compared with the right subtree, and they must be equal.

 

bool isUnivalTree(struct TreeNode* root){
    //先序遍历
    if(root == NULL)
        return true;
        //判断==并没有多大的用处,判断相反可快速结束递归。
    if(root->left && root->val != root->left->val)//1.判断节点是否存在,2.判断值是否不相等。
        return false;
    if(root->right && root->val != root->right->val)
        return false;
    return isUnivalTree(root->left) && isUnivalTree(root->right);//左树 右树都得同时满足才可返回真

}

100. The same tree

The comparison between two trees is to see whether the corresponding nodes exist and are equal.

Ideas: 1. If both trees are empty, return true.

2. If the corresponding nodes of the two trees are missing, return false

3. Recursion, preorder traversal can be done.

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);

}

Symmetric binary tree

Minor changes have been made based on comparing whether the two trees are equal.

Here, we only need to compare the root left subtree and the root right subtree below the root node.

Attention should be paid to the comparison: because it is mirror symmetry, the left subtree of the left tree and the right subtree of the right tree are compared;

The right subtree of the left tree is compared to the left subtree of the right subtree.

Just call the code for the same tree ,

 

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->right) && _isSameTree(p->right,q->left);

}

bool isSymmetric(struct TreeNode* root){
    //为空树
    if(root == NULL)
        return true;
    //调用相同树的代码
    return _isSameTree(root->left,root->right);

}

Preorder traversal of binary tree

Review: Preorder Traversal: Root - Left Subtree - Right Subtree

In short, it is still the idea of ​​recursive divide and conquer, but this question is a bit different.

For this problem, you need to apply for an array space to store data. Using a static array will be destroyed when the function goes out of scope due to the function stack frame, and the returned value may not exist at all. And the static local variables modified by static are called multiple times, and the problem of data coverage will occur. The optimal solution is: open up space on the heap, how much space is open?

We can traverse the binary tree first to obtain the number of nodes in the binary tree. The corresponding code and ideas have been mentioned in previous blogs.

Ideas: 1. The idea of ​​pre-order traversal

2. Recursively find the number of nodes.

2. Dynamically open up the array.

 

 int BTreeSize(struct TreeNode* root)
{
    return root == NULL? 0:BTreeSize(root->left)+BTreeSize(root->right)+1;
}
void _preorder(struct TreeNode* root,int* a,int* pi)
{
    if(root == NULL)
        return ;
    a[(*pi)++] = root->val;

    _preorder(root->left,a,pi);
    _preorder(root->right,a,pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
    //确定树的大小
    *returnSize = BTreeSize(root);
    int* a = (int*)malloc(sizeof(int)*(*returnSize));

    int i =0;
    _preorder(root,a,&i);
    return a;
}

Postorder Traversal of Binary Tree

Post-order traversal: left subtree - right subtree - root

The idea is consistent with the preorder traversal above

 

int BTreeSize(struct TreeNode* root)
{
    return root == NULL? 0:BTreeSize(root->left)+BTreeSize(root->right)+1;
}
void _preorder(struct TreeNode* root,int* a,int* pi)
{
    if(root == NULL)
        return ;

    _preorder(root->left,a,pi);
    _preorder(root->right,a,pi);
    a[(*pi)++] = root->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize = BTreeSize(root);
    int* a = (int*)malloc(sizeof(int)*(*returnSize));

    int i =0;
    _preorder(root,a,&i);
    return a;

}

Inorder traversal of binary tree

int BTreeSize(struct TreeNode* root)
{
    return root == NULL? 0:BTreeSize(root->left)+BTreeSize(root->right)+1;
}
void _preorder(struct TreeNode* root,int* a,int* pi)
{
    if(root == NULL)
        return ;

    _preorder(root->left,a,pi);
    a[(*pi)++] = root->val;
    _preorder(root->right,a,pi);
    
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize = BTreeSize(root);
    int* a = (int*)malloc(sizeof(int)*(*returnSize));

    int i =0;
    _preorder(root,a,&i);
    return a;
}

subtree of another tree

In essence, it is a problem of finding subtrees. When the structure and value of a small tree of the big tree and the given small tree are exactly equal , return true

Consider calling the function code to judge whether two numbers are the same, adopt the idea of ​​divide and conquer, run the left subtree to search first, then run the right subtree to search, if found during the period, return true directly .

Mainly the idea of ​​branching.

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 && subRoot == NULL)
        return true;
    if(root == NULL || subRoot == NULL)
        return false;
    //判断其是否为相同的树,找完左树找右树
    return _isSameTree(root,subRoot) || isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
}

Binary tree traversal

Ideas: 1) Build trees, recursively divide and conquer trees.

2) When passing parameters, it is necessary to pass pointers, call by value, and pass formal parameters. The change of formal parameters will not affect the actual parameters, so an error will occur during recursion.

3) In-order traversal, left subtree - root - right subtree

#include<stdio.h>
#include<stdlib.h>
typedef struct BTreeNode
{
    char data;
    struct BTreeNode* left;
    struct BTreeNode* right;
}BTNode;
BTNode* CreatTree(char *a, int *pi)//这里必须传递指针 pi
{
    //递归方式创建树,那么就必须传址调用,而不是传值调用。
    //如果是‘#’就返回NULL,同时找数组下一位
    if(a[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }
    //创建树
    BTNode* root = (BTNode*)malloc(sizeof(BTNode));
    root->data = a[(*pi)++];
    root->left = CreatTree(a, pi);
    root->right = CreatTree(a, pi);
    return root;
}
void InOrder(BTNode* root)
{
    if(root == NULL)
        return;
    InOrder(root->left);
    printf("%c ",root->data);
    InOrder(root->right);
}
int main()
{
    char a[100];
    scanf("%s",a);
    //创建树
    int i = 0;
    BTNode* Tree = CreatTree(a,&i);
    InOrder(Tree);
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_61932507/article/details/124229341