I am learning Elixir and wanted to try implementing simple tree traversal algorithms. However, I am not getting the desired results. What am I doing wrong?
defmodule Algos do
#pre_order function, prints the root, the left then the right
def pre_order(node, nodes) do
next = [nodes | node.data]
if (node && node.left) do
Algos.pre_order(node.left, next)
end
if (node && node.right) do
Algos.pre_order(node.right, next)
end
next
end
#in_order function, prints the left, the root then the right
def in_order(node, nodes) do
if (node && node.left) do
Algos.in_order(node.left, nodes)
end
next = [nodes | node.data]
if (node && node.right) do
Algos.in_order(node.right, next)
end
next
end
#post_order function, prints the left, the right then the root
def post_order(node, nodes) do
if (node && node.left) do
Algos.post_order(node.left, nodes)
end
if (node && node.right) do
Algos.post_order(node.right, nodes)
end
[nodes | node.data]
end
end
defmodule Traverse do
def print do
root = %{
data: "A",
left: %{
data: "B",
left: %{
data: "C",
left: nil,
right: nil
},
right: %{
data: "D",
left: nil,
right: nil
}
},
right: %{
data: "E",
left: nil,
right: nil
}
}
result = Algos.pre_order(root, "")
IO.puts(result)
result2 = Algos.in_order(root, "")
IO.puts(result2)
result3 = Algos.post_order(root, "")
IO.puts(result3)
end
end
Traverse.print
The output looks as follows
[Running] elixir "/Volumes/MAC/d/Algorithms/tree_traversal.exs"
A
A
A
[Done] exited with code=0 in 3.891 seconds
I did not read all the code, but this is not working as You expect, it should be an element first, then a list. If needed, You can reverse the list at the end.
[node.data | nodes]
Remember a list is [head | tail], with head being an element pushed at the head, while tails is a list.
defmodule Algos do
#pre_order function, prints the root, the left then the right
def pre_order(node, nodes) do
next = [node.data | nodes]
if (node && node.left) do
Algos.pre_order(node.left, next)
end
if (node && node.right) do
Algos.pre_order(node.right, next)
end
next
end
#in_order function, prints the left, the root then the right
def in_order(node, nodes) do
if (node && node.left) do
Algos.in_order(node.left, nodes)
end
next = [node.data | nodes]
if (node && node.right) do
Algos.in_order(node.right, next)
end
next
end
#post_order function, prints the left, the right then the root
def post_order(node, nodes) do
if (node && node.left) do
Algos.post_order(node.left, nodes)
end
if (node && node.right) do
Algos.post_order(node.right, nodes)
end
[node.data | nodes]
end
end
defmodule Traverse do
def print do
root = %{
data: "A",
left: %{
data: "B",
left: %{
data: "C",
left: nil,
right: nil
},
right: %{
data: "D",
left: nil,
right: nil
}
},
right: %{
data: "E",
left: nil,
right: nil
}
}
result = Algos.pre_order(root, [])
IO.puts(result)
result2 = Algos.in_order(root, [])
IO.puts(result2)
result3 = Algos.post_order(root, [])
IO.puts(result3)
end
end
Traverse.print
That is the current code.
I still get only the first node “A” returned by each function.
[Running] elixir "/Volumes/MAC/d/Algorithms/tree_traversal.exs"
A
A
A
[Done] exited with code=0 in 3.304 seconds
I expect the functions to traverse the tree, create a list, and then return that list
You “liked” my previous post, so I can assume you read it. If you have any problems understanding the hints, please feel free to ask more questions.
This provides you the generic case of the pattern match, you now need to provide the base case which breaks the recursive call. This version will crash on the leafs.
Using your answer, I modified the code as follows:
defmodule Algos do
#pre_order function, prints the root, the left then the right
def pre_order(%{data: data, left: nil, right: nil}) do
[data]
end
def pre_order(%{data: data, left: left, right: right}) do
[data] ++ pre_order(left) ++ pre_order(right)
end
#in_order function, prints the left, the root then the right
def in_order(%{data: data, left: nil, right: nil}) do
[data]
end
def in_order(%{data: data, left: left, right: right}) do
pre_order(left) ++ [data] ++ pre_order(right)
end
#post_order function, prints the left, the right then the root
def post_order(%{data: data, left: nil, right: nil}) do
[data]
end
def post_order(%{data: data, left: left, right: right}) do
pre_order(left) ++ pre_order(right) ++ [data]
end
end
defmodule Traverse do
def print do
root = %{
data: "A",
left: %{
data: "B",
left: %{
data: "C",
left: nil,
right: nil
},
right: %{
data: "D",
left: nil,
right: nil
}
},
right: %{
data: "E",
left: nil,
right: nil
}
}
result = Algos.pre_order(root)
IO.puts(result)
result2 = Algos.in_order(root)
IO.puts(result2)
result3 = Algos.post_order(root)
IO.puts(result3)
end
end
Traverse.print
The code worked as expected:
[Running] elixir "/Volumes/MAC/d/Algorithms/tree_traversal.exs"
ABCDE
BCDAE
BCDEA
[Done] exited with code=0 in 2.978 seconds
Is there a shorter way other than duplicating the function this way?
#pre_order function, prints the root, the left then the right
#for empty
def pre_order(%{data: nil, left: nil, right: nil}) do
[]
end
#for leafs
def pre_order(%{data: data, left: nil, right: nil}) do
[data]
end
def pre_order(%{data: data, left: left, right: right}) do
[data] ++ pre_order(left) ++ pre_order(right)
end