# Binary tree non recursive traversal algorithm

Keywords: Algorithm data structure

### Preorder non recursive (stack implementation)

#### Algorithm idea:

1. Access the root node to the left and down in turn, and then immediately put the node on the stack (until the left child is empty);
2. When you get to the bottom left, the top element of the stack goes out of the stack and turns to the right subtree (judge whether the right child is empty. If the right child is not empty, perform the same operation as 1 on the current node; if it is empty, continue to execute 2 on the current node)
3. Pithy formula: access into the stack to the left, out of the stack to the right subtree
```void PreOrder(BiTree T){
InitStack(S);
BiTree p=T;
while(p || !IsEmpty(S)){ //If p is not empty or the stack is not empty
if(p){   //p is not empty
visit(p->data); //First visit
push(S,p);		//Reentry stack
p=p->lchild;	//It's not empty. Go straight to the left
}else{
pop(S,p);  //Stack top element out of stack
p=p->rchild; //Turn right subtree
}
}
}
```

### Medium order non recursive (stack implementation)

#### Algorithm idea:

1. Enter the stack in turn along the left child of the root node until the left child is empty (indicating that the node that can be output has been found, and the element at the top of the stack is the node that can be output);
2. Stack top element out of the stack and access: if the right child is empty, continue to execute 2. If the right child is not empty, execute 1 with the current node as the right subtree of the root node
3. Pithy formula: go straight to the left when entering the stack, and access (turn to) the right subtree when leaving the stack
```void InOrder(BiTree T){
InitStack(S);
BiTree p=T;
while(p || !IsEmpty(S)){ //If p is not empty or the stack is not empty
if(p){   //p is not empty
push(S,p);		//First in stack
p=p->lchild;	//It's not empty. Go straight to the left
}else{
pop(S,p);  //Stack top element out of stack
visit(p->data); //Post stack access
p=p->rchild; //Turn right subtree
}
}
}
```

### Post order non recursive (stack implementation)

#### Algorithm idea:

1. Follow the left child of the root and enter the stack in turn until the left child is empty (go to the bottom left);
2. Read stack top element: if the right child is not empty and has not been accessed, perform 1 operation on the right child// This step requires an r pointer to point to the visited node (for marking)
3. Otherwise, the top element of the stack is directly out of the stack and accessed; (at this time, the node referred to by p must be a leaf node, and the left and right subtrees are empty).
```void PostOrder(BiTree T){
InitStack(S); //Initialize a stack
BiTree p=T;		//The p pointer points to the root node
r=NULL;		//The initialization auxiliary pointer is used to mark the node that has been accessed
while(p || !IsEmpty(S)){ //The tree (the node referred to by p) is not empty or the stack is not empty
if(p){			//p is not empty
push(S,p);	//Stack in turn
p=p->lchild; //p go straight down to the left
}else{				//p is empty, that is, it goes to the bottom left
GetTop(S,p); //Read the top element of the stack, that is, let p point back to the non empty node of the previous layer (p points back)
if(p->rchlid && p->rchild != r) //If the right subtree of p is not empty and the right subtree of p has not been accessed
p=p->rchild; //p points to the right subtree of p, turns right, and does the same operation as the left
else		//If the right subtree does not exist or has been accessed, directly pop the node indicated by p out of the stack, and then access
pop(S,p); //Pop stack
visit(p->data); //visit
r=p;		//Mark visited nodes
p=NULL;    //At this time, the subtree with the node referred to by P as the root node has been completely traversed, so set p to null
}
}
}

//Why use an auxiliary pointer to mark the nodes that have been accessed?
//Because post order traversal is to access the left subtree first, then the right subtree, and finally the root node.
//In the code, return to the root node from the left subtree first (do not access the root node first, because if there is a right subtree and it has not been accessed, the right subtree must be accessed first)
//Then access the right subtree, and finally return the root node from the right subtree (at this time, a pointer is required to point to the recently accessed node
//Because we don't know whether this node is returned by the left subtree or the right subtree
//If it is returned from the right subtree, and the root node is returned at this time, you can directly access the root node
//If it is returned from the left subtree, you also need to access the right subtree.)

```

### Hierarchical traversal (queue implementation)

#### Algorithm idea:

1. First queue the root node, then leave the queue, and access the out of queue node;
2. If the outgoing node has a left subtree, the root node of the left subtree will be queued; If an outgoing node has a right subtree, the root node of the right subtree will be queued. (loop until the queue is empty).
3. Pithy formula: root in and out, then left and right
```void LevelOrder(BiTree T){
InQueue(Q);	//Initialize queue
BiTree p;
EnQueue(Q,p); //Root node join
while(!IsEmpty(Q)){ //Loop if queue is not empty
DeQueue(Q,p); //Team leader node out of the team
visit(p);		//Access outbound node
if(p->lchild !=NULL){	//If the left subtree of the visited node is not empty, the root node of the left subtree will be queued
EnQueue(Q,p->lchild);
}
if(p->rchild !=NULL){	//If the right subtree of the visited node is not empty, the root node of the right subtree will be queued
EnQueue(Q,p->rchild);
}
}
}
```

Posted by djot on Wed, 01 Dec 2021 05:04:50 -0800