My code to check if a linkedlist is a palindrome or not is not working - data-structures

class Solution
{
//Function to check whether the list is palindrome.
boolean isPalindrome(Node head)
{
//Your code here
List<Integer> list = new List<>();
Node currNode = head;
while(currNode != null){
list.add(currNode.data);
currNode = currNode.next;
}
List rev_list = list.reverseIterate();
return list.equals(rev_list);
}
public void reverseIterate(){
if(head == null || head.next == null){
return;
}
// 4 --> 5 --> 6
//prevNode currNode nextNode
//head head.next currNode.next
Node prevNode = head;//4
Node currNode = head.next;//5
while(currNode != null){
Node nextNode = currNode.next;//6
currNode.next = prevNode;//currNode.next = 4
//update: prevNode = 4
prevNode = currNode;//prevNode = 5
currNode = nextNode;//currNode = 6
}
head.next = null;//one connection was left, so we cut that and the next of the initial head points towards null
head = prevNode;// the highest value needs to become the head of the LinkedList
}
}
I have used a reversIterate() function to reverse the linkedlist and store it in another list called rev_list. Then I have used the list equals method to compare the two lists...but the compiler is throwing errors.

Related

Binary Search Tree using the find method

I am trying to use the find() method for BST. However, I am encountering errors when I place the 'if' statement incorrectly. When I swap the following 2 lines, my code gave me an error TypeError: Cannot read properties of null (reading 'val'). However, if I used a "else if" for the second statement, it works. Not sure why.
if (val > current.val) current = current.right // these 2 lines were swapped which gave an error
if (val < current.val) current = current.left // these 2 lines were swapped which gave an error
Below is the full code.
class Node {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
class BST {
constructor() {
this.root = null;
}
insert(val) {
let newNode = new Node(val)
if (!this.root) {
this.root = newNode
return this;
}
let current = this.root
while (true) {
if (val === current.val) return undefined
if (val < current.val) {
if (current.left === null) {
current.left = newNode
return this;
} else {
current = current.left
}
}
if (val > current.val) {
if (current.right === null) {
current.right = newNode
return this;
} else {
current = current.right
}
}
}
}
find(val) {
if (!this.root) return false
let current = this.root
while (current) {
if (val === current.val) return true
console.log(current.val)
if (val > current.val) current = current.right // these 2 lines were swapped
if (val < current.val) current = current.left // these 2 lines were swapped
}
return false
}
}
let tree = new BST();
console.log(tree.insert(10));
console.log(tree.insert(5));
console.log(tree.insert(13));
console.log(tree.insert(11));
console.log(tree.insert(2));
console.log(tree.insert(16));
console.log(tree.insert(7));
console.log(tree.find(333))
Because you ask on your second "if" about the current.val but on the first "if" you change the current to null (when you got to the end of the tree), this is why you should use "else if" or to ask if the current == null before you ask about it again.
Notice that if you swap between the lines it won't solve the problem, just transfer the exception to the cases when you have an item that is smaller than any other element in the tree.

HackerRank: Inserting a Node Into a Sorted Doubly Linked List - Kotlin

Just wondering if someone would be able to help me on a kotlin implementation of the Hackerrank question https://www.hackerrank.com/challenges/insert-a-node-into-a-sorted-doubly-linked-list/problem
I came to the following solution which is only passing 3 out of the 8 tests.
I am confused as to what I am doing incorrectly, as when I searched the internet, I found a Java solution which is very similar - https://www.geeksforgeeks.org/insert-value-sorted-way-sorted-doubly-linked-list/
Any help would be appreciated, I'm at a loss with it.
fun sortedInsert(llist: DoublyLinkedListNode?, data: Int): DoublyLinkedListNode? {
val node = DoublyLinkedListNode(data)
if (llist == null) return node
if (llist.data >= data) {
node.next = llist
node.next!!.prev = node
return node
}
var current = llist
while (current?.next != null && current.next!!.data < data) {
current = current.next
}
node.next = current?.next
if (current?.next != null) current.next!!.prev = node
node.prev = current
current?.next = node
return llist
}
HackerRank's test harness appears to be broken for Kotlin, missing a println to separate output for each test case. The reason some pass (including sample tests) is that t=1 for these, so the bug isn't triggered.
See the problem's discussion thread for more complaints about the issue. Some of the complaints go back 3 years as of December 2021, suggesting that this is not a high priority for HR to fix, if they're even aware of the issue. Furthermore, the problem appears to affect boilerplate in other linked list problems in Kotlin such as Reverse a Doubly Linked List.
Here's your code translated into Java 15, which passed HackerRank's judge:
public static DoublyLinkedListNode sortedInsert(
DoublyLinkedListNode llist, int data
) {
var node = new DoublyLinkedListNode(data);
if (llist == null) return node;
if (llist.data >= data) {
node.next = llist;
node.next.prev = node;
return node;
}
var current = llist;
while (current.next != null && current.next.data < data) {
current = current.next;
}
node.next = current.next;
if (current.next != null) current.next.prev = node;
node.prev = current;
current.next = node;
return llist;
}

What's the difference about LinkedList?

public ListNode deleteDuplicates(ListNode head) {
ListNode current = head;
while (current != null && current.next != null) {
if (current.next.val == current.val) {
current.next = current.next.next;
} else {
current = current.next;
}
}
return head;
}
This is a program that delete duplicated value node from LinkedList(e.g. [1,1,2,3,4,4]→[1,2,3,4]).
I am wondering why "current.next = current.next.next;" delete "current.next" with "current.next.next" and "current = current.next;" move pointer to "current.next".
For me, Looks like both are "delete program".
it's very easy to understand ,let me take a picture for you.
//this means No1 Node.next is forward to No3 Node,then No2 Node is remove
current.next = current.next.next;
//this means No1 Node reference is forward No2 Node,can't change No1 Node next reference
current = current.next;
the picture will tell your

How can I find a middle element in a linked list?

How can I find a middle element in a linked list by traversing the entire list only once?
The length of the list is not given, and I am allowed to only use two pointers. How can this be done?
I don't see how you could do it without traversing the entire list unless you know the length.
I'm guessing the answer wants one pointer to be traversing one element at a time, while the second pointer moves 2 elements at a time.
This way when the second pointer reaches the end, the first pointer will be at the middle.
The below code will help you get the middle element.
You need to use two pointers "fast" and "slow". At every step the fast pointer will increment by two and slower will increment by one. When the list will end the slow pointer will be at the middle.
Let us consider the Node looks like this
class Node
{
int data;
Node next;
}
And LinkedList has a getter method to provide the head of the linked list
public Node getHead()
{
return this.head;
}
The below method will get the middle element of the list (Without knowing the size of the list)
public int getMiddleElement(LinkedList l)
{
return getMiddleElement(l.getHead());
}
private int getMiddleElement(Node n)
{
Node slow = n;
Node fast = n;
while(fast!=null && fast.next!=null)
{
fast = fast.next.next;
slow = slow.next;
}
return slow.data;
}
Example:
If the list is 1-2-3-4-5 the middle element is 3
If the list is 1-2-3-4 the middle element is 3
In C, using pointers, for completeness. Note that this is based on the "Tortoise and Hare" algorithm used for checking if a linked list contains a cycle.
Our node is defined as the following:
typedef struct node {
int val;
struct node *next;
} node_t;
Then our algorithm is thus:
node_t *
list_middle (node_t *root)
{
node_t *tort = root;
node_t *hare = root;
while (hare != NULL && hare->next != NULL) {
tort = tort->next;
hare = hare->next->next;
}
return (tort);
}
For a list with an even number of nodes this returns the node proceding the actual centre (e.g. in a list of 10 nodes, this will return node 6).
There are two possible answers one for odd and one for even, both having the same algorithm
For odd: One pointer moves one step and second pointer moves two element as a time and when the second elements reach the last element, the element at which the first pointer is, the mid element. Very easy for odd.
Try: 1 2 3 4 5
For even: Same, One pointer moves one step and second pointer moves two element as a time and when the second elements cannot jump to next element, the element at which the first pointer is, the mid element.
Try: 1 2 3 4
LinkedList.Node current = head;
int length = 0;
LinkedList.Node middle = head;
while(current.next() != null){
length++;
if(length%2 ==0){
middle = middle.next();
}
current = current.next();
}
if(length%2 == 1){
middle = middle.next();
}
System.out.println("length of LinkedList: " + length);
System.out.println("middle element of LinkedList : " + middle);
Using a size variable you can maintain the size of the Linked list.
public class LinkedList {
private Node headnode;
private int size;
public void add(int i) {
Node node = new Node(i);
node.nextNode = headnode;
headnode = node;
size++;
}
public void findMiddleNode(LinkedList linkedList, int middle) {
Node headnode = linkedList.getHeadnode();
int count = -1;
while (headnode != null) {
count++;
if(count == middle) {
System.out.println(headnode.data);
}else {
headnode = headnode.nextNode;
}
}
}
private class Node {
private Node nextNode;
private int data;
public Node(int data) {
this.data = data;
this.nextNode = null;
}
}
public Node getHeadnode() {
return headnode;
}
public int getSize() {
return size;
}
}
Then from a client method find the middle of the size of the list:
public class MainLinkedList {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(5);
linkedList.add(3);
linkedList.add(9);
linkedList.add(4);
linkedList.add(7);
linkedList.add(99);
linkedList.add(34);
linkedList.add(798);
linkedList.add(45);
linkedList.add(99);
linkedList.add(46);
linkedList.add(22);
linkedList.add(22);
System.out.println(linkedList.getSize());
int middle = linkedList.getSize()/2;
linkedList.findMiddleNode(linkedList, middle);
}
}
I don’t know if this is better than the two node way, but here also you don’t have to traverse through the entire loop.
Using C# to find a middle element of the linked list:
static void Main(string[] args)
{
LinkedList<int> linked = new LinkedList<int>();
linked.AddLast(1);
linked.AddLast(3);
linked.AddLast(5);
linked.AddLast(6);
linked.AddFirst(12);
Console.WriteLine("Middle Element - " + ListMiddle<int>(linked));
Console.ReadLine();
}
public static T ListMiddle<T>(IEnumerable<T> input)
{
if (input == null)
return default(T);
var slow = input.GetEnumerator();
var fast = input.GetEnumerator();
while (slow.MoveNext())
{
if (fast.MoveNext())
{
if (!fast.MoveNext())
return slow.Current;
}
else
{
return slow.Current;
}
}
return slow.Current;
}
The below Java methods finds the middle of a linked list. It uses two pointers:
Slow pointers which moves by one in each iteration.
A fast pointer which moves twice in each iteration.
The slow pointer will point to the middle when fast reaches the end of the list
public SinglyLinkedListNode getMiddle(SinglyLinkedListNode list) {
if (list == null)
return null;
SinglyLinkedListNode fastPtr = list.next;
SinglyLinkedListNode slowPtr = list;
while (fastPtr != null) {
fastPtr = fastPtr.next;
if (fastPtr != null) {
slowPtr = slowPtr.next;
fastPtr = fastPtr.next;
}
}
return slowPtr;
}
For a doubly-linked list with given pointers to the head and tail node:
We can use both head and tail traversal:
p = head;
q = tail;
while(p != q && p->next != q)
{
p = p->next;
q = q->prev;
}
return p;
Introducing a pointer to the middle node may be an option, but functions like insertNode and deleteNode have to modify this pointer.
Python code for a middle element using the two-pointer method:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def printList(self):
temp = self.head
while(temp):
print(temp.data, end=" ")
temp = temp.next
def insertAtBeg(self, new_data):
new_node = Node(new_data)
if self.head is None:
self.head = new_node
return
new_node.next = self.head
self.head = new_node
def findMiddle(self):
fast_ptr = self.head
slow_ptr = self.head
if(self.head is not None):
while(fast_ptr is not None and fast_ptr.next is not None):
fast_ptr = fast_ptr.next.next
slow_ptr = slow_ptr.next
print('The middle element is ' + str (slow_ptr.data))
if __name__ == '__main__':
mylist = LinkedList()
mylist.insertAtBeg(10)
mylist.insertAtBeg(20)
mylist.insertAtBeg(30)
mylist.findMiddle()
Output:
The middle element is
import java.util.*;
public class MainLinkedList {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(10);
linkedList.add(32);
linkedList.add(90);
linkedList.add(43);
linkedList.add(70);
linkedList.add(20);
linkedList.add(45);
int middle = linkedList.size()/2;
System.out.println(linkedList.get(middle));
}
}
I am adding my solution which will work for both odd and even number of elements scenarios like:
1-2-3-4-5 middle element 3
1-2-3-4 middle element 2,3
It is inspired by the same fast pointer and slow pointer principle as mentioned in some of the other answers in the post.
public class linkedlist {
Node head;
static class Node {
int data;
Node next;
Node(int d) { data = d; next=null; }
}
public static void main(String args[]) {
linkedlist ll = new linkedlist();
Node one = new Node(1);
Node second = new Node(2);
Node third = new Node(3);
Node fourth = new Node(4);
Node five = new Node(5);
Node sixth = new Node(6);
Node seventh = new Node(7);
Node eight = new Node(8);
ll.head = one;
one.next = second;
second.next = third;
third.next = fourth;
fourth.next = five;
five.next = sixth;
sixth.next = seventh;
seventh.next = eight;
ll.printList();
ll.middleElement();
}
public void printList() {
Node n = head;
while(n != null) {
System.out.print(n.data + " ---> ");
n = n.next;
}
}
public void middleElement() {
Node headPointer = head;
Node headFasterPointer = head;
int counter = 0;
if(head != null) {
while(headFasterPointer.next != null) {
if(headFasterPointer.next.next != null) {
headFasterPointer = headFasterPointer.next.next;
headPointer = headPointer.next;
}
else
{
headFasterPointer = headFasterPointer.next;
}
counter++;
}
System.out.println();
System.out.println("The value of counter is " + counter);
if(counter %2 == 0) {
System.out.println("The middle element is " + headPointer.data + "," + headPointer.next.data);
}
else
{
System.out.println("The middle element is " + headPointer.data);
}
}
}
}
Class Node:
# Function to initialise the node object
def __init__(self, data):
self.data = data
self.next = None
Class LinkedList:
def __init__(self):
self.head = None
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
# Function to get the middle of
# the linked list
def printMiddle(self):
slow_ptr = self.head
fast_ptr = self.head
if self.head is not None:
while (fast_ptr is not None and fast_ptr.next is not None):
fast_ptr = fast_ptr.next.next
slow_ptr = slow_ptr.next
print("The middle element is: ", slow_ptr.data)
Driver code
list1 = LinkedList()
list1.push(5)
list1.push(4)
list1.push(2)
list1.push(3)
list1.push(1)
list1.printMiddle()
It's stupid to use two pointers, "fast" and "slow", because the operator next is used 1.5n times. There is no optimization.
Using a pointer to save the middle element can help you:
list* find_mid_1(list* ptr)
{
list *p_s1 = ptr, *p_s2 = ptr;
while (p_s2=p_s2->get_next())
{
p_s2 = p_s2->get_next();
if (!p_s2)
break;
p_s1 = p_s1->get_next();
}
return p_s1;
}

Post order traversal of binary tree without recursion

What is the algorithm for doing a post order traversal of a binary tree WITHOUT using recursion?
Here's the version with one stack and without a visited flag:
private void postorder(Node head) {
if (head == null) {
return;
}
LinkedList<Node> stack = new LinkedList<Node>();
stack.push(head);
while (!stack.isEmpty()) {
Node next = stack.peek();
boolean finishedSubtrees = (next.right == head || next.left == head);
boolean isLeaf = (next.left == null && next.right == null);
if (finishedSubtrees || isLeaf) {
stack.pop();
System.out.println(next.value);
head = next;
}
else {
if (next.right != null) {
stack.push(next.right);
}
if (next.left != null) {
stack.push(next.left);
}
}
}
}
Here's a link which provides two other solutions without using any visited flags.
https://leetcode.com/problems/binary-tree-postorder-traversal/
This is obviously a stack-based solution due to the lack of parent pointer in the tree. (We wouldn't need a stack if there's parent pointer).
We would push the root node to the stack first. While the stack is not empty, we keep pushing the left child of the node from top of stack. If the left child does not exist, we push its right child. If it's a leaf node, we process the node and pop it off the stack.
We also use a variable to keep track of a previously-traversed node. The purpose is to determine if the traversal is descending/ascending the tree, and we can also know if it ascend from the left/right.
If we ascend the tree from the left, we wouldn't want to push its left child again to the stack and should continue ascend down the tree if its right child exists. If we ascend the tree from the right, we should process it and pop it off the stack.
We would process the node and pop it off the stack in these 3 cases:
The node is a leaf node (no children)
We just traverse up the tree from the left and no right child exist.
We just traverse up the tree from the right.
Here's a sample from wikipedia:
nonRecursivePostorder(rootNode)
nodeStack.push(rootNode)
while (! nodeStack.empty())
currNode = nodeStack.peek()
if ((currNode.left != null) and (currNode.left.visited == false))
nodeStack.push(currNode.left)
else
if ((currNode.right != null) and (currNode.right.visited == false))
nodeStack.push(currNode.right)
else
print currNode.value
currNode.visited := true
nodeStack.pop()
This is the approach I use for iterative, post-order traversal. I like this approach because:
It only handles a single transition per loop-cycle, so it's easy to follow.
A similar solution works for in-order and pre-order traversals
Code:
enum State {LEFT, RIGHT, UP, CURR}
public void iterativePostOrder(Node root) {
Deque<Node> parents = new ArrayDeque<>();
Node curr = root;
State state = State.LEFT;
while(!(curr == root && state == State.UP)) {
switch(state) {
case LEFT:
if(curr.left != null) {
parents.push(curr);
curr = curr.left;
} else {
state = RIGHT;
}
break;
case RIGHT:
if(curr.right != null) {
parents.push(curr);
curr = curr.right;
state = LEFT;
} else {
state = CURR;
}
break;
case CURR:
System.out.println(curr);
state = UP;
break;
case UP:
Node child = curr;
curr = parents.pop();
state = child == curr.left ? RIGHT : CURR;
break;
default:
throw new IllegalStateException();
}
}
}
Explanation:
You can think about the steps like this:
Try LEFT
if left-node exists: Try LEFT again
if left-node does not exist: Try RIGHT
Try RIGHT
If a right node exists: Try LEFT from there
If no right exists, you're at a leaf: Try CURR
Try CURR
Print current node
All nodes below have been executed (post-order): Try UP
Try UP
If node is root, there is no UP, so EXIT
If coming up from left, Try RIGHT
If coming up from right, Try CURR
Here is a solution in C++ that does not require any storage for book keeping in the tree.
Instead it uses two stacks. One to help us traverse and another to store the nodes so we can do a post traversal of them.
std::stack<Node*> leftStack;
std::stack<Node*> rightStack;
Node* currentNode = m_root;
while( !leftStack.empty() || currentNode != NULL )
{
if( currentNode )
{
leftStack.push( currentNode );
currentNode = currentNode->m_left;
}
else
{
currentNode = leftStack.top();
leftStack.pop();
rightStack.push( currentNode );
currentNode = currentNode->m_right;
}
}
while( !rightStack.empty() )
{
currentNode = rightStack.top();
rightStack.pop();
std::cout << currentNode->m_value;
std::cout << "\n";
}
import java.util.Stack;
public class IterativePostOrderTraversal extends BinaryTree {
public static void iterativePostOrderTraversal(Node root){
Node cur = root;
Node pre = root;
Stack<Node> s = new Stack<Node>();
if(root!=null)
s.push(root);
System.out.println("sysout"+s.isEmpty());
while(!s.isEmpty()){
cur = s.peek();
if(cur==pre||cur==pre.left ||cur==pre.right){// we are traversing down the tree
if(cur.left!=null){
s.push(cur.left);
}
else if(cur.right!=null){
s.push(cur.right);
}
if(cur.left==null && cur.right==null){
System.out.println(s.pop().data);
}
}else if(pre==cur.left){// we are traversing up the tree from the left
if(cur.right!=null){
s.push(cur.right);
}else if(cur.right==null){
System.out.println(s.pop().data);
}
}else if(pre==cur.right){// we are traversing up the tree from the right
System.out.println(s.pop().data);
}
pre=cur;
}
}
public static void main(String args[]){
BinaryTree bt = new BinaryTree();
Node root = bt.generateTree();
iterativePostOrderTraversal(root);
}
}
// the java version with flag
public static <T> void printWithFlag(TreeNode<T> root){
if(null == root) return;
Stack<TreeNode<T>> stack = new Stack<TreeNode<T>>();
stack.add(root);
while(stack.size() > 0){
if(stack.peek().isVisit()){
System.out.print(stack.pop().getValue() + " ");
}else{
TreeNode<T> tempNode = stack.peek();
if(tempNode.getRight()!=null){
stack.add(tempNode.getRight());
}
if(tempNode.getLeft() != null){
stack.add(tempNode.getLeft());
}
tempNode.setVisit(true);
}
}
}
Depth first, post order, non recursive, without stack
When you have parent:
node_t
{
left,
right
parent
}
traverse(node_t rootNode)
{
bool backthreading = false
node_t node = rootNode
while(node <> 0)
if (node->left <> 0) and backthreading = false then
node = node->left
continue
endif
>>> process node here <<<
if node->right <> 0 then
lNode = node->right
backthreading = false
else
node = node->parent
backthreading = true
endif
endwhile
The logic of Post order traversal without using Recursion
In Postorder traversal, the processing order is left-right-current. So we need to visit the left section first before visiting other parts. We will try to traverse down to the tree as left as possible for each node of the tree. For each current node, if the right child is present then push it into the stack before pushing the current node while root is not NULL/None. Now pop a node from the stack and check whether the right child of that node exists or not. If it exists, then check whether it's same as the top element or not. If they are same then it indicates that we are not done with right part yet, so before processing the current node we have to process the right part and for that pop the top element(right child) and push the current node back into the stack. At each time our head is the popped element. If the current element is not the same as the top and head is not NULL then we are done with both the left and right section so now we can process the current node. We have to repeat the previous steps until the stack is empty.
def Postorder_iterative(head):
if head is None:
return None
sta=stack()
while True:
while head is not None:
if head.r:
sta.push(head.r)
sta.push(head)
head=head.l
if sta.top is -1:
break
head = sta.pop()
if head.r is not None and sta.top is not -1 and head.r is sta.A[sta.top]:
x=sta.pop()
sta.push(head)
head=x
else:
print(head.val,end = ' ')
head=None
print()
void postorder_stack(Node * root){
stack ms;
ms.top = -1;
if(root == NULL) return ;
Node * temp ;
push(&ms,root);
Node * prev = NULL;
while(!is_empty(ms)){
temp = peek(ms);
/* case 1. We are nmoving down the tree. */
if(prev == NULL || prev->left == temp || prev->right == temp){
if(temp->left)
push(&ms,temp->left);
else if(temp->right)
push(&ms,temp->right);
else {
/* If node is leaf node */
printf("%d ", temp->value);
pop(&ms);
}
}
/* case 2. We are moving up the tree from left child */
if(temp->left == prev){
if(temp->right)
push(&ms,temp->right);
else
printf("%d ", temp->value);
}
/* case 3. We are moving up the tree from right child */
if(temp->right == prev){
printf("%d ", temp->value);
pop(&ms);
}
prev = temp;
}
}
Please see this full Java implementation. Just copy the code and paste in your compiler. It will work fine.
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
class Node
{
Node left;
String data;
Node right;
Node(Node left, String data, Node right)
{
this.left = left;
this.right = right;
this.data = data;
}
public String getData()
{
return data;
}
}
class Tree
{
Node node;
//insert
public void insert(String data)
{
if(node == null)
node = new Node(null,data,null);
else
{
Queue<Node> q = new LinkedList<Node>();
q.add(node);
while(q.peek() != null)
{
Node temp = q.remove();
if(temp.left == null)
{
temp.left = new Node(null,data,null);
break;
}
else
{
q.add(temp.left);
}
if(temp.right == null)
{
temp.right = new Node(null,data,null);
break;
}
else
{
q.add(temp.right);
}
}
}
}
public void postorder(Node node)
{
if(node == null)
return;
postorder(node.left);
postorder(node.right);
System.out.print(node.getData()+" --> ");
}
public void iterative(Node node)
{
Stack<Node> s = new Stack<Node>();
while(true)
{
while(node != null)
{
s.push(node);
node = node.left;
}
if(s.peek().right == null)
{
node = s.pop();
System.out.print(node.getData()+" --> ");
if(node == s.peek().right)
{
System.out.print(s.peek().getData()+" --> ");
s.pop();
}
}
if(s.isEmpty())
break;
if(s.peek() != null)
{
node = s.peek().right;
}
else
{
node = null;
}
}
}
}
class Main
{
public static void main(String[] args)
{
Tree t = new Tree();
t.insert("A");
t.insert("B");
t.insert("C");
t.insert("D");
t.insert("E");
t.postorder(t.node);
System.out.println();
t.iterative(t.node);
System.out.println();
}
}
Here I am pasting different versions in c# (.net) for reference:
(for in-order iterative traversal you may refer to: Help me understand Inorder Traversal without using recursion)
wiki (http://en.wikipedia.org/wiki/Post-order%5Ftraversal#Implementations) (elegant)
Another version of single stack
(#1 and #2: basically uses the fact that in post order traversal the right child node is visited before visiting the actual node - so, we simply rely on the check that if stack top's right child is indeed the last post order traversal node thats been visited - i have added comments in below code snippets for details)
Using Two stacks version (ref: http://www.geeksforgeeks.org/iterative-postorder-traversal/)
(easier: basically post order traversal reverse is nothing but pre order traversal with a simple tweak that right node is visited first, and then left node)
Using visitor flag (easy)
Unit Tests
~
public string PostOrderIterative_WikiVersion()
{
List<int> nodes = new List<int>();
if (null != this._root)
{
BinaryTreeNode lastPostOrderTraversalNode = null;
BinaryTreeNode iterativeNode = this._root;
Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();
while ((stack.Count > 0)//stack is not empty
|| (iterativeNode != null))
{
if (iterativeNode != null)
{
stack.Push(iterativeNode);
iterativeNode = iterativeNode.Left;
}
else
{
var stackTop = stack.Peek();
if((stackTop.Right != null)
&& (stackTop.Right != lastPostOrderTraversalNode))
{
//i.e. last traversal node is not right element, so right sub tree is not
//yet, traversed. so we need to start iterating over right tree
//(note left tree is by default traversed by above case)
iterativeNode = stackTop.Right;
}
else
{
//if either the iterative node is child node (right and left are null)
//or, stackTop's right element is nothing but the last traversal node
//(i.e; the element can be popped as the right sub tree have been traversed)
var top = stack.Pop();
Debug.Assert(top == stackTop);
nodes.Add(top.Element);
lastPostOrderTraversalNode = top;
}
}
}
}
return this.ListToString(nodes);
}
Here is post order traversal with one stack (my version)
public string PostOrderIterative()
{
List<int> nodes = new List<int>();
if (null != this._root)
{
BinaryTreeNode lastPostOrderTraversalNode = null;
BinaryTreeNode iterativeNode = null;
Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();
stack.Push(this._root);
while(stack.Count > 0)
{
iterativeNode = stack.Pop();
if ((iterativeNode.Left == null)
&& (iterativeNode.Right == null))
{
nodes.Add(iterativeNode.Element);
lastPostOrderTraversalNode = iterativeNode;
//make sure the stack is not empty as we need to peek at the top
//for ex, a tree with just root node doesn't have to enter loop
//and also node Peek() will throw invalidoperationexception
//if it is performed if the stack is empty
//so, it handles both of them.
while(stack.Count > 0)
{
var stackTop = stack.Peek();
bool removeTop = false;
if ((stackTop.Right != null) &&
//i.e. last post order traversal node is nothing but right node of
//stacktop. so, all the elements in the right subtree have been visted
//So, we can pop the top element
(stackTop.Right == lastPostOrderTraversalNode))
{
//in other words, we can pop the top if whole right subtree is
//traversed. i.e. last traversal node should be the right node
//as the right node will be traverse once all the subtrees of
//right node has been traversed
removeTop = true;
}
else if(
//right subtree is null
(stackTop.Right == null)
&& (stackTop.Left != null)
//last traversal node is nothing but the root of left sub tree node
&& (stackTop.Left == lastPostOrderTraversalNode))
{
//in other words, we can pop the top of stack if right subtree is null,
//and whole left subtree has been traversed
removeTop = true;
}
else
{
break;
}
if(removeTop)
{
var top = stack.Pop();
Debug.Assert(stackTop == top);
lastPostOrderTraversalNode = top;
nodes.Add(top.Element);
}
}
}
else
{
stack.Push(iterativeNode);
if(iterativeNode.Right != null)
{
stack.Push(iterativeNode.Right);
}
if(iterativeNode.Left != null)
{
stack.Push(iterativeNode.Left);
}
}
}
}
return this.ListToString(nodes);
}
Using two stacks
public string PostOrderIterative_TwoStacksVersion()
{
List<int> nodes = new List<int>();
if (null != this._root)
{
Stack<BinaryTreeNode> postOrderStack = new Stack<BinaryTreeNode>();
Stack<BinaryTreeNode> rightLeftPreOrderStack = new Stack<BinaryTreeNode>();
rightLeftPreOrderStack.Push(this._root);
while(rightLeftPreOrderStack.Count > 0)
{
var top = rightLeftPreOrderStack.Pop();
postOrderStack.Push(top);
if(top.Left != null)
{
rightLeftPreOrderStack.Push(top.Left);
}
if(top.Right != null)
{
rightLeftPreOrderStack.Push(top.Right);
}
}
while(postOrderStack.Count > 0)
{
var top = postOrderStack.Pop();
nodes.Add(top.Element);
}
}
return this.ListToString(nodes);
}
With visited flag in C# (.net):
public string PostOrderIterative()
{
List<int> nodes = new List<int>();
if (null != this._root)
{
BinaryTreeNode iterativeNode = null;
Stack<BinaryTreeNode> stack = new Stack<BinaryTreeNode>();
stack.Push(this._root);
while(stack.Count > 0)
{
iterativeNode = stack.Pop();
if(iterativeNode.visted)
{
//reset the flag, for further traversals
iterativeNode.visted = false;
nodes.Add(iterativeNode.Element);
}
else
{
iterativeNode.visted = true;
stack.Push(iterativeNode);
if(iterativeNode.Right != null)
{
stack.Push(iterativeNode.Right);
}
if(iterativeNode.Left != null)
{
stack.Push(iterativeNode.Left);
}
}
}
}
return this.ListToString(nodes);
}
The definitions:
class BinaryTreeNode
{
public int Element;
public BinaryTreeNode Left;
public BinaryTreeNode Right;
public bool visted;
}
string ListToString(List<int> list)
{
string s = string.Join(", ", list);
return s;
}
Unit Tests
[TestMethod]
public void PostOrderTests()
{
int[] a = { 13, 2, 18, 1, 5, 17, 20, 3, 6, 16, 21, 4, 14, 15, 25, 22, 24 };
BinarySearchTree bst = new BinarySearchTree();
foreach (int e in a)
{
string s1 = bst.PostOrderRecursive();
string s2 = bst.PostOrderIterativeWithVistedFlag();
string s3 = bst.PostOrderIterative();
string s4 = bst.PostOrderIterative_WikiVersion();
string s5 = bst.PostOrderIterative_TwoStacksVersion();
Assert.AreEqual(s1, s2);
Assert.AreEqual(s2, s3);
Assert.AreEqual(s3, s4);
Assert.AreEqual(s4, s5);
bst.Add(e);
bst.Delete(e);
bst.Add(e);
s1 = bst.PostOrderRecursive();
s2 = bst.PostOrderIterativeWithVistedFlag();
s3 = bst.PostOrderIterative();
s4 = bst.PostOrderIterative_WikiVersion();
s5 = bst.PostOrderIterative_TwoStacksVersion();
Assert.AreEqual(s1, s2);
Assert.AreEqual(s2, s3);
Assert.AreEqual(s3, s4);
Assert.AreEqual(s4, s5);
}
Debug.WriteLine(string.Format("PostOrderIterative: {0}", bst.PostOrderIterative()));
Debug.WriteLine(string.Format("PostOrderIterative_WikiVersion: {0}", bst.PostOrderIterative_WikiVersion()));
Debug.WriteLine(string.Format("PostOrderIterative_TwoStacksVersion: {0}", bst.PostOrderIterative_TwoStacksVersion()));
Debug.WriteLine(string.Format("PostOrderIterativeWithVistedFlag: {0}", bst.PostOrderIterativeWithVistedFlag()));
Debug.WriteLine(string.Format("PostOrderRecursive: {0}", bst.PostOrderRecursive()));
}
Python with 1 stack and no flag:
def postorderTraversal(self, root):
ret = []
if not root:
return ret
stack = [root]
current = None
while stack:
previous = current
current = stack.pop()
if previous and ((previous is current) or (previous is current.left) or (previous is current.right)):
ret.append(current.val)
else:
stack.append(current)
if current.right:
stack.append(current.right)
if current.left:
stack.append(current.left)
return ret
And what is better is with similar statements, in order traversal works too
def inorderTraversal(self, root):
ret = []
if not root:
return ret
stack = [root]
current = None
while stack:
previous = current
current = stack.pop()
if None == previous or previous.left is current or previous.right is current:
if current.right:
stack.append(current.right)
stack.append(current)
if current.left:
stack.append(current.left)
else:
ret.append(current.val)
return ret
I have not added the node class as its not particularly relevant or any test cases, leaving those as an excercise for the reader etc.
void postOrderTraversal(node* root)
{
if(root == NULL)
return;
stack<node*> st;
st.push(root);
//store most recent 'visited' node
node* prev=root;
while(st.size() > 0)
{
node* top = st.top();
if((top->left == NULL && top->right == NULL))
{
prev = top;
cerr<<top->val<<" ";
st.pop();
continue;
}
else
{
//we can check if we are going back up the tree if the current
//node has a left or right child that was previously outputted
if((top->left == prev) || (top->right== prev))
{
prev = top;
cerr<<top->val<<" ";
st.pop();
continue;
}
if(top->right != NULL)
st.push(top->right);
if(top->left != NULL)
st.push(top->left);
}
}
cerr<<endl;
}
running time O(n) - all nodes need to be visited
AND space O(n) - for the stack, worst case tree is a single line linked list
It's very nice to see so many spirited approaches to this problem. Quite inspiring indeed!
I came across this topic searching for a simple iterative solution for deleting all nodes in my binary tree implementation. I tried some of them, and I tried something similar found elsewhere on the Net, but none of them were really to my liking.
The thing is, I am developing a database indexing module for a very specific purpose (Bitcoin Blockchain indexing), and my data is stored on disk, not in RAM. I swap in pages as needed, doing my own memory management. It's slower, but fast enough for the purpose, and with having storage on disk instead of RAM, I have no religious bearings against wasting space (hard disks are cheap).
For that reason my nodes in my binary tree have parent pointers. That's (all) the extra space I'm talking about. I need the parents because I need to iterate both ascending and descending through the tree for various purposes.
Having that in my mind, I quickly wrote down a little piece of pseudo-code on how it could be done, that is, a post-order traversal deleting nodes on the fly. It's implemented and tested, and became a part of my solution. And it's pretty fast too.
The thing is: It gets really, REALLY, simple when nodes have parent pointers, and furthermore since I can null out the parent's link to the "just departed" node.
Here's the pseudo-code for iterative post-order deletion:
Node current = root;
while (current)
{
if (current.left) current = current.left; // Dive down left
else if (current.right) current = current.right; // Dive down right
else
{
// Node "current" is a leaf, i.e. no left or right child
Node parent = current.parent; // assuming root.parent == null
if (parent)
{
// Null out the parent's link to the just departing node
if (parent.left == current) parent.left = null;
else parent.right = null;
}
delete current;
current = parent;
}
}
root = null;
If you are interested in a more theoretical approach to coding complex collections (such as my binary tree, which is really a self-balancing red-black-tree), then check out these links:
http://opendatastructures.org/versions/edition-0.1e/ods-java/6_2_BinarySearchTree_Unbala.html
http://opendatastructures.org/versions/edition-0.1e/ods-java/9_2_RedBlackTree_Simulated_.html
https://www.cs.auckland.ac.nz/software/AlgAnim/red_black.html
Happy coding :-)
Søren Fog
http://iprotus.eu/
1.1 Create an empty stack
2.1 Do following while root is not NULL
a) Push root's right child and then root to stack.
b) Set root as root's left child.
2.2 Pop an item from stack and set it as root.
a) If the popped item has a right child and the right child
is at top of stack, then remove the right child from stack,
push the root back and set root as root's right child.
b) Else print root's data and set root as NULL.
2.3 Repeat steps 2.1 and 2.2 while stack is not empty.
Here is the Java implementation with two stacks
public static <T> List<T> iPostOrder(BinaryTreeNode<T> root) {
if (root == null) {
return Collections.emptyList();
}
List<T> result = new ArrayList<T>();
Deque<BinaryTreeNode<T>> firstLevel = new LinkedList<BinaryTreeNode<T>>();
Deque<BinaryTreeNode<T>> secondLevel = new LinkedList<BinaryTreeNode<T>>();
firstLevel.push(root);
while (!firstLevel.isEmpty()) {
BinaryTreeNode<T> node = firstLevel.pop();
secondLevel.push(node);
if (node.hasLeftChild()) {
firstLevel.push(node.getLeft());
}
if (node.hasRightChild()) {
firstLevel.push(node.getRight());
}
}
while (!secondLevel.isEmpty()) {
result.add(secondLevel.pop().getData());
}
return result;
}
Here is the unit tests
#Test
public void iterativePostOrderTest() {
BinaryTreeNode<Integer> bst = BinaryTreeUtil.<Integer>fromInAndPostOrder(new Integer[]{4,2,5,1,6,3,7}, new Integer[]{4,5,2,6,7,3,1});
assertThat(BinaryTreeUtil.iPostOrder(bst).toArray(new Integer[0]), equalTo(new Integer[]{4,5,2,6,7,3,1}));
}
/**
* This code will ensure holding of chain(links) of nodes from the root to till the level of the tree.
* The number of extra nodes in the memory (other than tree) is height of the tree.
* I haven't used java stack instead used this ParentChain.
* This parent chain is the link for any node from the top(root node) to till its immediate parent.
* This code will not require any altering of existing BinaryTree (NO flag/parent on all the nodes).
*
* while visiting the Node 11; ParentChain will be holding the nodes 9 -> 8 -> 7 -> 1 where (-> is parent)
*
* 1
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
2 7
/ \ /
/ \ /
/ \ /
/ \ /
3 6 8
/ \ /
/ \ /
4 5 9
/ \
10 11
*
* #author ksugumar
*
*/
public class InOrderTraversalIterative {
public static void main(String[] args) {
BTNode<String> rt;
String[] dataArray = {"1","2","3","4",null,null,"5",null,null,"6",null,null,"7","8","9","10",null,null,"11",null,null,null,null};
rt = BTNode.buildBTWithPreOrder(dataArray, new Counter(0));
BTDisplay.printTreeNode(rt);
inOrderTravesal(rt);
}
public static void postOrderTravesal(BTNode<String> root) {
ParentChain rootChain = new ParentChain(root);
rootChain.Parent = new ParentChain(null);
while (root != null) {
//Going back to parent
if(rootChain.leftVisited && rootChain.rightVisited) {
System.out.println(root.data); //Visit the node.
ParentChain parentChain = rootChain.Parent;
rootChain.Parent = null; //Avoid the leak
rootChain = parentChain;
root = rootChain.root;
continue;
}
//Traverse Left
if(!rootChain.leftVisited) {
rootChain.leftVisited = true;
if (root.left != null) {
ParentChain local = new ParentChain(root.left); //It is better to use pool to reuse the instances.
local.Parent = rootChain;
rootChain = local;
root = root.left;
continue;
}
}
//Traverse RIGHT
if(!rootChain.rightVisited) {
rootChain.rightVisited = true;
if (root.right != null) {
ParentChain local = new ParentChain(root.right); //It is better to use pool to reuse the instances.
local.Parent = rootChain;
rootChain = local;
root = root.right;
continue;
}
}
}
}
class ParentChain {
BTNode<String> root;
ParentChain Parent;
boolean leftVisited = false;
boolean rightVisited = false;
public ParentChain(BTNode<String> node) {
this.root = node;
}
#Override
public String toString() {
return root.toString();
}
}
void display_without_recursion(struct btree **b)
{
deque< struct btree* > dtree;
if(*b)
dtree.push_back(*b);
while(!dtree.empty() )
{
struct btree* t = dtree.front();
cout << t->nodedata << " " ;
dtree.pop_front();
if(t->right)
dtree.push_front(t->right);
if(t->left)
dtree.push_front(t->left);
}
cout << endl;
}
import java.util.Stack;
class Practice
{
public static void main(String arr[])
{
Practice prc = new Practice();
TreeNode node1 = (prc).new TreeNode(1);
TreeNode node2 = (prc).new TreeNode(2);
TreeNode node3 = (prc).new TreeNode(3);
TreeNode node4 = (prc).new TreeNode(4);
TreeNode node5 = (prc).new TreeNode(5);
TreeNode node6 = (prc).new TreeNode(6);
TreeNode node7 = (prc).new TreeNode(7);
node1.left = node2;
node1.right = node3;
node2.left = node4;
node2.right = node5;
node3.left = node6;
node3.right = node7;
postOrderIteratively(node1);
}
public static void postOrderIteratively(TreeNode root)
{
Stack<Entry> stack = new Stack<Entry>();
Practice prc = new Practice();
stack.push((prc).new Entry(root, false));
while (!stack.isEmpty())
{
Entry entry = stack.pop();
TreeNode node = entry.node;
if (entry.flag == false)
{
if (node.right == null && node.left == null)
{
System.out.println(node.data);
} else
{
stack.push((prc).new Entry(node, true));
if (node.right != null)
{
stack.push((prc).new Entry(node.right, false));
}
if (node.left != null)
{
stack.push((prc).new Entry(node.left, false));
}
}
} else
{
System.out.println(node.data);
}
}
}
class TreeNode
{
int data;
int leafCount;
TreeNode left;
TreeNode right;
public TreeNode(int data)
{
this.data = data;
}
public int getLeafCount()
{
return leafCount;
}
public void setLeafCount(int leafCount)
{
this.leafCount = leafCount;
}
public TreeNode getLeft()
{
return left;
}
public void setLeft(TreeNode left)
{
this.left = left;
}
public TreeNode getRight()
{
return right;
}
public void setRight(TreeNode right)
{
this.right = right;
}
#Override
public String toString()
{
return "" + this.data;
}
}
class Entry
{
Entry(TreeNode node, boolean flag)
{
this.node = node;
this.flag = flag;
}
TreeNode node;
boolean flag;
#Override
public String toString()
{
return node.toString();
}
}
}
I was looking for a code snippet that performs well and is simple to customise. Threaded trees are not “simple”. Double stack solution requires O(n) memory. LeetCode solution and solution by tcb have extra checks and pushes...
Here is one classic algorithm translated into C that worked for me:
void postorder_traversal(TreeNode *p, void (*visit)(TreeNode *))
{
TreeNode *stack[40]; // simple C stack, no overflow check
TreeNode **sp = stack;
TreeNode *last_visited = NULL;
for (; p != NULL; p = p->left)
*sp++ = p;
while (sp != stack) {
p = sp[-1];
if (p->right == NULL || p->right == last_visited) {
visit(p);
last_visited = p;
sp--;
} else {
for (p = p->right; p != NULL; p = p->left)
*sp++ = p;
}
}
}
IMHO this algorithm is easier to follow than well performing and readable wikipedia.org / Tree_traversal pseudocode. For glorious details see answers to binary tree exercises in Knuth’s Volume 1.
Here is a Python version too ::
class Node:
def __init__(self,data):
self.data = data
self.left = None
self.right = None
def postOrderIterative(root):
if root is None :
return
s1 = []
s2 = []
s1.append(root)
while(len(s1)>0):
node = s1.pop()
s2.append(node)
if(node.left!=None):
s1.append(node.left)
if(node.right!=None):
s1.append(node.right)
while(len(s2)>0):
node = s2.pop()
print(node.data)
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
root.right.left = Node(6)
root.right.right = Node(7)
postOrderIterative(root)
Here is the output ::
So you can use one stack to do a post order traversal.
private void PostOrderTraversal(Node pos) {
Stack<Node> stack = new Stack<Node>();
do {
if (pos==null && (pos=stack.peek().right)==null) {
for (visit(stack.peek()); stack.pop()==(stack.isEmpty()?null:stack.peek().right); visit(stack.peek())) {}
} else if(pos!=null) {
stack.push(pos);
pos=pos.left;
}
} while (!stack.isEmpty());
}
Two methods to perform Post Order Traversal without Recursion:
1. Using One HashSet of Visited Nodes and One stack for backtracking:
private void postOrderWithoutRecursion(TreeNode root) {
if (root == null || root.left == null && root.right == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
Set<TreeNode> visited = new HashSet<>();
while (!stack.empty() || root != null) {
if (root != null) {
stack.push(root);
visited.add(root);
root = root.left;
} else {
root = stack.peek();
if (root.right == null || visited.contains(root.right)) {
System.out.print(root.val+" ");
stack.pop();
root = null;
} else {
root = root.right;
}
}
}
}
Time Complexity: O(n)
Space Complexity: O(2n)
2. Using Tree Altering method:
private void postOrderWithoutRecursionAlteringTree(TreeNode root) {
if (root == null || root.left == null && root.right == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
while (!stack.empty() || root != null) {
if (root != null) {
stack.push(root);
root = root.left;
} else {
root = stack.peek();
if (root.right == null) {
System.out.print(root.val+" ");
stack.pop();
root = null;
} else {
TreeNode temp = root.right;
root.right = null;
root = temp;
}
}
}
}
Time Complexity: O(n)
Space Complexity: O(n)
TreeNode Class:
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int x) {
val = x;
}
}
Here's a short (the walker is 3 lines) version that I needed to write in Python for a general tree. Of course, works for a more limited binary tree too. Tree is a tuple of the node and list of children. It only has one stack. Sample usage shown.
def postorder(tree):
def do_something(x): # Your function here
print(x),
def walk_helper(root_node, calls_to_perform):
calls_to_perform.append(partial(do_something, root_node[0]))
for child in root_node[1]:
calls_to_perform.append(partial(walk_helper, child, calls_to_perform))
calls_to_perform = []
calls_to_perform.append(partial(walk_helper, tree, calls_to_perform))
while calls_to_perform:
calls_to_perform.pop()()
postorder(('a', [('b', [('c', []), ('d', [])])]))
d
c
b
a
The simplest solution, it may look like not the best answer but it is easy to understand. And I believe if you have understood the solution then you can modify it to make the best possible solution
// using two stacks
public List<Integer> postorderTraversal(TreeNode root){
Stack<TreeNode> st=new Stack<>();
Stack<TreeNode> st2=new Stack<>();
ArrayList<Integer> al = new ArrayList<Integer>();
if(root==null)
return al;
st.push(root); //push the root to 1st stack
while(!st.isEmpty())
{
TreeNode curr=st.pop();
st2.push(curr);
if(curr.left!=null)
st.push(curr.left);
if(curr.right!=null)
st.push(curr.right);
}
while(!st2.isEmpty())
al.add(st2.pop().val);
//this ArrayList contains the postorder traversal
return al;
}
Simple Intuitive solution in python.
while stack:
node = stack.pop()
if node:
if isinstance(node,TreeNode):
stack.append(node.val)
stack.append(node.right)
stack.append(node.left)
else:
post.append(node)
return post
This is what I've come up for post order iterator:
class PostOrderIterator
implements Iterator<T> {
private Stack<Node<T>> stack;
private Node<T> prev;
PostOrderIterator(Node<T> root) {
this.stack = new Stack<>();
recurse(root);
this.prev = this.stack.peek();
}
private void recurse(Node<T> node) {
if(node == null) {
return;
}
while(node != null) {
stack.push(node);
node = node.left;
}
recurse(stack.peek().right);
}
#Override
public boolean hasNext() {
return !stack.isEmpty();
}
#Override
public T next() {
if(stack.peek().right != this.prev) {
recurse(stack.peek().right);
}
Node<T> next = stack.pop();
this.prev = next;
return next.value;
}
}
Basically, the main idea is that you should think how the initialization process puts the first item to print on the top of the stack, while the rest of the stack follow the nodes that would have been touched by the recursion. The rest would just then become a lot easier to nail.
Also, from design perspective, PostOrderIterator is an internal class exposed via some factory method of the tree class as an Iterator<T>.
In post-order traversal, he left child of a node is visited first, followed by its right child, and finally the node itself.
This tree traversal method is similar to depth first search (DFS) traversal of a graph.
Time Complexity: O(n)
Space Complexity: O(n)
Below is the iterative implementation of post-order traversal in python:
class Node:
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
def post_order(node):
if node is None:
return []
stack = []
nodes = []
last_node_visited = None
while stack or node:
if node:
stack.append(node)
node = node.left
else:
peek_node = stack[-1]
if peek_node.right and last_node_visited != peek_node.right:
node = peek_node.right
else:
nodes.append(peek_node.data)
last_node_visited = stack.pop()
return nodes
def main():
'''
Construct the below binary tree:
15
/ \
/ \
/ \
10 20
/ \ / \
8 12 16 25
'''
root = Node(15)
root.left = Node(10)
root.right = Node(20)
root.left.left = Node(8)
root.left.right = Node(12)
root.right.left = Node(16)
root.right.right = Node(25)
print(post_order(root))
if __name__ == '__main__':
main()
For writing iterative equivalents of these recursive methods, we can first understand how the recursive methods themselves execute over the program's stack. Assuming that the nodes do not have their parent pointer, we need to manage our own "stack" for the iterative variants.
One way to start is to see the recursive method and mark the locations where a call would "resume" (fresh initial call, or after a recursive call returns). Below these are marked as "RP 0", "RP 1" etc ("Resume Point"). For the case of postorder traversal:
void post(node *x)
{
/* RP 0 */
if(x->lc) post(x->lc);
/* RP 1 */
if(x->rc) post(x->rc);
/* RP 2 */
process(x);
}
Its iterative variant:
void post_i(node *root)
{
node *stack[1000];
int top;
node *popped;
stack[0] = root;
top = 0;
popped = NULL;
#define POPPED_A_CHILD() \
(popped && (popped == curr->lc || popped == curr->rc))
while(top >= 0)
{
node *curr = stack[top];
if(!POPPED_A_CHILD())
{
/* type (x: 0) */
if(curr->rc || curr->lc)
{
if(curr->rc) stack[++top] = curr->rc;
if(curr->lc) stack[++top] = curr->lc;
popped = NULL;
continue;
}
}
/* type (x: 2) */
process(curr);
top--;
popped = curr;
}
}
The code comments with (x: 0) and (x: 2) correspond to the "RP 0" and "RP 2" resume points in the recursive method.
By pushing both the lc and rc pointers together, we have removed the need of keeping the post(x) invocation at resume-point 1 while the post(x->lc) completes its execution. That is, we could directly shift the node to "RP 2", bypassing "RP 1". So, there is no node kept on stack at "RP 1" stage.
The POPPED_A_CHILD macro helps us deduce one of the two resume-points ("RP 0", or "RP 2").

Resources