In-order traversal of a binary tree

recursive traversal

Here to help you determine the three elements of the recursive algorithm. Every time you write recursion, write according to these three elements, which can ensure that everyone writes the correct recursive algorithm!

  1. Determine the parameters and return values ​​of the recursive function: Determine which parameters need to be processed during the recursion process, then add this parameter to the recursive function, and also specify what the return value of each recursion is to determine the return type of the recursive function .
  2. Determine the termination condition: After writing the recursive algorithm, when it is running, it often encounters a stack overflow error, that is, the termination condition is not written or the termination condition is written incorrectly. The operating system also uses a stack structure to save the information of each layer of recursion , if the recursion is not terminated, the operating system's memory stack will inevitably overflow.
  3. Determine the logic of single-level recursion: Determine the information that needs to be processed for each level of recursion. Here, the process of calling itself repeatedly to achieve recursion will also be repeated.

preorder traversal

class Solution {
    
    
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
    
    
        if (cur == NULL) return;
        vec.push_back(cur->val);    // 中
        traversal(cur->left, vec);  // 左
        traversal(cur->right, vec); // 右
    }
    vector<int> preorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

Inorder traversal

class Solution {
    
    
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
    
    
         if (cur == NULL) return;
	     traversal(cur->left, vec);  // 左
	     vec.push_back(cur->val);    // 中
	     traversal(cur->right, vec); // 右
    }
    vector<int> postorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

post order traversal

class Solution {
    
    
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
    
    
         if (cur == NULL) return;
   		 traversal(cur->left, vec);  // 左
  	     traversal(cur->right, vec); // 右
         vec.push_back(cur->val);    // 中
    }
    vector<int> postorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

sequence traversal

class Solution {
    
    
public:
    void order(TreeNode* cur, vector<vector<int>>& result, int depth)
    {
    
    
        if (cur == nullptr) return;
        if (result.size() == depth) result.push_back(vector<int>());
        result[depth].push_back(cur->val);
        order(cur->left, result, depth + 1);
        order(cur->right, result, depth + 1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
    
    
        vector<vector<int>> result;
        int depth = 0;
        order(root, result, depth);
        return result;
    }
};

iterate through

The implementation of recursion is: each recursive call will push the local variables, parameter values ​​and return address of the function into the call stack, and then when the recursion returns, the parameters of the previous recursion will be popped from the top of the stack, so this is recursion The reason why it is possible to return to the previous position.

At this time, everyone should know that we can also use the stack to realize the front-to-back and in-order traversal of the binary tree.

Preorder traversal (iteration)

The pre-order traversal is middle and left, and each time the middle node is processed first, then the root node is put into the stack first, then the right child is added to the stack, and then the left child is added.

lass Solution {
    
    
public:
    vector<int> preorderTraversal(TreeNode* root) {
    
    
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
    
    
            TreeNode* node = st.top();                     // 中
            st.pop();
            result.push_back(node->val);
            if (node->right) st.push(node->right);         // 右(空节点不入栈)
            if (node->left) st.push(node->left);           // 左(空节点不入栈)
        }
        return result;
    }

Inorder traversal

The in-order traversal is left, middle and right. First, the node at the top of the binary tree is accessed, and then it is accessed layer by layer until it reaches the bottom of the left side of the tree, and then starts to process the node (that is, put the value of the node into the result array ), which causes the processing order and access order to be inconsistent.

Then, when using the iterative method to write in-order traversal, it is necessary to borrow pointer traversal to help access nodes, and the stack is used to process elements on nodes .

class Solution {
    
    
public:
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != NULL || !st.empty()) {
    
    
            if (cur != NULL) {
    
     // 指针来访问节点,访问到最底层
                st.push(cur); // 将访问的节点放进栈
                cur = cur->left;                // 左
            } else {
    
    
                cur = st.top();
                 // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
                st.pop();
                result.push_back(cur->val);     // 中
                cur = cur->right;               // 右
            }
        }
        return result;
    }
};

post order traversal

Let’s look at the post-order traversal again. The pre-order traversal is in the left and right, and the subsequent traversal is in the left and right. Then we only need to adjust the code order of the pre-order traversal to become the traversal order of the middle, right and left, and then reverse the result array and output The result sequence is right and left, as shown in the figure below:
insert image description here

So the post-order traversal only needs to modify the code of the pre-order traversal slightly, the code is as follows:

class Solution {
    
    
public:
    vector<int> postorderTraversal(TreeNode* root) {
    
    
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
    
    
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->left) st.push(node->left); 
            // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
            if (node->right) st.push(node->right); // 空节点不入栈
        }
        reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了
        return result;
    }
};

sequence traversal

It is necessary to borrow an auxiliary data structure, that is, a queue. The queue is first-in-first-out, which conforms to the logic of layer-by-layer traversal. Instead, using the stack first-in-last-out is suitable for simulating the logic of depth-first traversal, which is recursion.

And this layer-order traversal method is the breadth-first traversal in graph theory, but we apply it to the binary tree.

class Solution {
    
    
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
    
    
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {
    
    
            int size = que.size();
            vector<int> vec;
        // 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
            for (int i = 0; i < size; i++) {
    
    
                TreeNode* node = que.front();
                que.pop();
                vec.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(vec);
        }
        return result;
    }
};

Guess you like

Origin blog.csdn.net/weixin_54792212/article/details/125356542