Forward citation
Just finished writing the blog of tearing the smallest pile by hand, I thought, do you have to write a binary tree traversal? Ha ha, because I wrote it some time ago and it took a lot of time to understand at that time, so now it takes about 5 minutes to tear three traversals by hand, and the traversal of the front, middle and back order will be all AC at once. After writing this article, I'll go to dinner and get into the next step Let's face it
Introduction to binary tree traversal
Binary tree is really classic. It can't be classic anymore. You must master its three non recursive traversals skillfully! The interview must be very often. I won't test you. Otherwise, it's too retarded. Ha ha
Before traversing a binary tree, we need to find out what is the pre order, what is the middle order and what is the post order. We will use this figure later, and we won't talk about it here
Of course, traversal is not only used in binary search tree, any tree can be traversed, but there are some other properties for the first, middle and last traversal of binary search tree, which will be discussed later
1. Preorder traversal of binary tree
Before we talk about code implementation, we give the results of the above preamble
We can understand that we prefer to output the value first, then move the left node, and finally move the right node. Every time we move, we will act in this order
1. Binary tree preorder traversal code (recursion)
As the most classic recursive implementation, the recursive code is as follows
class Solution { public: void preorder_visit(TreeNode* root,vector<int>& ret) { if(!root) return; ret.emplace_back(root->val); preorder_visit(root->left,ret); preorder_visit(root->right,ret); } vector<int> preorderTraversal(TreeNode* root) { vector<int> ret; preorder_visit(root,ret); return ret; } };
2. Binary tree preorder traversal code (non recursive)
I don't think it's easy to talk about non recursion
I write code in an abstract representation
I think it's the preamble. Whenever we access a node, we immediately put it into the array
When traversing to the far left, check whether there is a node on the right. If there is no re-entry cycle, it doesn't matter that the current pointer is equal to nullptr to enter the next cycle
Let's understand it in combination with the code
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { TreeNode* ptr = root; stack<TreeNode*> stack; vector<int> ret; while(ptr || stack.size()) { while(ptr) { stack.emplace(ptr); //Put pointer ret.emplace_back(ptr->val);//Put it now ptr = ptr->left; } ptr = stack.top()->right; //Access the right pointer at the top stack.pop(); //If it has been used, pop it directly } return ret; } };
2. Order traversal in binary tree
Similarly, for your convenience, I'd better take some time to do the middle order traversal results myself
If the middle order traversal is performed, we'd better directly look at the following code. Let's understand it together with this figure
1. Binary tree sequence traversal code (recursive)
Directly to the code
class Solution { public: void inorder_visit(TreeNode* root,vector<int>& ret) { if(!root) return; inorder_visit(root->left,ret); ret.emplace_back(root->val); inorder_visit(root->right,ret); } vector<int> inorderTraversal(TreeNode* root) { vector<int> ret; inorder_visit(root,ret); return ret; } };
2. Ordinal traversal code in binary tree (non recursive)
I'd better take some time to write this part
My understanding is that we still write with recursive code
First, instead of pushing numbers when encountering nodes, push numbers from the stack in recursive order. If it comes out of the stack, push again, and then ptr is the same. The order of pushing numbers does not change from stack. Top() - > right
The code is implemented as follows
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { TreeNode* ptr = root; stack<TreeNode*> stack; vector<int> ret; while(ptr || stack.size()) { while(ptr) { stack.emplace(ptr); //Storage pointer ptr = ptr->left; } ptr = stack.top(); //Inverted pointer stack.pop(); //Yes ret.emplace_back(ptr->val); // Put the values back in, in recursive order ptr = ptr->right; // Look at the right pointer } return ret; } };
3. Postorder traversal of binary tree
As usual, put the post order traversal result graph
1. Binary tree postorder traversal code (recursion)
Put the code directly
class Solution { public: void postorder_visit(TreeNode* root,vector<int>& ret) { if(!root) return; postorder_visit(root->left,ret); postorder_visit(root->right,ret); ret.emplace_back(root->val); } vector<int> postorderTraversal(TreeNode* root) { vector<int> ret; postorder_visit(root,ret); return ret; } };
2. Binary tree postorder traversal code (non recursive)
The post order is different from the pre order and the middle order. It is a little difficult, but it is only a little different, because we need to wait until whether the current node has been exhausted
I understand it this way. It is necessary to require the right node to be pushed into the array in front of the current node. If the previous right pointer is not a pre pointer, it means that the right or nullptr. If it is a null pointer, we can directly push into the array, because it means that the current pointer is the last one
The code I understand is written in this way. The following is not very easy to understand. I hope you will spend more time understanding the following code
Then the last one will put the code directly
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { TreeNode* ptr = root,*pre = nullptr; \\pre The previous pointer record is pushed into the array stack<TreeNode*> stack; vector<int> ret; while(ptr || stack.size()) { while(ptr) { stack.emplace(ptr); ptr = ptr->left; } ptr = stack.top(); if(!ptr->right || ptr->right == pre) //If the right pointer is empty or the right has been pushed, it can be pushed directly { ret.emplace_back(ptr->val); pre = ptr; stack.pop(); ptr = nullptr; } else ptr = ptr->right; } return ret; } };
Binary tree traversal example
Now let's put three classic force deduction questions in the first, middle and last order. You can also verify whether your code is correct through these three questions. Finally, I've finished writing. Now I'm playing DK in EDG. I have to write it quickly and go back to my bedroom to watch the game. I'm too excited to write it here first
144. Preorder traversal of binary tree
94. Middle order traversal of binary tree
145. Post order traversal of binary tree
Love 6 record blog 144. Preorder traversal of binary tree (iterative recursive Morris)
Love 6 record blog 94. Middle order traversal of binary tree
Love 6 record blog 145. Post order traversal of binary tree (divine Morris)