Restore binary tree according to pre-order middle-order

First order traversal: root —> left —> right

In-order traversal: left —> root —> right

Post-order traversal: left —> right —> root

Algorithm idea:
  1. According to the characteristics of pre-order traversal, the first traversed node is the root node, we find the root node

  2. According to the characteristics of in-order traversal, we know that the sequence on the left of the root node is the left subtree, and the sequence on the right of the root node is the right subtree

  3. According to the original pre-order and middle-order traversal results, the pre-order and middle-order traversal results of the left and right subtrees are obtained, and the binary tree is recursively restored

Construct the traversal result of the subtree according to the traversal result:
  • Post-order traversal: [[Left sub-tree post-order traversal result], [Right sub-tree post-order traversal result], root node]
  • Middle-order traversal: [[Left subtree middle-order traversal result], root node, [Right subtree middle-order traversal result]]
For example:

preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]

First, we know that node 3 is the root node of the entire tree according to preorder, and then according to the inorder sequence, we know that the sequence [9] on the left of 3 is the left subtree, and the sequence [15,20,7] on the right is the right subtree. Like this,
Insert picture description here
next we construct the pre-order and middle-order traversal sequences of the left and right subtrees:

left_preorder = [9]
right_preorder = [20,15,7]

left_inorder = [9]
right_inorder = [15,20,7]

The next step is the recursive process. Follow the same steps to get the root node based on the first element of the preorder sequence, and get the left and right subtrees based on the root node and inorder, like this:

Insert picture description here

code show as below:
Insert picture description here

  TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    
    
        if(inorder.size() == 0){
    
    
            return nullptr;
        }
        TreeNode* cur = new TreeNode(preorder[0]);
        //找到当前结点在中序遍历中的位置,此索引左边为左子树,右边为右子树
        vector<int>::iterator mid = find(inorder.begin(), inorder.end(), preorder[0]);
        int left_nodes = mid - inorder.begin();//当前结点的左子树有left_nodes个

        vector<int> left_inorder(inorder.begin(), mid);
        vector<int> right_inorder(mid+1, inorder.end());
        vector<int> left_preorder(preorder.begin()+1, preorder.begin()+left_nodes+1);
        vector<int> right_preorder(preorder.begin()+left_nodes+1, preorder.end());
        cur->left = buildTree(left_preorder, left_inorder);
        cur->right = buildTree(right_preorder, right_inorder);
        return cur;
    }

Note: It is easy for us to get the results of the left and right sub-tree in-order traversal from the results of the in-order traversal of the entire tree. However, it requires certain calculations to obtain the results of the left and right sub-tree pre-order traversals based on the results of the entire tree.

After we get the root node from the middle-order traversal result, we get the index left_nodes of the root node in the current sequence . This index indicates that the left subtree has a total of left_nodes nodes.

When constructing the pre-order traversal sequence of the left subtree, start from the first element of the current sequence (excluding the root node), and count left_nodes nodes in the future . Then the remainder of this sequence is the result of the pre-order traversal of the right subtree

Post a test question from Xidian

Insert picture description here

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

struct Node{
    
    
    char data;
    Node* left;
    Node* right;
    Node(char data){
    
    
        this->data = data;
        this->left = nullptr;
        this->right = nullptr;
    }
};

vector<char> getCharArray(string str){
    
    
    vector<char> res;
    for(char c : str){
    
    
        res.push_back(c);
    }
    return res;
}

Node* getTree(vector<char>& preOrder, vector<char>& inOrder){
    
    
    if(preOrder.empty()){
    
    
        return nullptr;
    }
    Node* root = new Node(preOrder[0]);//构造根结点
    vector<char>::iterator mid = find(inOrder.begin(), inOrder.end(), preOrder[0]);
    int left_nodes = mid - inOrder.begin();
    vector<char> left_inOrder(inOrder.begin(), mid);
    vector<char> right_inOrder(mid+1, inOrder.end());
    vector<char> left_preOrder(preOrder.begin()+1, preOrder.begin()+1+left_nodes);
    vector<char> right_preOrder(preOrder.begin()+1+left_nodes, preOrder.end());
    root->left = getTree(left_preOrder, left_inOrder);
    root->right = getTree(right_preOrder, right_inOrder);
    return root;
}

void postOrder(Node* root){
    
    
    if(root == nullptr){
    
    
        return ;
    }
    postOrder(root->left);
    postOrder(root->right);
    cout<<root->data;
}

int main(){
    
    
    string pre_str;
    string in_str;
    while(cin >> pre_str >> in_str){
    
    
        vector<char> preOrder = getCharArray(pre_str);
        vector<char> inOrder = getCharArray(in_str);
        Node* root = getTree(preOrder, inOrder);
        postOrder(root);
        cout<<endl;
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_42500831/article/details/105984986