[Data structure and algorithm] Easy to understand binary tree traversal

In the easy-to-understand explanation of binary search trees (please poke me), the article mainly introduces the nature of binary search trees. This article will continue to introduce the traversal of binary trees.

Traversal of binary search tree

Traversing all nodes of the tree is to visit only once. According to the position of the root node, it is mainly divided into pre-order traversal, middle-order traversal, and post-order traversal. Note that the traversal of the binary search tree and the ordinary binary tree is exactly the same, so in the following, it is not distinguished whether it is a binary search tree or a binary tree.

Preorder traversal

The preorder traversal operation of a binary tree is as follows:

  • Visit the root node
  • Preorder traverse the left subtree
  • Preorder traverse the right subtree

For example, in the following figure, the preorder traversal node access order of the binary tree is 3 1 2 5 4 6:
[Data structure and algorithm] Easy to understand binary tree traversal
According to the operation steps of preorder traversal analyzed above, it is not difficult to see that it is easy to implement the preorder access of the binary tree by recursive method:

//前序遍历递归版本
void preOrder(struct node *root)
{
    if(root != NULL)
    {
        cout << root->data << " ";
        preOrder(root->left);
        preOrder(root->right);
    }
}

In fact, the preorder traversal of the binary tree can also be implemented in a non-recursive manner: since the root node has to be retrieved after traversing the root node in order to traverse the right subtree corresponding to the root node, you can consider using the stack to store the visited The root node of the code implementation is as follows:

//前序遍历的非递归版本
void preOrder(struct node *root)  
{  
    stack<struct node *> s;  
    while (root != NULL || !s.empty()) 
    {  
        if (root != NULL) 
        {  
        //访问结点并入栈
            cout << root->data << " ";   
            s.push(root);                
            root = root->left; //访问左子树  
       } 
       else 
       {  
            root = s.top();  //回溯至父亲结点  
            s.pop();  
            root = root->right; //访问右子树  
       }  
    }  
    cout << endl;  
}  

In-order traversal

The middle order traversal operation of a binary tree is as follows:

  • Middle-order traversal of the left subtree
  • Visit the root node
  • In-order traversal of right subtree

For example, in the following figure, the access order of the nodes in the binary tree traversal is 1 2 3 4 5 6:
[Data structure and algorithm] Easy to understand binary tree traversal

Like the preorder traversal, it can also be implemented in a recursive or non-recursive way, and the idea is similar, except that the order of access is different. The two implementations are as follows:

//中序遍历递归版本
void inOrder(struct node *root)
{
    if(root != NULL)
    {
        inOrder(root->left);
    //和前序遍历相比,只是输出语句换了个位置唯一
    cout << root->data << " ";
        inOrder(root->right);
    }
}
//中序遍历的非递归版本
void inOrder(struct node *root)  
{  
    stack<struct node *> s;  
    while (root != NULL || !s.empty()) 
    {  
        if (root != NULL) 
        {  
            s.push(root);  
            root = root->left;  
        }  
        else 
        {  
        //访问完左子树后才访问根结点  
            root = s.top();  
            cout << root->data << " ";  
            s.pop();  
            root = root->right; //访问右子树  
        }  
    }  
    cout << endl;  
}  

Subsequent traversal

The post-order traversal operation of a binary tree is as follows:

  • Post-order traversal of the left subtree
  • Post-order traversal of the right subtree
  • Visit the root node

For example, in the following figure, the post-order traversal node access order of the binary tree is 2 1 4 6 5 3: The
[Data structure and algorithm] Easy to understand binary tree traversal
recursive version of the post-order traversal of the binary tree is similar to the pre-order middle order, as follows:

//后序遍历递归版本
void postOrder(struct node *root)
{
    if(root != NULL)
    {
        postOrder(root->left);
        postOrder(root->right);

        //最后访问根节点
        cout << root->data << " ";
    }
}

The non-recursive algorithm of post-order traversal is more complicated and can be implemented using one stack, but the process is very cumbersome. We can consider using two stacks to implement the non-recursive algorithm of post-order traversal. Note that the post-order traversal can be regarded as the inverse process of the following traversal: that is, first traverse a certain node, then traverse its right child, and then traverse its left child. The reverse of this process is post-order traversal. The algorithm steps are as follows:

(1) Push the root node to the first stack s.
(2) Pop a node from the stack s and push it to the stack output.
(3) Then push the left child and the right child of the node to the first stack s.
(4) Repeat procedures 2 and 3 until the stack s is empty.
(5) Now all nodes have been pushed to the stack output, and stored in the order of post-order traversal, and pop out directly is the result of post-order traversal of the binary tree.

The code is implemented as follows:

//后序遍历的非递归版本
void postOrder(struct node *root)  
{  
    if (!root) return;  
    stack<struct node*> s, output;  
    s.push(root);  
    while (!s.empty()) 
    {  
        struct node *curr = s.top();  
        output.push(curr);  
        s.pop();  
        if (curr->left)  
            s.push(curr->left);  
        if (curr->right)  
            s.push(curr->right);  
    }  

    while (!output.empty()) 
    {  
        cout << output.top()->data << " ";  
        output.pop();  
    }  
    cout << endl;  
}  

Recommended reading:

[Welfare] Video sharing of online boutique courses collected by myself (
Part 1 ) [System design] LRU cache
[Data structure and algorithm] Easy to understand linked list
[Data structure and algorithm] Easy to understand bit sorting
[C++ Notes] C++ 11 Concurrent Programming (1) Start the thread journey
[C++ Notes] Common pitfalls in using C/C++ pointers
[C++ Notes] Detailed explanation of static and dynamic libraries (on)

Focus on server background technology stack knowledge summary sharing

Welcome to pay attention to communication and common progress

[Data structure and algorithm] Easy to understand binary tree traversal

Coding

The code farmer has the right way to provide you with easy-to-understand technical articles to make technology easier!

Guess you like

Origin blog.51cto.com/15006953/2552022