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 .
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 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 *** All Not 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 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
The pointer to the subscript passed in outside
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
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
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.
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 ;
}