Implementing DFS and BFS for binary tree
If it is a tree, visited
can be a list since trees are non-circular, so there no need to check whether you have visited a node before and, more importantly, you want to maintain the order of your traversal.
def dfs(self, tree):
if tree.root is None:
return []
visited, stack = [], [tree.root]
while stack:
node = stack.pop()
visited.append(node)
stack.extend(filter(None, [node.r, node.l]))
# append right first, so left will be popped first
return visited
Your DFS implementation is slightly incorrect. As written, you've actually mimicked a queue, not a stack.
Your current code actually works fairly well for breadth-first search. It forces the siblings of a node to be evaluated before its children:
def bfs(self, graph, start):
visited, queue = set(), [start]
while queue:
vertex = queue.pop()
if vertex not in visited:
visited.add(vertex)
# new nodes are added to end of queue
queue.extend(graph[vertex] - visited)
return visited
The logic for DFS requires a stack to behave like this: when a new node comes, you need to add it to the left of the list, rather than the right. This way, you force the traversal of a node's descendants before the node's siblings.
def dfs(self, graph, start):
visited, stack = set(), [start]
while stack:
vertex = stack.pop()
if vertex not in visited:
visited.add(vertex)
# new nodes are added to the start of stack
stack = graph[vertex] - visited + stack
return visited
Other Issues
The specific issue you are facing beyond this is that you haven't specified what graph
is.
If graph
is an object that doesn't support lookup, then you could implement that using a __getitem__()
method in the class definition.
Typically, people are content to use a dictionary to implement this. Something like {Node: [<list of node's children], ... }
should more than suffice.