Binary tree pre, middle and post order traversal, iteration and Morris writing records

Posted by PHPnewby! on Tue, 04 Jan 2022 06:35:53 +0100

Binary tree pre, middle and post order traversal, iteration and Morris records

Preorder traversal of binary tree

iteration

class Solution {
public:
   vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if (!root) return res;
        stack<TreeNode *> stk;
        while (root || !stk.empty()) {
            while (root) {
                res.emplace_back(root->val);
                stk.emplace(root);
                root = root->left;
            }
            root = stk.top();
            stk.pop();
            root = root->right;
        }
        return res;
    }
};

Using the stack, if the root is not empty and the stack is not empty, cycle repeatedly
First, traverse the left node of root, push the value of root into the result in each cycle, and press root into the stack for subsequent extraction to obtain the right node

morris

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if (!root) return res;
        TreeNode *predecessor = nullptr;
        while (root) {
            predecessor = root->left;
            if (predecessor) {
                while (predecessor->right && predecessor->right != root) {
                    predecessor = predecessor->right;
                }
                if (!predecessor->right) {
                    res.emplace_back(root->val);
                    predecessor->right = root;
                    root = root->left;
                    continue;
                } else {
                    predecessor->right = nullptr;
                }
            } else {
                res.emplace_back(root->val);
            }
            root = root->right;
        }
        return res;
    }
};

morris is a little more complicated,
This algorithm requires a temporary node, and the overall loop is performed with root not null
If the root is not null, the node needs to be left first (i.e. = root - > left). If the left bit is not, it will directly push the value of root into the result and let root = root - > right
If yes, the temporary node will be moved to the rightmost first, and the rightmost right will be null. For the first time, the rightmost right will be the position of root at this time, and then move root to the left once. Because it is a pre sequence traversal, the first thing is to push the root value into the result list in advance. If the rightmost right = = root in the next traversal, the temporary node will be null, and root will move to the right node at this time.

Order traversal in binary tree

iteration

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode *> stk;
        while (root || !stk.empty()) {
            while (root) {
                stk.push(root);
                root = root->left;
            }
            root = stk.top();
            stk.pop();
            res.push_back(root->val);
            root = root->right;
        }
        return res;
    }
};

In the second cycle, the root traverses the left node, does not put the result in the list, but first into the stack, and finally traverses FILO top first out of the stack. It indicates that the leftmost node pushes the result first, and then puts root = root - > right

morris

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        TreeNode* predecessor = nullptr;
        while (root != nullptr) {
            if (root->left != nullptr) {
                predecessor = root->left;
                while (predecessor->right != nullptr && predecessor->right != root) {
                    predecessor = predecessor->right;
                }
                if (predecessor->right == nullptr) {
                    predecessor->right = root;
                    root = root->left;
                } else {
                    res.push_back(root->val);
                    predecessor->right = nullptr;
                    root = root->right;
                }
            } else {
                res.push_back(root->val);
                root = root->right;
            }
        }
        return res;
    }
};

Compared with the previous sequence, morris does not push the results into the result list first after the rightmost, but moves this step to push the value of root into the list if there is root on the rightmost right of the temporary node

Postorder traversal of binary tree

iteration

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if (!root) return res;
        stack<TreeNode *> stk;
        TreeNode *prev = nullptr;
        while (root || !stk.empty()) {
            while (root) {
                stk.emplace(root);
                root = root->left;
            }
            root = stk.top();
            stk.pop();
            if (!root->right || root->right == prev) {
                res.emplace_back(root->val);
                prev = root;
                root = nullptr;
            } else {
                stk.emplace(root);
                root = root->right;
            }
        }
        return res;
    }
};

The iteration of the subsequent sequence is quite different. It needs a front node to store the root pushed into the list last time. When the right node of the root in this cycle is empty or not the front node, it will be pushed into the result list. Otherwise, it will be pushed back to the stack and move the root to the right node.

morris

class Solution {
public:
    void addPath(vector<int> &vec, TreeNode *node) {
        int count = 0;
        while (node) {
            ++count;
            vec.emplace_back(node->val);
            node = node->right;
        }
        reverse(vec.end() - count, vec.end());
    }

    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if (!root) return res;
        TreeNode *p1 = root, *p2 = nullptr;
        while (p1) {
            p2 = p1->left;
            if (p2) {
                while (p2->right && p2->right != p1) {
                    p2 = p2->right;
                }
                if (!p2->right) {
                    p2->right = p1;
                    p1 = p1->left;
                    continue;
                } else {
                    p2->right = nullptr;
                    addPath(res, p1->left);
                }
            }
            p1 = p1->right;
        }
        addPath(res, root);
        return res;
    }
};

The morris of the post order is the most complex. The post order needs the leftmost and the right of the same level of the left (if the right has no children).
First prepare a temporary node according to morris's old process. The temporary node first moves left and then right to the last, and the last right node is the main node. Then the main node moves left to do the same operation until there is a node on the left of the main node. At this time, the temporary node has connected the left node and the right node of the master node to the master node
At this time, the temporary node will remove the connection of the right node. Although the primary node is pushed into the list, the operation at the bottom left is relatively easy to understand, mainly the right node at the same level of the subsequent left node.
At this time, after the leftmost node is pushed, the master node will come to the right node of the same level. Obviously, the left child node of the master node is empty, so the master node will continue to move to the right, and the moving position is the master node set by the previous temporary node. At this time, after the same operation, The temporary node removes the connection with the master node, pushes the point previously used as the master node into the list as the left child node of the current master node, and pushes all its right child nodes, but the traversal order is wrong. Therefore, it is also necessary to flip the order of all the nodes just pushed, which is the operation of the above code addPath
This method will not push the root node, so you need to push the root node before returning

Topics: C++ Algorithm Binary tree