First order traversal: root —> left —> right
In-order traversal: left —> root —> right
Post-order traversal: left —> right —> root
Algorithm idea:
-
According to the characteristics of pre-order traversal, the first traversed node is the root node, we find the root node
-
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
-
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,
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:
code show as below:
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
#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;
}