Traversal of Binary Trees (Recursive and Non-Recursive)

Posted by Mark.P.W on Thu, 22 Aug 2019 13:46:52 +0200

recursion

1. Preorder traversal (around the root)

void BinaryTreePrevOrder(BTNode* root) //Ordered traversal around the root (recursion)
{
	if (root)
	{
		putchar(root->data);//Print the root node
		BinaryTreePrevOrder(root->lchild);
		BinaryTreePrevOrder(root->rchild);
	}	
}

2. Mid-order traversal (left root right)

void BinaryTreeInOrder(BTNode* root) //Middle-order traversal of left root and right root (recursion)
{
	if (root)
	{
		BinaryTreeInOrder(root->lchild);
		putchar(root->data);
		BinaryTreeInOrder(root->rchild);
	}
	
}

3. Post-order traversal (left and right roots)

void BinaryTreePostOrder(BTNode* root)//Later order traverses left and right roots (recursion)
{
	if (root)
	{
		BinaryTreePostOrder(root->lchild);
		BinaryTreePostOrder(root->rchild);
		putchar(root->data);
		
	}
}

Non-recursive (need to be implemented with stacks)

Code for the stack to be used

void StackInit(Stack* psl, size_t capicity)
{
	assert(psl);
	psl->capicity = capicity;
	psl->array = (SLDataType *)malloc(capicity * sizeof(SLDataType));
	assert(psl->array);

	psl->size = 0;
}
void StackDestory(Stack* psl)
{
	assert(psl);
	if (psl->array)
	{
		free(psl->array);
		psl->array = NULL;
		psl->size = 0;
		psl->capicity = 0;
	}
}
void CheckCapacity(Stack* psl)
{
	assert(psl);
	if (psl->size == psl->capicity)
	{
		psl->capicity *= 2;
		psl->array = (SLDataType *)realloc(psl->array, psl->capicity * sizeof(SLDataType));

	}
}
void StackPush(Stack* psl, SLDataType x)
{
	assert(psl);
	CheckCapacity(psl);

	psl->array[psl->size] = x;
	psl->size++;
}
void StackPop(Stack* psl)
{
	assert(psl || psl->size);
	psl->size--;

}
SLDataType StackTop(Stack* psl)
{
	if (StackIsEmpty(psl))
	{
		return (SLDataType)0;
	}
	return psl->array[psl->size - 1];
}
int StackIsEmpty(Stack * psl)
{
	return psl->size == 0;
}


1. Preorder traversal

(1) Print the current node

(2) If it has a right child, it will all be on the stack.

(3) If it has a left child, visit the left child; if not, visit the top of the stack.

void BinaryTreePrevOrderNonR(BTNode* root) // Preorder traversal (non-recursive)
{
	Stack st;
	BTNode * cur = root;
	StackInit(&st, 100); //Initialization stack
	while (cur) 
	{
		putchar(cur->data); //Print the value of the current root node
		if (cur->rchild) //Right child exists
		{
			StackPush(&st, cur->rchild); //Right kid in the stack
		}
		if (cur->lchild) //Left child exists
		{
			cur = cur->lchild; //The root node is the left child
		}
		else//No left child takes the top of the stack
		{
			cur = StackTop(&st); //Take the space-time and end the traversal
			StackPop(&st); //Stack out
		}
	}
	StackDestory(&st);
}

2. Mid-order traversal

(1) Traverse the left subtree from the current node and stack all the nodes until the left subtree is empty.

(2) Remove and print the top of the stack, visit its right child, if the right child, repeat process 1, if there is no right child, repeat process 2

void BinaryTreeInOrderNonR(BTNode* root) //Ordered traversal (non-recursive)
{
	Stack st;
	BTNode* cur = root;
	StackInit(&st,100);
	while (cur || !StackIsEmpty(&st))//(1)
	{
		for (; cur; cur = cur->lchild)//Stack the current node and the left child (list traversal)
		{
			StackPush(&st, cur);
		}
		    cur = StackTop(&st);//Remove the top of the stack (1. The right child is empty, for loop does not directly take the top of the stack.
			//2. If the right child is not empty, then this is a node without the left child.
			//The first case is that the left subtree has been visited, and the second case is that the right subtree is empty.
			//Either way, the current node should be printed.)
			/*if (!cur )
			{
			break;
			}*/
			putchar(cur->data);
			StackPop(&st);
			cur = cur->rchild;
		
	}
	StackDestory(&st);
}

3. Postorder traversal

LT = left subtree access tag, the tag array in the code

(1) Traverse the left subtree from the current node, stack all the nodes, and empty the LT tag until the left subtree is empty, then enter process 2.

(2) Access the top of the stack, place its LT tag, access its right subtree, if the right subtree exists, repeat process 1, if the right subtree does not exist, enter process 3

(3) Remove the top of the stack, print, and then check whether the LT of its parent node is also positioned. If so, print together until the location of the node marked as empty by the first LT is found, and then return to Procedure 2.

void BinaryTreePostOrderNonR(BTNode* root)//Post-order traversal (non-recursive)
{
	char tag[64];
	Stack st;
	BTNode* cur = root;
	StackInit(&st, 100);

	do
	{
		for (; cur; cur = cur->lchild)//Stack the current node and the left child (list traversal)
		{
			StackPush(&st, cur);//Left child in the stack
			tag[st.size - 1] = 0;//Reset left subtree access tag (LT)
		}
		while (!StackIsEmpty(&st)&&tag[st.size - 1])//The stack is not empty and marked 1 
			//The preceding condition only takes effect when the last cycle jumps out.
			//The latter condition can be divided into two cases.
			//1. When cur is empty, the above for does not enter. This condition holds.
			//2. When cur is not empty, the above condition does not hold.
			//If the current LT is detected to be positioned, then after printing the current node, go directly to check that the previous node (parent node) is also printed.
		{
			cur = StackTop(&st); //Take the top of the stack
			putchar(cur->data);//Printing
			StackPop(&st);//Stack out
		}
		if (!StackIsEmpty(&st))//The stack is not empty // This condition only takes effect when the last loop jumps out
		{
			cur = StackTop(&st);//Take the top of the stack
			//1. If the while above is in, then prove that the left subtree has been accessed and put LT in place.
			//2. If the white above does not enter, then prove that the left subtree does not exist and place LT
			tag[st.size - 1] = 1;//Marker changed to 1
			cur = cur->rchild; //Take the right child
			//After accessing the left subtree, access the right subtree
		}
			//
	} while (!StackIsEmpty(&st));//Because the stack cannot be empty before the root node finally leaves the stack in post-order traversal, it is judged whether the root node is empty or not.
	StackDestory(&st);
}

4. Sequence traversal (requiring queue assistance)

Code for queues

void QueueInit(Queue* plist)
{
	assert(plist);
	plist->_head = NULL;
	plist->_rear = NULL;

}
void QueueDestory(Queue* plist)
{
	QueueNode * tmp;
	while (plist->_head)
	{
		tmp = plist->_head;
		plist->_head = plist->_head->_next;
		free(tmp);
	}
}

void QueuePop(Queue* plist)
{
	assert(plist);
	QueueNode * tmp;
	if (plist->_head)
	{
		tmp = plist->_head;
		plist->_head = plist->_head->_next;
		free(tmp);
	}
}
void QueuePush(Queue* plist, QuDataType x)
{
	QueueNode * cur = (QueueNode *)malloc(sizeof(QueueNode));
	cur->_data = x;
	cur->_next = NULL;
	if (QueueIsEmpty(plist))
	{
		plist->_head = plist->_rear = cur;
		return;
	}
	plist->_rear->_next = cur;
	plist->_rear = cur;
}

int QueueIsEmpty(Queue * plist)
{
	return plist->_head == NULL;
}
QuDataType QueueTop(Queue *plist)
{
	if (QueueIsEmpty(plist))
	{
		return (QuDataType)0;
	}
	return plist->_head->_data;
}

Realization of Sequence Traverse

First put the root in the column

(1) Take the top of the team to print

(2) If it has a left child, it will join the team with a left child, and if it has a right child, it will join the team with a right child.

(3) Team top out

void BinaryTreeLeveorder(BTNode* root)//level traversal
{
	Queue qu;
	BTNode * cur;
	QueueInit(&qu);//Initialization queue
	QueuePush(&qu, root);//Enter the queue
	while (!QueueIsEmpty(&qu))//The queue is not empty
	{
		cur = QueueTop(&qu); //cur equals the head of the queue
		putchar(cur->data); //Output cur
		if (cur->lchild) // Left child exists
		{
			QueuePush(&qu, cur->lchild);//Left children in the queue
		}
		if (cur->rchild)//Right child exists
		{
			QueuePush(&qu, cur->rchild); //The right child joined the queue
		}
		QueuePop(&qu);//Head element out of queue
	}
	QueueDestory(&qu);//Destruction
}