Skip to content

Commit b0dcd25

Browse files
committed
postorder traverse
1 parent ef4210e commit b0dcd25

File tree

3 files changed

+131
-0
lines changed

3 files changed

+131
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Problem: 135. Binary Tree Postorder Traversal
2+
3+
Post-order traversal is to traverse the left subtree first. Then traverse the right subtree. Finally, visit the root.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package binarytreepostordertraversal
2+
3+
// TreeNode data structure
4+
type TreeNode struct {
5+
Val int
6+
Left *TreeNode
7+
Right *TreeNode
8+
}
9+
10+
// Stack data structure that implements LIFO
11+
type Stack []*TreeNode
12+
13+
// Push adds an item onto the stack.
14+
func (s *Stack) Push(node *TreeNode) {
15+
*s = append(*s, node)
16+
}
17+
18+
// Pop removes the most-recently-pushed item from the stack.
19+
func (s *Stack) Pop() *TreeNode {
20+
arr := *s
21+
last := len(arr) - 1
22+
top := arr[last]
23+
if len(arr) > 0 {
24+
arr = arr[0:last]
25+
} else {
26+
arr = []*TreeNode{}
27+
}
28+
*s = arr
29+
return top
30+
}
31+
32+
// Peek a top element
33+
func (s *Stack) Peek() *TreeNode {
34+
arr := *s
35+
if len(arr) == 0 {
36+
return nil
37+
}
38+
last := len(arr) - 1
39+
top := arr[last]
40+
return top
41+
}
42+
43+
// Nice explanation: https://www.geeksforgeeks.org/iterative-postorder-traversal-using-stack/
44+
func postorderTraversal(root *TreeNode) []int {
45+
ret := []int{}
46+
if root == nil {
47+
return ret
48+
}
49+
stack := Stack{}
50+
for {
51+
// Push root's right child and then root to stack
52+
for root != nil {
53+
if root.Right != nil {
54+
stack.Push(root.Right)
55+
}
56+
stack.Push(root)
57+
// Set root as root's left child
58+
root = root.Left
59+
}
60+
// Pop an item from stack and set it as root
61+
root = stack.Pop()
62+
// If the popped item has a right child and the
63+
// right child is not processed yet, then make sure
64+
// right child is processed before root
65+
if root.Right != nil && stack.Peek() == root.Right {
66+
stack.Pop() //Remove right child from stack
67+
stack.Push(root) //Push root back to stack
68+
root = root.Right // change root so that the right childis processed next
69+
} else { // Else print root's data and set root as None
70+
ret = append(ret, root.Val)
71+
root = nil
72+
}
73+
if len(stack) <= 0 {
74+
break
75+
}
76+
}
77+
return ret
78+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package binarytreepostordertraversal
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
)
7+
8+
func TestPostorderTraversal(t *testing.T) {
9+
testCases := []struct {
10+
Input *TreeNode
11+
Output []int
12+
}{
13+
{
14+
Input: &TreeNode{
15+
Val: 1,
16+
Left: nil,
17+
Right: &TreeNode{
18+
Val: 2,
19+
Left: &TreeNode{
20+
Val: 3,
21+
},
22+
},
23+
},
24+
Output: []int{3, 2, 1},
25+
},
26+
{
27+
Input: nil,
28+
Output: []int{},
29+
},
30+
{
31+
Input: &TreeNode{
32+
Val: 3,
33+
Left: &TreeNode{
34+
Val: 1,
35+
Right: &TreeNode{
36+
Val: 2,
37+
},
38+
},
39+
},
40+
Output: []int{2, 1, 3},
41+
},
42+
}
43+
44+
for _, test := range testCases {
45+
out := postorderTraversal(test.Input)
46+
if !reflect.DeepEqual(test.Output, out) {
47+
t.Errorf("expected to get %#v, but got %#v", test.Output, out)
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)