The day before yesterday, I went to the Meituan for an interview. On the second side, I had a good trip. Later, I encountered a non-Recursive Method to Solve the binary tree height and asked me to write the program on the site. Then I got stuck and was very upset. In the past two days, I have supplemented this part and summarized the following ideas.
1. Consider clearly solving the problem similar to traversing in the forward or middle order or follow-up;
2. Consider what needs to be written into the stack in a recursive program: The Node itself, the return address (used to tell the program where to execute the returned content), local variables, and returned values.
Next, let's start with the code and compare the ideas.
First, let's take a look at the recursive and non-recursive procedures of sequential traversal:
Void pretraverse (cNode * subtree, bool (* visit) (cNode *) {If (subtree) {visit (subtree); pretraverse (subtree-> lchild, visit ); pretraverse (subtree-> rchild, visit) ;}} void pretraversenonrecursive (cNode * subtree, bool (* visit) (cNode *)) // will you simplify this function in the form below ^ this function comes from the network, and I personally think it is complicated to write. You can use three cases to simplify the process. {STD: Stack <cNode *> S; cNode * t = subtree; S. Push (t); While (! S. Empty () {While (! S. Empty () // go left until the most left child {T = S. Top (); // notice: Without pop !! If (! T) break; visit (t); S. Push (t-> lchild);} s. Pop (); // pop null pointerif (! S. Empty () // right child {T = S. Top (); S. Pop (); S. Push (t-> rchild );}}}
Next, perform sequential traversal:
void InTraverse(CNode *subTree, bool (*Visit)(CNode *)){if (subTree){InTraverse(subTree->lchild, Visit);Visit(subTree);InTraverse(subTree->rchild, Visit);}}void InTraverseNonRecursiveVer2(CNode *subTree, bool (*Visit)(CNode *)) { class CPostNode { public: CNode* pNode; int flag; CPostNode(CNode *n, int i) { pNode = n; flag = i; }; }; std::stack<CPostNode> s; CPostNode t(subTree, 1); s.push(t); while (!s.empty()) { t= s.top(); s.pop(); switch(t.flag) { case 1: t.flag = 2; s.push(t); if (t.pNode->lchild) { s.push(CPostNode(t.pNode->lchild, 1)); } break; case 2: Visit(t.pNode); if (t.pNode->rchild) { s.push(CPostNode(t.pNode->rchild, 1)); } break; case 3: // unable to run to here for in-traverse. break; } } }
Then, it is the next traversal:
void PostTraverse(CNode *subTree, bool (*Visit)(CNode *)){if (subTree){PostTraverse(subTree->lchild, Visit);PostTraverse(subTree->rchild, Visit);Visit(subTree);}}void PostTraverseNonRecursive(CNode *subTree, bool (*Visit)(CNode *)){class CPostNode{public:CNode* pNode;int flag;CPostNode(CNode *n, int i){pNode = n;flag = i;};};std::stack<CPostNode> s;CPostNode t(subTree, 1);s.push(t);while (!s.empty()){t = s.top(); s.pop(); // notice: pop() here!!switch(t.flag){case 1:t.flag = 2;s.push(t);if (t.pNode->lchild){s.push(CPostNode(t.pNode->lchild, 1));}break;case 2:t.flag = 3;s.push(t);if (t.pNode->rchild){s.push(CPostNode(t.pNode->rchild, 1));}break;case 3:Visit(t.pNode);//s.pop();break;}}}
Finally, the height of the tree is obtained by non-recursive methods:
int GetSubTreeDepth(CNode *subTree){if (!subTree)return 0;return std::max<int>(GetSubTreeDepth(subTree->lchild), GetSubTreeDepth(subTree->rchild)) + 1;}int GetSubTreeDepthVer2(CNode *subTree){class CStackNode{public:CNode* pNode;int flag;int depth;CStackNode(CNode *n, int i, int d){pNode = n;flag = i;depth = d;};};std::stack<CStackNode> s;CStackNode t(subTree, 1, 1);s.push(t);while (!s.empty()){t = s.top(); s.pop();switch (t.flag){case 1:t.flag = 2;s.push(t);if (t.pNode->lchild){s.push(CStackNode(t.pNode->lchild, 1, 1));}break;case 2:t.flag = 3;s.push(t);if (t.pNode->rchild){s.push(CStackNode(t.pNode->rchild, 1, 1));}break;case 3:if (s.empty())return t.depth;CStackNode t3 = s.top(); s.pop();t3.depth = std::max<int>(t3.depth, t.depth + 1);s.push(t3);break;}}return t.depth;}
From the above example, we can clearly see the solution: flag is used to mark the number of times we access the node. Different times mean we have to do different things, therefore, different codes are executed in different cases in the program.
In addition, when determining the height of a tree, Case 3 must first determine whether s is null. If it is null, the height can be directly returned ~
It took me one day to complete all the code. Please specify the source for your reference. Thank you ~
Xjs.xjtu@gmail.com
2012-10-24