[C Exercises] Binary Tree Classic Exercises

foreword

  • Binary trees are recursive
  • Therefore, when we do the questions, we have to think in the general direction of recursion .

1. Traverse

1. Preorder traversal

link link

  • First traverse the root, then traverse the left subtree, and finally traverse the right subtree
  • The key to this question: pass in the address of i, not a temporary copy of i
  • Reason: Each layer of i needs to create a stack frame , so the value of i after recursion, each layer is an independent i, and will not affect each other .
//求二叉树的size相当于根节点+左子树的节点总数+右子树的节点总数
int BTSize(struct TreeNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        return 0;
    }
    return BTSize(root->right) + BTSize(root->left) + 1;
}
void BTPreOrder(struct TreeNode*root,int*arr,int*pi)
{
    
    
    if (root == NULL)
    {
    
    

        return;
    }
    arr[*pi]=root->val;
    (*pi)++;//*与++的优先级相同,但是运算顺序是从右向左的!
    BTPreOrder(root->left,arr,pi);
    BTPreOrder(root->right,arr,pi);

}
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
    
    
    *returnSize =BTSize(root);

    int *arr=(int*)malloc(sizeof(int)*(*returnSize));


    if(arr==NULL)
    {
    
    
        perror("malloc fail");
        exit(-1);
    }
    int i = 0;
    BTPreOrder(root,arr,&i);
    return arr;
}

2. Inorder traversal

link link

  • First traverse the left subtree, then traverse the heel, and finally traverse the right subtree
  • key: ditto

int BTSize(struct TreeNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        return 0;
    }
    return BTSize(root->right) + BTSize(root->left) + 1;
}
void BTInOrder(struct TreeNode* root,int* i,int *arr)
{
    
    
    if (root == NULL)
    {
    
    
        return;
    }
    BTInOrder(root->left,i,arr);
    arr[*i] = root->val;
    (*i)++;
    BTInOrder(root->right,i,arr);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize)
{
    
    
    *returnSize = BTSize(root);
    int *arr=(int *)malloc(sizeof(int)*(*returnSize));
    int i = 0;
    BTInOrder(root,&i,arr);
    return arr;
}

3. Post-order traversal

link link

  • First traverse the left subtree, then traverse the right subtree, and finally traverse the root
  • key: ditto
int BTSize(struct TreeNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        return 0;
    }
    return BTSize(root->right) + BTSize(root->left) + 1;
}
void BTPostOrder(struct TreeNode* root,int*i,int* arr)
{
    
    
    if (root == NULL)
    {
    
    
        return;
    }

    BTPostOrder(root->left,i,arr);
    BTPostOrder(root->right,i,arr);
    arr[*i]=root->val;
    (*i)++;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
    
    
    *returnSize=BTSize(root);
    int *arr=(int*)malloc((*returnSize)*sizeof(int));
    if(arr==NULL)
    {
    
    
        perror("malloc fail");
        exit(-1);
    }
    int i = 0;
    BTPostOrder(root,&i,arr);
    return arr;
}

4. Layer order traversal

  • With column first-in-first-out structure
  • The root node pushes its left and right children onto the stack
  • Until the end of the column is empty !
typedef  struct BTNode* QLNDateType;//typedef不能对已封装的类型再次封装
//节点
typedef struct QListNode
{
    
    
	QLNDateType val;
	struct QListNode* next;
}QListNode;

typedef struct Queue
{
    
    
	QListNode* Top;
	QListNode* Tail;
}Queue;
void QueuePushBack(Queue* q,QLNDateType x)
{
    
    
	QListNode* NewNode = (QListNode*)malloc(sizeof(QListNode));
	if (NewNode == NULL)
	{
    
    
		perror("malloc fail");
		exit(-1);
	}
	NewNode->next = NULL;
	NewNode->val = x;
	if (q->Top == NULL)
	{
    
    
		q->Tail = NewNode;
		q->Top = NewNode;
		return;
	}
	else
	{
    
    
		q->Tail->next = NewNode;
		q->Tail = NewNode;
	}
}
int QueueEmpty(Queue q)
{
    
    
	return q.Top == NULL;
}
void QueueDestory(Queue* q)
{
    
    
	QListNode* cur = q->Top;
	q->Top = NULL;
	q->Tail = NULL;
	while (cur)
	{
    
    
		QListNode* next = cur->next;
		free(cur);
		cur = next;
	}
}
//到这才是关键
void BTLevelOrder(BTNode* root)
{
    
    
    Queue qlist;
    QueueInit(&qlist);
    if (root != NULL)
    {
    
    
        QueuePushBack(&qlist, root);
    }
    while (!QueueEmpty(qlist))
    {
    
    
        BTNode* front = QueueTop(qlist);
        QueuePopFront(&qlist);
        if (front != NULL)
        {
    
    
            printf("%d ", front->val);
            QueuePushBack(&qlist, front->left);
            QueuePushBack(&qlist, front->right);
        }
    }
    QueueDestory(&qlist);
}

Two. Improve

1. Single-valued binary tree

link link

  • Compare the root node with the left and right nodes
  • Note: What we want is the result!
  • Therefore: when the value of the right node is not equal to the value of the root node, it returns false! The left node is the same!
  • If the node is empty, it means: the left and right subtrees are the same as the root node, or there is only one node (subject condition).
bool isUnivalTree(struct TreeNode* root)
{
    
    
    if(root==NULL)
    {
    
    
        return true;
    }
    if(root->left!=NULL&&root->val!=root->left->val)
    {
    
    
        return false;
    }
    if(root->right!=NULL&&root->val!=root->right->val)
    {
    
    
        return false;
    }
    return isUnivalTree(root->left)&&isUnivalTree(root->right);
}

2. Binary tree flipping

link link

  • Recursive idea: flipping a tree is equivalent to flipping its left and right subtrees
struct TreeNode* invertTree(struct TreeNode* root)
{
    
    
    if(root==NULL)
    {
    
    
        return NULL;
    }
    invertTree(root->left);
    invertTree(root->right);
    struct TreeNode*tmp = root->right;
    root->right = root->left;
    root->left = tmp;
    return root;
}

3. Judging that the binary tree is the same

link link

  • Judging whether the binary tree is the same depends on whether the left subtree and the right subtree are the same
  • Note: What we want is the result!
  • Therefore: when the values ​​​​of the left and right nodes are different, we can return false
  • Note: If both are empty, it means true, if one is empty, it means false, and if neither is empty, it means it needs to be judged
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);
}

4. Judging the symmetry of the binary tree

link link

  • Idea: Binary tree symmetry only needs to judge whether the left subtree of one tree is the same as the right subtree of another tree and whether the right subtree and left subtree of a tree are the same
  • Note: What we want is the result!
  • Therefore: when the values ​​​​of the left and right nodes are different, we can return false
 bool is_same_tree(struct TreeNode* root1,struct TreeNode* root2)
{
    
    
	if (root1 == NULL && root2 == NULL)
	{
    
    
		return true;
	}
	if (root1 == NULL || root2 == NULL)
	{
    
    
		return false;
	}
	if (root1->val != root2->val)
	{
    
    
		return false;
	}
	return is_same_tree(root1->left, root2->right) &&
		   is_same_tree(root1->right, root2->left);
}
bool isSymmetric(struct TreeNode* root)
{
    
    
    return is_same_tree(root->left,root->right);
}

5. A subtree of another tree

link link

  • Idea: First compare whether the whole tree is the same, then compare whether the left subtree is the same, and finally compare whether the right subtree is the same , if they are the same, return true , if ***AllNot the same return false! *
bool is_same_tree(struct TreeNode* root1,struct TreeNode* root2)
{
    
    
	if (root1 == NULL && root2 == NULL)
	{
    
    
		return true;
	}
	if (root1 == NULL || root2 == NULL)
	{
    
    
		return false;
	}
	if (root1->val != root2->val)
	{
    
    
		return false;
	}
	return is_same_tree(root1->right, root2->right) && 
	       is_same_tree(root1->left, root2->left);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
    
    
    if(root==NULL)
    {
    
    
        return false;
    }
    bool ret = is_same_tree(root,subRoot);
    if(ret)
      return true;

    bool left = isSubtree(root->left,subRoot);
    if(left)
      return true;
    bool right = isSubtree(root->right,subRoot);
    if (right)
       return true;

       return false;
}

5. Judging the complete binary tree

  • With the help of the idea of ​​layer order traversal, when it is empty, if there is a non-empty one behind, it is not a complete binary tree, otherwise it is a complete binary tree.
typedef  struct BTNode* QLNDateType;//typedef不能对已封装的类型再次封装
//节点
typedef struct QListNode
{
    
    
	QLNDateType val;
	struct QListNode* next;
}QListNode;

typedef struct Queue
{
    
    
	QListNode* Top;
	QListNode* Tail;
}Queue;
void QueuePushBack(Queue* q,QLNDateType x)
{
    
    
	QListNode* NewNode = (QListNode*)malloc(sizeof(QListNode));
	if (NewNode == NULL)
	{
    
    
		perror("malloc fail");
		exit(-1);
	}
	NewNode->next = NULL;
	NewNode->val = x;
	if (q->Top == NULL)
	{
    
    
		q->Tail = NewNode;
		q->Top = NewNode;
		return;
	}
	else
	{
    
    
		q->Tail->next = NewNode;
		q->Tail = NewNode;
	}
}
int QueueEmpty(Queue q)
{
    
    
	return q.Top == NULL;
}
void QueueDestory(Queue* q)
{
    
    
	QListNode* cur = q->Top;
	q->Top = NULL;
	q->Tail = NULL;
	while (cur)
	{
    
    
		QListNode* next = cur->next;
		free(cur);
		cur = next;
	}
}
//关键代码
bool BinaryTreeComplete(BTNode* root)
{
    
    

    Queue qlist;
    QueueInit(&qlist);
    if (root != NULL)
    {
    
    
        QueuePushBack(&qlist, root);
    }
    while (!QueueEmpty(qlist))
    {
    
    
        BTNode* front = QueueTop(qlist);
        QueuePopFront(&qlist);
        if (front != NULL)
        {
    
    
            QueuePushBack(&qlist, front->left);
            QueuePushBack(&qlist, front->right);
        }
        else
        {
    
    
            break;
        }
    }
    while (!QueueEmpty(qlist))
    {
    
    
        BTNode* front = QueueTop(qlist);
        QueuePopFront(&qlist);
        if (front != NULL)
        {
    
    
            QueueDestory(&qlist);
            return false;
        }
    }
    QueueDestory(&qlist);
    return true;
}

6. Construction and traversal of binary tree

Niu Ke link

  • Create a binary tree from an array
  1. The pointer to the subscript passed in outside
  2. When # is recognized, the node of the binary tree is set to be empty, but the array needs to be recognized later, and the subscript should be increased by 1 at this time
  3. There is no need to consider whether the array has been read, because the elements of the array are just enough to build a binary tree
  4. The left node pointer of the root is equal to the return value after the node created by its subtree, and the right node is the same.
  5. Returns the created root node (also the return value of 4)
  • Inorder traversal of a binary tree
    Idea: see above
#include <stdio.h>
#include<stdlib.h>
typedef char BTNodeDataType;
typedef struct BTNode
{
    
    
    BTNodeDataType val;
    struct BTNode* left;
    struct BTNode* right;
}BTNode;
BTNode* BTCreat(BTNodeDataType* a, int* pi)
{
    
    
    if (a[*pi] == '#')
    {
    
    
        (*pi)++;
        return NULL;
    }
    BTNode* NewNode = (BTNode*)malloc(sizeof(BTNode));
    if (NewNode == NULL)
    {
    
    
        perror("malloc fail");
        exit(-1);
    }
    NewNode->val = a[(*pi)++];
    NewNode->left = BTCreat(a, pi);
    NewNode->right = BTCreat(a,  pi);
    return NewNode;
}
void BTInOrder(BTNode* root)
{
    
    
    if (root == NULL)
    {
    
    
        return;
    }
    BTInOrder(root->left);
    printf("%c ", root->val);
    BTInOrder(root->right);
}
int main() 
{
    
    
    char arr[150]={
    
    0};
    scanf("%s",arr);
    int i = 0;
    BTNode*root = BTCreat(arr,&i);
    BTInOrder(root);
    return 0;
}

7. The maximum depth of the binary tree

link link

  • Maximum depth: the greater value of the depth of the left subtree and the depth of the right subtree, plus the height of the root node 1.
  • Details: The depth of the left subtree and the value of the depth of the right subtree should be preserved, so that recursion can be reduced many times!
int maxDepth(struct TreeNode* root)
{
    
    
    if(root==NULL)
    {
    
    
        return 0;
    }
    int left = maxDepth(root->left);
    int right = maxDepth(root->right);
    return left > right? left+1:right+1;
}

Guess you like

Origin blog.csdn.net/Shun_Hua/article/details/129954071