========================= First-order traversal ========================
Traverse pseudo code 1 in sequence:
Void preOrder1 (TNode * root)
{
Stack st;
While (root! = NULL) |! St. empty ())
{
If (root! = NULL)
{
Visit (root); // access the re-stack first
St. push (root );
Root = root-> left;
}
Else
{
Root = st. pop ();
Root = root-> right;
}
}
}
Traverse pseudo code 2 in sequence:
Void preOrder2 (TNode * root)
{
If (root! = NULL)
{
Stack st;
St. push (root );
While (! St. empty ())
{
TNode * node = st. pop ();
Visit (node); // first access the root node, and then the root node does not need to go into the stack.
St. push (node-> right); // first push the right node, then the left node
St. push (node-> left); // access the left node first.
}
}
}
First traverse without Stack:
Void preOrder3 (TNode * root)
{
While (root! = NULL)
{
If (! Root-> bVisited)
{
Visit (root );
Root-> bVisited = true;
}
If (root-> left &&! Root-> left-> bVisited)
{
Root = root-> left;
}
Else if (root-> right! = NULL &&! Root-> right-> bVisited)
{
Root = root-> right;
}
Else
{// Backtracking
Root = root-> parent;
}
}
}
========================== Middle-order traversal ======================
In-order traversal of pseudo code:
Void inOrder1 (TNode * root)
{
Stack s;
While (root! = NULL |! S. empty ())
{
While (root! = NULL) // locate the left subtree
{
S. push (root); // first enters the stack
Root = root-> left;
}
If (! S. empty ())
{
Root = s. pop (); // re-Access
Visit (root );
Root = root-> right; // traverse the right subtree through the next loop
}
}
}
In-order traversal without Stack:
Void inOrder3 (TNode * root)
{
While (root! = NULL)
{
While (root-> left! = NULL &&! Root-> left-> bVisited)
{
Root = root-> left;
}
If (! Root-> bVisited)
{
Visit (root );
Root-> bVisited = true;
}
If (root-> right! = NULL &&! Root-> right-> bVisited)
{
Root = root-> right;
}
Else
{
Root = root-> parent; // trace back
}
}
}
======================= Post-order traversal ==========================
Pseudo code for post-sequential traversal:
Void PostOrder (TNode * root)
{
Stack s;
If (root! = NULL)
S. push (root );
While (! S. empty ())
{
TNode * node = s. pop ();
If (node-> bPushed) // The left and right sub-trees of the sub-trees are in the stack, access the node
{
Visit (node );
}
Else
{// If the left and right subtree have not been added to the stack, the root node, right node, and left node are successively added to the stack.
S. push (node); // 1> root
If (node-> right! = NULL)
{
Node-> right-> bPushed = false; // set the left and right subtree to false first.
S. push (node-> right); // 2> right subtree into Stack
}
If (node-> left! = NULL)
{
Node-> left-> bPushed = false; // set the left and right subtree to false first.
S. push (node-> left); // 3> left subtree into Stack
}
Node-> bPushed = true; // both left and right subtree are in the stack, and the root node can access
}
}
}
======================= Sequence traversal ======================
Hierarchical traversal of pseudo code:
Void levelOrder (TNode * root)
{
Queue Q;
Q. push (root );
While (! Q. empty ())
{
TNode * node = Q. front ();
Visit (node );
If (node-> left! = NULL)
{
Q. push (node-> left );
}
If (node-> right! = NULL)
{
Q. push (node-> right );
}
}
}
In the beauty of programming, the vector container is used to store information of n nodes, and the access termination condition of the previous layer is recorded with a cursor variable last, as follows:
Void PrintNodeByLevel (Node * root)
{
Vector <Node *> vec; // here we use the vector in STL to replace the array, and we can use its dynamic extended attributes.
Vec. push_back (root );
Int cur = 0;
Int last = 1;
While (cur <vec. size ()){
Last = vec. size (); // access the new row to start, and locate the next position last in the Last node of the current row.
While (cur <last ){
Cout <vec [cur]-> data <"; // access the node
If (vec [cur]-> lChild) // if the left node of the current access node is not empty, press
Vec. push_back (vec [cur]-> lChild );
// Press in if the right node of the current access node is not empty. Note that the access order of the left and right nodes cannot be reversed.
If (vec [cur]-> rChild)
Vec. push_back (vec [cur]-> rChild );
Cur ++;
}
Cout <endl; // when cur = last, it indicates that the access to this layer is over and the line break is output.
}
}
In addition,
=================
// If T is an empty tree, the depth is 0. Otherwise, the depth equals to the maximum depth of the Left or right subtree plus 1.
Int getDepth (BiTree T)
{
If (T = NULL) return 0;
Else {
Dep1 = getDepth (T-> lchild );
Dep2 = getDepth (T-> rchild );
Return dep1> dep2? Dep1 + 1: dep2 + 1;
}
Summary:
Stack-based tracing is more convenient than adding a pointer pointing to the parent node:
1. The stack method is to track pointer movement and use the stack to save intermediate results. The first order is the same as the middle order, and the latter order is very difficult. You only need to modify the access location in the first and middle orders.
2. The method of adding a parent node is used to directly simulate recursion using stacks. The first order is very simple, while the middle order is the same as the latter. The first order is simple because nodes can be accessed directly, and no records are required after access.
In the middle and back order, the node cannot be accessed immediately after the stack is played, and it must be accessed only after other nodes are accessed. Therefore, the node needs to set a flag to determine, therefore, additional O (n) space is required.
Appendix: C source program
# Include <stdio. h>
# Include <stdlib. h>
# Define MAX 20
# Define NULL 0
Typedef char TElemType;
Typedef int Status;
Typedef struct BiTNode {
TElemType data;
Struct BiTNode * lchild, * rchild;
} BiTNode, * BiTree;
Status CreateBiTree (BiTree * T ){
Char ch;
Ch = getchar ();
If (ch = '#') (* T) = NULL;/* # indicates a NULL pointer */
Else {
(* T) = (BiTree) malloc (sizeof (BiTNode);/* Application node */
(* T)-> data = ch;/* generate the root node */
CreateBiTree (& (* T)-> lchild);/* construct the left subtree */
CreateBiTree (& (* T)-> rchild);/* construct the right subtree */
}
Return 1;
}
Void PreOrder (BiTree T ){
If (T ){
Printf ("% 2c", T-> data);/* access the root node, which is simplified to the data value of the output root node */
PreOrder (T-> lchild);/* First traverse the left subtree */
PreOrder (T-> rchild);/* First traverse the right subtree */
}
}
Void LevleOrder (BiTree T ){
/* Traverse binary tree T at a level, starting from the first layer, and each layer from left to right */
/* The queue is represented by a one-dimensional array, and the front and rear represent the first and last pointers of the Team */
BiTree Queue [MAX], B;
Int front, rear;
Front = rear = 0;
If (T)/* if the tree is not empty */
{
Queue [rear ++] = T;/* enter the Queue as the root node */
While (front! = Rear) {/* When the queue is not empty */
B = Queue [front ++];/* the first element of the Queue goes out of the Queue and accesses this node */
Printf ("% 2c", B-> data );
If (B-> lchild! = NULL)
Queue [rear ++] = B-> lchild;/* enter the Queue if the left subtree is not empty */
If (B-> rchild! = NULL)
Queue [rear ++] = B-> rchild;/* If the right subtree is not empty, enter the Queue */
}
}
} // LevelOrder
Int getDepth (BiTree T)
{
If (T = NULL) return 0;
Else {
Dep1 = getDepth (T-> lchild );
Dep2 = getDepth (T-> rchild );
Return dep1> dep2? Dep1 + 1: dep2 + 1;
} // Depth
Main (){
BiTree T = NULL;
Printf ("\ nCreate a Binary Tree \ n ");
CreateBiTree (& T);/* Create a binary tree T */
Printf ("\ nThe preorder is: \ n ");
PreOrder (T);/* traverse Binary Trees in sequence */
Printf ("\ nThe level order is: \ n ");
LevleOrder (T);/* traverse a binary tree hierarchically */
Printf ("\ nThe depth is: % d \ n", depth (T ));
}
Author sdtarena