"Turn" a simpler way to traverse a binary tree with no recursion

Source: Internet
Author: User

The solution to solve many of the two-tree problems is based on the traversal of the two-fork tree. Traversing the binary tree of the pre-order, the middle sequence, the three major methods of post-order computer science students must write code. Its recursive traversal is accessible to everyone, but it is not easy to write non-recursive traversal when rusty. Because it is not easy, there are countless articles on the Internet that introduce the non-recursive traversal method of binary tree. But do you really need those non-recursive traversal codes and storytelling? Code Early Learning data structure to understand, understand, but why we again and again to forget the non-recursive traversal method, but always remember the recursive traversal method?

Three kinds of recursive traversal of the description of the traversal, the idea is very concise, the most important is the total unity of three methods, greatly reducing the burden of our understanding. And we often come into contact with those three non-recursive traversal methods, in addition to the use of stacks, the specific implementation of the differences, resulting in a vague understanding. This paper presents a unified implementation of the three non-recursive traversal of the idea.

Three recursive traversal
//前序遍历void preorder(TreeNode *root, vector<int> &path){ if(root != NULL) { path.push_back(root->val); preorder(root->left, path); preorder(root->right, path); }}
//Middle sequence traversal void inorder (TreeNode *root, vector<int> &path" {if (Root! = Span class= "Hljs-literal" >null) {inorder (root->left, path); Path.push_back (Root->val); Inorder (root->right , path); }}
//后续遍历void postorder(TreeNode *root, vector<int> &path){ if(root != NULL) { postorder(root->left, path); postorder(root->right, path); path.push_back(root->val); }}

From the above, recursive algorithm implementation ideas and code style is very unified, about the "recursion" understanding of my "brain understanding recursion."

Non-recursive traversal in textbooks
//non-recursive pre-sequence traversal void preordertraversal (TreeNode *root, Span class= "hljs-built_in" >vector<int> &path) { Stack<treenode *> S; TreeNode *p = root; while (P! = null | |!s.empty ()) { while (P! = null) {path.push_back (p->val); S.push (p); p = p->left;} if (!s.empty ()) {p = s.top (); S.pop (); p = p->right;}}}        
//非递归中序遍历void inorderTraversal(TreeNode *root, vector<int> &path){ stack<TreeNode *> s; TreeNode *p = root; while(p != NULL || !s.empty()) { while(p != NULL) { s.push(p); p = p->left; } if(!s.empty()) { p = s.top(); path.push_back(p->val); s.pop(); p = p->right; } }}
Non-recursive post-traversal-iterative void Postordertraversal (TreeNode *root, vector<int> &path) {Stack<tempnode *> s;    TreeNode *p = root; Tempnode *temp;while (P! =null | |!s.empty ()) {while (P!) = null) //searches down the Zuozi until a node with no left subtree appears {TreeNode *tempnode = new TreeNode; Tempnode->btnode = p; Tempnode->isfirst = true; S.push (tempnode); p = p->left;} if (!s.empty ()) {temp = S.top (); S.pop (); if (Temp->isfirst = = true) //is the first time that it appears on the top of the stack { Temp->isfirst = false; s.push (temp); p = temp->btnode->right;} else //appears the second time at the top of the stack {path.push_back (temp->btnode->val); p = null; } } }}

Read the above textbook three kinds of non-recursive traversal method, it is not difficult to find that the implementation of the post-order traversal is significantly more complex than the sequence traversal and the middle sequence traversal, the pre-sequence traversal and the middle sequence traversal seems to implement the same style, but in fact the former is in the pointer iterative access to the node value, the latter is the top There is an essential difference in the realization of ideas. The biggest drawback of these three methods is that they use nested loops, which greatly increases the complexity of understanding.

A simpler way to traverse binary trees with non-recursive recursion

Here I give a unified implementation of ideas and code style method to complete the two-fork tree three kinds of non-recursive traversal.

Simpler non-recursive pre-order traversalvoidPreordertraversalnew(TreeNode *root, vector<int> &path) { stack< Pair<treenode *, bool> > S; s.push (Make_pair (root, false)); BOOL visited; While (!s.empty ()) {root = S.top (). First; visited = S.top (). second; S.pop (); if (root = = NULL) continue; if (visited) {path.push_back (root->val);} else {s.push (Make_pair (Root->right, false)), S.push (Make_pair (Root->left, false)), S.push (make _pair (Root, true)); } }}
Simpler non-recursive mid-order traversalvoidInordertraversalnew(TreeNode *root, vector<int> &path) { stack< Pair<treenode *, bool> > S; s.push (Make_pair (root, false)); BOOL visited; While (!s.empty ()) {root = S.top (). First; visited = S.top (). second; S.pop (); if (root = = NULL) continue; if (visited) {path.push_back (root->val);} else {s.push (Make_pair (Root->right, false)), S.push (Make_pair (root, true)), S.push (Make_pair ( Root->left, false)); } }}
Simpler non-recursive post-traversalvoidPostordertraversalnew (TreeNode *root, vector<int > &path) {stack< pair<treenode *, bool> > S ; S.push (Make_pair (Root, false)); bool visited; while (!s.empty ()) {root = S.top (). First; visited = S.top (). second; S.pop (); if (root = null) continue; if (visited) {path.push_back (root->val);} else {S.push (Make_pair (Root, true)); S.push (Make_pair (root- >right, false)); S.push (Make_pair (root->left, false));}}        

The above three traversal implementations have exactly the same number of lines, and as with recursive traversal, only three lines of core code have a different order. Why is this effect possible? I'll introduce you below.

Local ordering of coincident elements can lead to a whole order

This is how I can unify the basic idea of three simpler non-recursive traversal methods: The partial ordering of coincident elements can cause the whole order .
The following sequence, local 2 3 4 and local 1 2 3 , is orderly, but cannot guarantee the overall order.

And the following sequence, local 2 3 4 , are 4 5 6 6 8 10 ordered, and the adjacent parts have a coincident element, so ensure that the whole sequence is also ordered.

Applied to Binary tree

Based on this idea, I conceived three kinds of non-recursive traversal of the unity: whether it is the pre-order, the middle order, after the order, as long as I can guarantee to each node, the node, its left Dial hand node, its right sub-node to meet the previous order/middle order/sequence of access sequence, the entire binary tree of this three-node local order must be able to Ordinal/post-order access, because adjacent parts must have coincident nodes, that is, a local "root" node is another local "sub" node.

For example, for a two-fork tree, will 每个框内结点集都看做一个局部 , then locally have,,,,,, A A B C B D E D E C F F and can be found 每个结点元素都是相邻的两个局部的重合结点 . Found that this is very critical, because know the coincident node, you can order a local, by taking out a coincident node transition to the adjacent part of the new local ordering. We can use the stack to ensure that the local order (in front of the order before the stack, in the back of the first stack, to ensure that the local elements out of the stack order must be correct), and then through the stack top elements (coincident elements) to the new local ordering, the new local ordering will cause the coincident node again into the stack, So when the top of the stack has completed the transition mission of the node, you can completely out of the stack output (and this output can guarantee that the node in its transition of the part must be the first), and the new stack top element will continue to complete the new local transition. When all the nodes have completed the transition mission, it is all out of the stack, then I dare to guarantee that all local elements are ordered out of the stack, and adjacent parts must have coincident elements to ensure that the overall output must be orderly. The advantage of this idea is 将算法与顺序分离 that the definition of what order does not affect the algorithm, the algorithm only do one thing: the top element of the stack out, so that the element is the "root" node of the local ordered into the stack, but if it has been through the node in the local stack, then directly out of the stack output .

From the implementation of the program can be seen: three non-recursive traversal is the only difference is the local into the stack of three lines of code sequencing. So either,,, 根->左->右 左->根->右 or even, the 左->右->根 根->右->左 右->根->左 右->左->根 New Order of the definitions, the algorithm implementation has no change, except to change the local stacking order.

It is worth mentioning that, for the pre-sequence traversal, you may find out a stack top element, so that its local pre-sequence into the stack, the top element of the stack is still this element, and then out of the stack output, so that it is not necessary with the local stack, its code can be simplified to the following form.

void Preordertraversalnew(TreeNode*root, vector<int> &path) {Stack<treenode *> s; S.push(root), while(!s.empty()) {root = S.top(); S.pop(); if(root = = NULL) {continue;} else {path.push_back(root->val); S.push(root->right); S.push(root->left);             }}} 

This is what I want to introduce is a simpler way to traverse a binary tree with no recursion.

Transfer from HTTP://WWW.JIANSHU.COM/P/4DB970D8DDC1

"Turn" a simpler way to traverse a binary tree with no recursion

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.