def __init__(self, digraph): # This is used to keep track of whether a vertex has been encountered or not. # This way dfs() will only run at most once for each vertex self.marked_array = [False]*digraph.V() # This array is used to build the cycle_stack # For a given index self.paths_array = [None]*digraph.V() # This stack stays empty until a cycle is detected. # If a cycle is detected, all of the vertices along the cycle are added to the stack # This is done by utilizing the paths_array which stores the previous vertex along its path self.cycle_stack = Stack_ResizingArray() # This array keeps track of whether a vertex is still on the call stack. # If we encounter a vertex that is still on the call stack, then we know a cycle exists (similar to how if the end of the string re-encounters the string in the Tremaux maze) # The value at a given index is turned to True while it is on the call stack and turned to False when dfs finishes (and it is no longer on the call stack) self.onStack = [False]*digraph.V() for i in range(digraph.V()): # This way dfs goes through all vertices even if in different components. if not self.marked_array[i]: self.onStack[i]=True self.dfs(i, digraph) self.onStack[i]=False
class Directed_DFS_Orderings: def __init__(self, digraph): self.marked_array = [False] * digraph.V() self.pre_order = Queue_LinkedList() self.post_order = Queue_LinkedList() self.reverse_post_order = Stack_ResizingArray() for i in range(digraph.V()): if not self.marked_array[i]: self.dfs(i, digraph) def dfs(self, v, digraph): self.pre_order.enqueue(v) self.marked_array[v] = True for j in digraph.adjacent(v): if not self.marked_array[j]: self.dfs(j, digraph) self.post_order.enqueue(v) self.reverse_post_order.push(v) def preorder(self): return self.pre_order def postorder(self): return self.post_order def reversepostorder(self): return self.reverse_post_order
class Directed_DFS_Orderings_EWD: def __init__(self, ew_digraph): self.ew_digraph = ew_digraph self.marked_array = [False] * self.ew_digraph.V() self.pre_order = Queue_LinkedList() self.post_order = Queue_LinkedList() self.reverse_post_order = Stack_ResizingArray() for i in range(self.ew_digraph.V()): if self.marked_array[i] != True: self.dfs(i) def dfs(self, v): self.pre_order.enqueue(v) self.marked_array[v] = True # For Edge_Weighted_Digraph, self.ew_digraph.adjacent(v) returns the edges coming from vertex v (in Digraph, self.digraph.adjacent(v) returns the vertices v is pointing towards). for directed_edge in self.ew_digraph.adjacent(v): w = directed_edge.towards_vert() if self.marked_array[w] != True: self.dfs(w) self.post_order.enqueue(v) self.reverse_post_order.push(v) def preorder(self): return self.pre_order def postorder(self): return self.post_order def reversepostorder(self): return self.reverse_post_order
def pathTo(self, v): if not self.hasPathTo(v): return None stack = Stack_ResizingArray() while v is not None: stack.push(v) v = self.paths_array[v] return stack
def pathTo(self, v): if not self.hasPathTo(v): return None stack = Stack_ResizingArray() x = v while x is not None: stack.push(x) x = self.path_array[x] return stack
def __init__(self, digraph): self.marked_array = [False] * digraph.V() self.pre_order = Queue_LinkedList() self.post_order = Queue_LinkedList() self.reverse_post_order = Stack_ResizingArray() for i in range(digraph.V()): if not self.marked_array[i]: self.dfs(i, digraph)
def __init__(self, ew_digraph): self.ew_digraph = ew_digraph self.marked_array = [False] * self.ew_digraph.V() self.pre_order = Queue_LinkedList() self.post_order = Queue_LinkedList() self.reverse_post_order = Stack_ResizingArray() for i in range(self.ew_digraph.V()): if self.marked_array[i] != True: self.dfs(i)
def dfs(self, graph, s): stack = Stack_ResizingArray() stack.push(s) while stack: v = stack.pop() self.count_connected += 1 print(v, self.count_connected) for neighbor in graph.adj[v]: if not self.marked_array[neighbor]: self.marked_array[v] = True stack.push(neighbor)
def dfs(self, graph, v): self.marked_array[v] = True stack = Stack_ResizingArray() stack.push(v) while stack: vertex = stack.pop() neighbors_list = graph.adj[vertex] for i in neighbors_list: if self.marked_array[i] != True: stack.push(i) self.marked_array[vertex] = True self.path_array[i] = vertex
def pathTo(self,v): path_stack = Stack_ResizingArray() directed_edge = self.edgeTo[v] if v == self.s: return "No edges required to reach source vertex from source vertex" vert_from = directed_edge.from_vert() while vert_from != self.s: path_stack.push(directed_edge) directed_edge = self.edgeTo[vert_from] vert_from = directed_edge.from_vert() path_stack.push(directed_edge) return path_stack
class Directed_Weighted_Cycle: def __init__(self, ew_digraph): # This is used to keep track of whether a vertex has been encountered or not. # This way dfs() will only run at most once for each vertex self.marked_array = [False] * ew_digraph.V() # This array is used to build the cycle_stack # For a given index self.edgeTo = [None] * ew_digraph.V() # This stack stays empty until a cycle is detected. # If a cycle is detected, all of the vertices along the cycle are added to the stack # This is done by utilizing the paths_array which stores the previous vertex along its path self.cycle_stack = Stack_ResizingArray() # This array keeps track of whether a vertex is still on the call stack. # If we encounter a vertex that is still on the call stack, then we know a cycle exists (similar to how if the end of the string re-encounters the string in the Tremaux maze) # The value at a given index is turned to True while it is on the call stack and turned to False when dfs finishes (and it is no longer on the call stack) self.onStack = [False] * ew_digraph.V() for i in range(ew_digraph.V()): # This way dfs goes through all vertices even if in different components. if self.marked_array[i] != True: self.dfs(i, ew_digraph) def dfs(self, v, ew_digraph): self.onStack[v] = True self.marked_array[v] = True # For Edge_Weighted_Digraph, self.ewdigraph.adjacent(v) returns the edges coming from vertex v (in Digraph, self.digraph.adjacent(v) returns the vertices v is pointing towards. for directed_edge in ew_digraph.adjacent(v): w = directed_edge.towards_vert() # 1. # If a cycle has already been detected (and consequently cycle_stack has been built), # Then no more calls to dfs() will be added to the call stack and those remaining are quickly finished w/ this return statement. if self.hasCycle() == True: return # 2. # If a vertex has already been encountered, then we don't need to re-search through its neighbors. # We only search through the neighbors of a vertex once. elif self.marked_array[w] == False: self.edgeTo[w] = directed_edge self.dfs(w, ew_digraph) # 3. # If this is a true, a cycle has been detected and we can build the cycle stack to show the cycle. elif self.onStack[w] == True: self.cycle_stack.push(directed_edge) x = self.edgeTo[v] while x.from_vert() != directed_edge.towards_vert(): self.cycle_stack.push(x) x = self.edgeTo[x.from_vert()] self.cycle_stack.push(x) self.onStack[v] = False def hasCycle(self): return not self.cycle_stack.isEmpty() def cycle(self): if self.hasCycle() == False: return None else: return self.cycle_stack