Depth-first search
Depth-first search of a tree is a method for recursively iterating across all nodes of a tree to find if the tree contains a given value. The depth-first method descends to the lowest level of each branch before moving to a different branch.
Approach
Check if the current node's value is equal to the given value. If so, return true
. If not, do the same thing for each of the children of the current node.
JS
function Tree(value) {
this.children = [];
this.value = value;
}
Tree.prototype.addBranch = function(value) {
const branch = new Tree(value);
this.children.push(branch);
return branch;
}
Tree.prototype.dfs = function(value) {
if (this.value === value) {
return true;
}
for (let i = 0; i < this.children.length; i++) {
if (this.children[i].dfs(value)) return true;
}
return false;
}
First thing we do is create a Tree object, with a children
property initialized to an empty array, and a value
property that is initialized with the given value. To add a new branch, we simply push a new tree to the children
property of the node on which we are constructing a new branch.
The depth-first search first checks the current node's value, and then recursively checks each child down the tree, checking that child's value. If at any point the node's value is equal to the given search value, we return true and come back up through the stack. If we check all nodes and don't find a node with the right value, we return false.
Lua
Tree = {}
function Tree:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Tree:addChild(v)
local branch = Tree:new{value = v, children = {}}
table.insert(self.children, branch)
return branch
end
function Tree:dfs(v)
if self.value == v then return true end
for _,child in ipairs(self.children) do
if child:dfs(v) then return true end
end
return false
end
In Lua, we create the Tree namespace, a Tree constructor, and then the function to add a child Tree. The depth-first search proceeds in exactly the same manner as the search in JS.
Go
type Tree struct {
children []*Tree
v int
}
func (t *Tree) addBranch(v int) *Tree {
branch := &Tree{v: v}
t.children = append(t.children, branch)
return branch
}
func (t *Tree) dfs(x int) bool {
if t.v == x {
return true
}
for _, v := range t.children {
if v.dfs(x) {
return true
}
}
return false
}
We do the same thing here in Go. We create the Tree struct, give it an addBranch
method to add more trees as children to whatever tree we're working with, and then create the recursive depth-first search.
Summary
A classic and straightforward prompt, the depth-first search is always a good one for testing your knowledge of data structures in a language. However, there is very little "algorithm" action, and it's more about construction of the data structure itself.