Forward, middle, and backward traversal of binary trees (non-recursive implementation)

We have mentioned three ways of traversing a binary tree, the first, the second, and the second. Today we will do this non-recursively.

1. Pre-order traversal

We need stacks as a data structure for recursion

1.1 Analysis

• First we stack the root node
• Loop the top element out of the stack at the same time and add the top element to the result set
• Determine if the right child of the current node is empty, not empty on the stack
• Determine if the left child of the current node is empty, not empty on the stack

1.2 Example

Here's a specific example, illustrated by the following figure

First we put root node A on the stack, then we go into a loop

• Print A First
• Next, determine if their right child (C) is empty, find that it is not empty, and stack it
• Next, determine if their left child (B) is empty, find that it is not empty, and stack it

Second Enter Cycle

• Take top element B, print B
• Next, determine if their right child (E) is empty, find that it is not empty, and stack it
• Next, determine if their left child (D) is empty, find that it is not empty, and stack it

Third Enter Cycle

• Take top element D, print D
• Next, it determines if its right child (null) is empty and finds it empty
• Next, it determines if its left child (null) is empty and finds it empty

Fourth Enter Cycle

• Take top element E, print E
• Next, it determines if its right child (null) is empty and finds it empty
• Next, it determines if its left child (null) is empty and finds it empty

Fifth Enter Cycle

• Take top element C, print C
• Next, it determines if its right child (null) is empty and finds it empty
• Next, it determines if its left child (null) is empty and finds it empty

The loop ends, and the results are printed in turn: A B D E C 3. Code implementation

public List<Integer> preorderTraversal4(TreeNode root)
{
ArrayList<Integer> list = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
if (root == null)
{
return list;
}
//First put the root node on the stack
stack.push(root);
//Loop judgment when stack is not empty
while (!stack.isEmpty())
{
//Pop-up top element
TreeNode cur = stack.pop();
//Add its value to the list collection
//If the right child of the current node is not empty, stack it
if (cur.right != null)
{
stack.push(cur.right);
}
//If the left child of the current node is not empty, stack it
if (cur.left != null)
{
stack.push(cur.left);
}
}
return list;
}

2. Medium-order traversal

2.1 Analysis

• Starting from the root node, lookup the left subtree in turn with a loop, and all elements encountered are stacked until empty, exiting the loop
• After reaching the leftmost element, take the top element out of the stack and add it to the result set
• Use the right subtree of the top element of the stack as the starting point, loop left again, and all the elements on the path are stacked

2.2 Example

Here's a specific example, illustrated by the following figure • First, we use a loop to go all the way to the left subtree until it is empty, then stack the A B D ** (stack: A B D at this time)**

• Next, take the top element D of the stack and print D (in this case, stack: A B)

• null right subtree of top stack element D as starting point, found empty

• Next, take the top element B of the stack and print B (in this case, stack: A)

• Start with the right subtree E of top element B and place it on the stack** (stack: A E at this time)**

• Next, take the top element E and print E (stack: A at this point)

• null, the right subtree of element E at the top of the stack, as the starting point, is found to be empty

• Next take top element A and print A** (the stack is empty at this time)**

• Use the right subtree C of element A at the top of the stack as the starting point and place it on the stack (stack: C in this case)

• Next take the top element C and print C (the stack is empty at this time)

End of stack empty

2.3 Code

public List<Integer> inorderTraversal2(TreeNode root)
{
ArrayList<Integer> list = new ArrayList<>();
if (root == null)
{
return list;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (true)
{
//Loop through to the left until empty
while (cur != null)
{
stack.push(cur);
cur = cur.left;
}
//2. If empty, end of traversal
if (stack.isEmpty())
{
break;
}
//3. Take the top element of the stack and access it
TreeNode pop = stack.pop();
//4. Start from the right subtree of the current node
cur = pop.right;
}
return list;
}

3. Post-order traversal

3.1 Analysis

• Starting from the root node, lookup the left subtree in turn with a loop, and all elements encountered are stacked until empty, exiting the loop
• Determine if the top element of the stack (peek is not pop) is accessible (in two cases)
• The top element of the stack has no right subtree, pop it
• The right subtree of the top element of the stack has been visited once and pop ped
• Use the right subtree of the top element of the stack as the starting point, loop left again, and all the elements on the path are stacked

3.2 Example

Here's a specific example, illustrated by the following figure • First, we use a loop to look all the way to the left subtree until it is empty, then stack the A B D (in this case, stack: A B D)
• Next, determine the top element D of the stack, find that it has no right subtree, and print it out of the stack
• null right subtree of top stack element D as starting point, found empty
• Next, determine element B at the top of the stack and find that it has a right subtree, but it has not been visited yet. Use its right subtree as a starting point to start looping left into the stack (stack: A B E at this time)
• Next, determine the top element E, find that it has no right subtree, take it out of the stack and print it
• Next, determine the top element B** (second visit)** and find that it has a right subtree, but has been visited, stack it and print it (stack: A at this time)
• Next, determine element A at the top of the stack and find that it has a right subtree, but it has not been visited yet. Use its right subtree as a starting point to start looping left into the stack (stack: A C at this time)
• Next, determine the top element C of the stack, find that it has no right subtree, and print it out of the stack (stack: A in this case)
• Next, determine the top element A** (second visit)** and find that it has a right subtree, but has been visited, stack it and print it (the stack is empty at this time)
• End

3.3 Code

public List<Integer> postorderTraversal(TreeNode root)
{
ArrayList<Integer> list = new ArrayList<>();
if (root == null)
{
return list;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode pre = null;
while (true)
{
//1. Search left and stack until empty
while (cur != null)
{
stack.push(cur);
cur = cur.left;
}
if (stack.isEmpty())
{
break;
}
//Take out the top element of the stack and check if you can access it
TreeNode top = stack.peek();
//Two conditions to judge
if (top.right == null || pre == top.right)
{
TreeNode pop = stack.pop();
//The last record after the element has been traversed
pre = pop;
}
//If the condition is not satisfied, use the right subtree of the top element of the stack as the starting point, loop left again, and all the elements on the path are stacked
else
{
cur = top.right;
}
}
return list;
}

Keywords: Java

Added by studio805 on Thu, 30 Dec 2021 03:42:19 +0200