Non recursive tree traversal

The code connects the code in the BST tree and can be put together to run tests

Non recursive preamble:

The basic idea of root traversal is to output itself, left subtree and right subtree.

Starting from the root node, output and stack to the left in turn. When the left child is empty, the pointer points to the right subtree at the top of the stack, and then exits the stack to traverse the right subtree.

void pre_output_stack(node* root)
{
    stack<node*> s;
    node* p = root;
    
    while (p  || !s.empty())
    {
        while (p)               //First output, then stack, all the way to the left
        {
            cout << p->data;
            s.push(p);
            p = p->lch;
        }                       //From the root node, the leftmost node
        if (!s.empty())         //Traverse the right subtree of the leftmost node, and the leftmost node is outbound
        {
            p = s.top();
            s.pop();
            p = p->rch;
        }
    }
}

Middle order traversal: first left subtree, right subtree.

Understand the middle root traversal, first root traversal is easy to understand, starting from the root node to the left, once out of the stack to save, to the left most node, record the top of the stack t, out of the stack output t, traverse the right subtree.

void mid_output_stack(node* root)
{
    stack<node*> s;
    node *p = root;
    
    while (p || !s.empty())
    {
        while (p)
        {
            s.push(p);
            p = p->lch;
        }
        if (!s.empty())
        {
            p = s.top();
            s.pop();
            cout << p->data;
            p = p->rch;
        }
    }
}

Post order traversal: first traverse left and right subtrees, and then output itself.

First of all, we should pay attention to the rule that if the right child of a node is not empty, then the right child must be output first, followed by the node.

So after traversing the left subtree, you can directly see the right child of the node. If it is empty, you can directly output it. If it is not empty, you need to see whether the right subtree outputs itself (if there is no output, you need to continue traversing). If the previous output node is the root node of the right subtree, then you can directly output it after traversing the right subtree.

Therefore, compared with the former, the middle and the latter, we need a precursor node to mark the output node.

void post_output_stack(node* root)
    node* p = root;
    stack<node*> s;
    node* prev = NULL;
    while (p || !s.empty())
    {
        while (p)  //Traverse left
        {
            s.push(p);
            p = p->lch;
        }
        if (s.top()->rch == NULL || s.top()->rch == prev)  //If the right child is empty or traversed, output and stack
        {
            cout << s.top()->data;
            prev = s.top();
            s.pop();
        }
        else  //Traverse the right child without traversing
        {
            p = s.top()->rch;
        }
    }
}

 

Posted by unkwntech on Sat, 21 Dec 2019 12:15:59 -0800