First, create a two fork tree as shown below and print it out.
recursionThe idea of building a two fork tree is a natural idea.
1. Previous traversal methods
/* Previous traversal mode was established * /BinaryTreeNode* create (){BinaryTreeNode *pRoot = nullptr;Char c;CIN > > C;If (C = = "X") {Return nullptr;}Else {PRoot = new BinaryTreeNode;PRoot-> value = C;PRoot-> lChild = create ();PRoot-> rChild = create ();}Return pRoot;}
Complement: as long as we input the sequence 621##43###8##, we will create a two fork tree as shown in Figure 1. A “node” in a sequence represents an empty node, which can be used as a condition for recursive termination.
2. Two fork tree is established according to the middle sequence and the posterior sequence.
If only one of the preceding sequence, the intermediate sequence or the posterior sequence is given, a binary tree can not be uniquely determined. But a binary tree can be uniquely determined if the sequence of the middle order and the sequence of the last order or the sequence of the first order and the sequence of the second order are given.
The intermediate traversal sequence and the posterior traversal sequence of the binary tree shown in Figure 1 are 123 468 and 134 286. We can create a binary tree as shown in Figure 1 by inputting these two sequences.
/* The two fork tree is created according to the middle sequence and the posterior sequence.BinaryTreeNode* create (int InOrd[], int PostOrd[], int n){If (n = = 0) {/ / recursive termination conditionReturn nullptr; / / here should be an empty node.}BinaryTreeNode *pRoot = new BinaryTreeNode;PROot-> value = PostOrd[n-1]; / / root node valueInt lChildNum = 0; / / left node tree node numberInt rChildNum = 0;Node number of / / right subtreeFor ((lChildNum < n; ++lChildNum) {If (InOrd[lChildNum] = = pRoot-> value)Break;}RChildNum = n - lChildNum - 1;/ / recursively create left and right subtrees.PRoot-> lChild = create (InOrd, PostOrd).LChildNum);PRoot-> rChild = create (InOrd + lChildNum + 1, PostOrd + lChildNum, rChildNum);REturn pRoot;}
Analysis: The last element of the sequence must be the root node of the tree. From the value of the node to traverse the sequence of the middle order, we can get the number of nodes of the left subtree and the right subtree.. With this recursion, we can create a two fork tree as shown in Figure 1.
Three. Recursion to achieve the forward / middle / traversal traversal of the two fork tree.
/* Preorder traversal * /Void PreOrderTraverse (BinaryTreeNode *pRoot){If (pRoot = = nullptr)Return;Cout < < pRoot-> value;PreOrderTraverse (pRoot-> lChild);PreOrderTraverse (pRoot-> rChild);}/ * sequential traversal * /Void InOrderTraverse (BinaryTreeNode *pRoot){If (pRoot = = nullptr)Return;InOrdeRTraverse (pRoot-> lChild);Cout < < pRoot-> value;InOrderTraverse (pRoot-> rChild);}* * traversal traversal * /Void PostOrderTraverse (BinaryTreeNode *pRoot){If (pRoot = = nullptr)Return;PostOrderTraverse (pRoot-> lChild);PostOrderTraverse (pRoot-> rChild);Cout < < pRoot-> valuE;}
Four, use the non recursive way to realize the forward / middle / traversal traversal of the two fork tree.
1. Preorder traversal
The node is first removed from the top of the stack. If the node is not empty, the node is accessed and the right and left subtrees of the node are placed on the stack in turn.
void PreOrderTraverse(BinaryTreeNode *pRoot) { stack<BinaryTreeNode*> sck; sck.push(pRoot); BinaryTreeNode *pNode = nullptr; while(!sck.empty()) { pNode = sck.top(); sck.pop(); if(pNode != nullptr) { cout << pNode->value; sck.push(pNode->rChild); sck.push(pNode->lChild); } } }
2. Middle order ergodic
The root node is put on the stack, and then the left subtree is put on the stack until the left subtree is empty, and then the stack stops. The top node of the stack is the node that we need to access. We take the top node P of the stack and access it. Then the node may have a right subtree, so after accessing the node p, you have to determine whether the right subtree of P is empty, if it is empty.The next node to be accessed is at the top of the stack, so assign p to null. If it is not empty, assign p to the value of its right subtree.
/* Sequential traversal * /Void InOrderTraverse (BinaryTreeNode *pRoot){Stack< BinaryTreeNode*> SCK;BinaryTreENode *pCur = pRoot;While (sck.empty ()) pCur! = nullptr) {While (pCur = nullptr) {Sck.pusH (pCur);PCur = pCur-> lChild;}PCur = sck.top ();Sck.pop ();Cout < < pCur-> VALue;If (pCur-> rChild! = nullptr)PCur = pCur-> rChild;ElsePCur = nullptr;}}
3. Post order traversal
For any node P, stack it and search it along its left sub tree until it is searched.No left child.The node appears at the top of the stack at this time, but at this pointYou can’t stack it out.And the right child has not been visited. So we follow the same rule to deal with the right subtree in the same way. When the right child is visited, the node appears at the top of the stack.You can stack it out.And visit. This ensures the correct access order. As you can see, during this process, each node that cannot exit the stack for the first time will appear on the top of the stack twice, and will be accessed only when it appears on the top of the stack for the second time. Therefore, we need to set up a variable to identify whether the node is the first time it appears on the top of the stack..
/* Post order traversal * /Struct BTNode {BinaryTreeNode *pNode;Bool isFirst;};Void PostOrderTraverse (BinaryTre)ENode *pRoot){Stack< BTNode*> SCK;BTNode *temp = nullptr;BinaryTreeNode *pCur = pRoot;While (pCur! = nullptr! Sck.empty!) {While (pCur = nullptr) {BTNode *pBtn = new BTNode;PBtn-> pNode = pCur;PBtn-> isFirst = true;Sck.push (pBtn);PCur = pCur-> lChild;}Temp = sck.top ();Sck.pop ();If (temp-> isFirst = = true) {Sck.push (Temp);Temp-> ISFirst = false;PCur = temp-> pNode-> rChild;}Else {Cout < < temp-> pNode-&gT; value;PCur = nullptr;}}}
For example, the binary tree shown in Figure 1 will output 1348 if no auxiliary variable is added to determine whether the node first appears on the top of the stack. The node with the right subtree will pop up because it first appears on the top of the stack, but it will not output when it first appears, so the output of the result will not have it.Ladies and gentlemen.
Five, level traversal
1. Loop implementation using queues
/* Hierarchical ergodic * /Void LevelTraverse (BinaryTreeNode *pRoot){Queue< BinaryTreeNode*> que;Que.push (pRoOT);BinaryTreeNode *pNode = nullptr;While (que.empty ()) {PNode = que.front ();Que.pop ();Cout < < pNode-> value;If (pNode-> lChild! = nullptr)Que.push (pNode-> lChild);If(pNode-> rChild! = nullptr)Que.push (pNode-> rChild);}}
2. Recursive implementation
/* Hierarchical ergodic * /Void PrintNodeAtLevel (BinaryTreeNode *pRoot, int level){If (pRoot = = nullptr nullptr level <1) / / empty tree or level unreasonable.Return;If (level = = 1) {Cout < < pRoot-> value;ReTurn;}/ / left sub tree level - 1 levelPrintNodeAtLevel (pRoot-> lChild, level - 1);/ / right subtreeLevel - 1 levelPrintNodeAtLevel (pRoot-> rChild, level - 1);}Void LevelTraverse (BinaryTreeN)Ode *pRoot){If (pRoot = = nullptr)Return;Int height = GetHeight (pRoot); / / two fork treeHeight/ / layer by layer printingFor (int i = 1; I < = height; i++) {PrintNodeAtLevel (pRoot, I);COut < < endl;}}
Analysis: this solution is not only the result of hierarchical traversal, but also the result of hierarchical output of the two fork tree.
Six. Seek the height of the tree.
1. Recursive implementation
/* Finding the height of the tree * /Int GetHeight (BinaryTreeNode *pRoot){If (pRoot = = nullptr) return 0;Int leftHeight = GEtHeight (pRoot-> lChild);Int rightHeight = GetHeight (pRoot-> rChild);Return leftHeight >RightHeight? LeftHeight + 1: rightHeight + 1;}
2. Loop implementation
The idea of using the loop to find the height of the two fork tree is to go out of the queue one by one. At the end of each visit, all the elements stored in the queue are just the next layer. So at the beginning of the next loop, you first record the number of elements in the layer and access all the elements in the layer at once.
/* Finding the height of the tree * /Int GetHeight (BinaryTreeNode *pRoot){If (pRoot = = nullptr) return 0;Int height = 0;/ / height of treeQueue< BinaryTreeNode*> que;Que.push (pRoot);BinaryTreeNode *pCur = nullptr;// Actually, when each loop starts, all the elements in the queue that happen to be in the layer to be accessed are storedWhile (que.empty ()) {Height++;Int curLevelNum = que.sIze (); / / current node node number/ / pop up all elements of the current layerWhile (curLevelNum-- > 0) {PCur = que.front ();Que.pOp ();/ / push the next layer of elements into the queue.If (pCur-> lChild! = nullptr)Que.push (pCur-> lChild);If (pCur-> rChild! = nullptrQue.push (pCur-> rChild);}}Return height;}
Seven. Total code
#include <iostream> #include <stack> #include <queue> using namespace std; struct BinaryTreeNode { int value; BinaryTreeNode *lChild; BinaryTreeNode *rChild; }; struct BTNode { BinaryTreeNode *pNode; bool isFirst; }; int GetHeight(BinaryTreeNode *pRoot); /* The two fork tree is created according to the middle sequence and the posterior sequence.BinaryTreeNode* create (int InOrd[], int PostOrd[], int n){If (n = = 0) {/ / recursive termination conditionReturn nullptr; / / here should be an empty node.}BinaryTreeNode *pRoot = new BinaryTreeNode;PROot-> value = PostOrd[n-1]; / / root node valueInt lChildNum = 0; / / left node tree node numberInt rChildNum = 0;Node number of / / right subtreeFor ((lChildNum < n; ++lChildNum) {If (InOrd[lChildNum] = = pRoot-> value)Break;}RChildNum = n - lChildNum - 1;/ / recursively create left and right subtrees.PRoot-> lChild = create (InOrd, PostOrd).LChildNum);PRoot-> rChild = create (InOrd + lChildNum + 1, PostOrd + lChildNum, rChildNum);REturn pRoot;}* * non recursive first order traversal * /Void PreOrderTraverse (BinaryTreeNode *pRoot){Stack< BinaryTreeNoDe*> SCK;Sck.push (pRoot);BinaryTreeNode *pNode = nullptr;While (sck.empty ()) {PNode = SCK.top ();Sck.pop ();If (pNode = nullptr) {Cout < < pNode-> value;Sck.push (pNode-&)Gt; rChild);Sck.push (pNode-> lChild);}}}* * non recursive sequential traversal * /Void InOrderTraverse (BinaryTree)Node *pRoot){Stack< BinaryTreeNode*> SCK;BinaryTreeNode *pCur = pRoot;While (sck.empty ())PCur! = nullptr) {While (pCur = nullptr) {Sck.push (pCur);PCur = pCur-> lChild;}PCur = sck.top ();Sck.pop ();Cout < < pCur-> value;If (pCur-> rChild! = nullptr)PCur = pCur-> rChild;ElsePCur = nullptr;}}* * non recursive backward traversal * /Void PostOrderTraverse (Bina)RyTreeNode *pRoot){Stack< BTNode*> SCK;BTNode *temp = nullptr;BinaryTreeNode *pCur = pRoOt;While (pCur! = nullptr! Sck.empty!) {While (pCur = nullptr) {BTNode *pBtn = new BTNodE;PBtn-> pNode = pCur;PBtn-> isFirst = true;Sck.push (pBtn);PCur = pCur-> lChilD;}Temp = sck.top ();Sck.pop ();If (temp-> isFirst = = true) {Sck.push (Temp);Temp-> isFirst = false;PCur = temp-> pNode-> rChild;}Else {Cout < < temp-> pNoDe-> value;PCur = nullptr;}}}* * recursive hierarchical ergodic * /Void PrintNodeAtLevel (BinaryTreeNode *pRoot,Int level){If (pRoot = = nullptr nullptr level < 1) / empty tree or hierarchy is unreasonable.Return;If (level = = 1) {Cout < < pRoot-> value;Return;}/ / left sub tree level - 1 levelPrintNodeATLevel (pRoot-> lChild, level - 1);/ / right subtree level - 1 levelPrintNodeAtLevel (pRoot-> rChild).Level - 1);}Void LevelTraverse (BinaryTreeNode *pRoot){If (pRoot = = nullptr)ReturN;Int height = GetHeight (pRoot); / / height of two fork tree/ / layer by layer printingFor (int i = 1; I < = height; I)+ +)PrintNodeAtLevel (pRoot, I);}/ * loop height of the tree * /Int GetHeight (BinaryTreeNode *pRoot){If (pRoOt = = nullptr) return 0;Int height = 0; / / tree heightQueue< BinaryTreeNode*> que;Que.Push (pRoot);BinaryTreeNode *pCur = nullptr;// Actually, when each loop starts, all the elements in the queue that happen to be in the layer to be accessed are storedWhile (! Que.emp)Ty ()) {Height++;Int curLevelNum = que.size (); / / the number of nodes in the current layer./ / pop up all elements of the current layerWhile (curLevelNu)M-- > 0) {PCur = que.front ();Que.pop ();/ / push the next layer of elements into the queue.If (pCur-> lChild! = nullp)TR)Que.push (pCur-> lChild);If (pCur-> rChild! = nullptr)Que.push (pCur-> rChild);}}Return height;}Int main (){Int InOrd[6] = {1, 2, 3, 4, 6, 8};Int PostOrd[6] = {1,3, 4, 2, 8, 6};BinaryTreeNode *pTree = create (InOrd, PostOrd, 6);Cout < < "hint: the two fork tree is created! "&lT; < endl;Cout < < "prompts: first traverses two fork tree..." < < endl;PreOrderTraverse (pTree);Cout < <Endl;Cout < < "hint: in order traversal two fork tree..." < < endl;InOrderTraverse (pTree);Cout < < endL;Cout < < "hint: traversing two fork tree..." < < endl;PostOrderTraverse (pTree);Cout < < endl;Cout < < "hint: level traversal two fork tree"... < < endl;LevelTraverse (pTree);Cout < < endl;CoUT < < "hint: the height of the tree is" < < GetHeight (pTree) < < endl;Return 0;}
Test results: