Skip to content

Instantly share code, notes, and snippets.

@mgritter
Created September 2, 2020 01:28
Show Gist options
  • Select an option

  • Save mgritter/bc76bd17f404c83f046f7b88851426e3 to your computer and use it in GitHub Desktop.

Select an option

Save mgritter/bc76bd17f404c83f046f7b88851426e3 to your computer and use it in GitHub Desktop.
Demonstrating recursion vs. iteration
package main
import (
"fmt"
"time"
)
type TreeNode struct {
Goal bool
Children map[string]*TreeNode
}
func makeTree(root *TreeNode, width int, depth int, goal_at_leaf bool) {
if depth == 0 {
root.Goal = goal_at_leaf
return
}
for i := 0; i < width; i++ {
key := fmt.Sprintf("child%v", i)
newNode := &TreeNode{
Goal: false,
Children: make(map[string]*TreeNode),
}
root.Children[key] = newNode
makeTree(newNode, width, depth-1, goal_at_leaf)
}
}
func recursive(root *TreeNode, visited map[*TreeNode]struct{}) *TreeNode {
if _, ok := visited[root]; ok {
return nil
}
visited[root] = struct{}{}
if root.Goal {
return root
}
for _, v := range root.Children {
// Don't visit a second time.
if _, ok := visited[v]; ok {
continue
}
goal := recursive(v, visited)
if goal != nil {
return goal
}
}
return nil
}
func start_recursive(root *TreeNode) *TreeNode {
visited := make(map[*TreeNode]struct{})
return recursive(root, visited)
}
func iterative(root *TreeNode) *TreeNode {
pending := []*TreeNode{root}
visited := make(map[*TreeNode]struct{})
for len(pending) > 0 {
// Pop next node to visit
curr := pending[len(pending)-1]
pending = pending[:len(pending)-1]
if _, ok := visited[curr]; ok {
continue
}
visited[curr] = struct{}{}
if curr.Goal {
return curr
}
for _, v := range curr.Children {
if _, ok := visited[v]; ok {
continue
}
pending = append(pending, v)
}
}
return nil
}
func main() {
testCases := []struct {
width int
depth int
goal bool
}{
{10, 5, true},
{10, 5, false},
{20, 5, true},
{20, 5, false},
}
for _, tc := range testCases {
root := &TreeNode{
Goal: false,
Children: make(map[string]*TreeNode),
}
fmt.Printf("#####################\nWidth %v, Depth %v, Goal %v\n",
tc.width, tc.depth, tc.goal)
makeTree(root, tc.width, tc.depth, tc.goal)
fmt.Printf("Constructed...\n")
// Warm up the cache
start_recursive(root)
iterative(root)
fmt.Printf("Sampling...\n")
for sample := 0; sample < 5; sample++ {
start_time := time.Now()
start_recursive(root)
end_time := time.Now()
fmt.Printf("recursive %v\n", end_time.Sub(start_time))
}
for sample := 0; sample < 5; sample++ {
start_time := time.Now()
iterative(root)
end_time := time.Now()
fmt.Printf("iterative %v\n", end_time.Sub(start_time))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment