From 6da2a6c57a953036f3fbc829df95fc723484d119 Mon Sep 17 00:00:00 2001 From: shellfly Date: Mon, 3 Feb 2020 16:59:06 +0800 Subject: [PATCH] add depth_first_order --- README.md | 28 ++++++++------ algs4/depth_first_order.py | 79 ++++++++++++++++++++++++++++++++++++++ algs4/digraph.py | 19 +++++++-- algs4/graph.py | 8 ++-- 4 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 algs4/depth_first_order.py diff --git a/README.md b/README.md index 968126b..95130a4 100644 --- a/README.md +++ b/README.md @@ -51,18 +51,22 @@ Try to keep the interface and variable name consistent with the original book wh * [LinearProbingHashST](algs4/linear_probing_hash_st.py) * 4 GRAPHS - - * [Graph](algs4/graph.py) - * [DepthFirstSearch](algs4/depth_first_search.py) - * [DepthFirstPaths](algs4/depth_first_paths.py) - * [BreadthFirstPaths](algs4/breadth_first_paths.py) - * [CC](algs4/cc.py) - * [Cycle](algs4/cycle.py) - * [SymbolGraph](algs4/symbol_graph.py) - * [DegreesOfSeparation](algs4/degrees_of_separation.py) - * [Digraph](algs4/digraph.py) - * [DirectedDFS](algs4/directed_dfs.py) - * [DirectedCycle](algs4/directed_cycle.py) + * Graph + * [Graph](algs4/graph.py) + * [DepthFirstSearch](algs4/depth_first_search.py) + * [DepthFirstPaths](algs4/depth_first_paths.py) + * [BreadthFirstPaths](algs4/breadth_first_paths.py) + * [CC](algs4/cc.py) + * [Cycle](algs4/cycle.py) + * [SymbolGraph](algs4/symbol_graph.py) + * [DegreesOfSeparation](algs4/degrees_of_separation.py) + * Digraph + * [Digraph](algs4/digraph.py) + * [DirectedDFS](algs4/directed_dfs.py) + * [DirectedCycle](algs4/directed_cycle.py) + * [DepthFirstOrder](depth_first_order.go) + * [Topological](topological.go) + * [KosarajuSCC](kosaraju_scc.go) * 5 STRING diff --git a/algs4/depth_first_order.py b/algs4/depth_first_order.py new file mode 100644 index 0000000..a8a6247 --- /dev/null +++ b/algs4/depth_first_order.py @@ -0,0 +1,79 @@ +""" + * Execution: python depth_first_order.py digraph.txt + * Data files: https://algs4.cs.princeton.edu/42digraph/tinyDAG.txt + * https://algs4.cs.princeton.edu/42digraph/tinyDG.txt + * + * Compute preorder and postorder for a digraph or edge-weighted digraph. + * Runs in O(E + V) time. + * + * % python depth_first_order.py tinyDAG.txt + * v pre post + * -------------- + * 0 0 8 + * 1 3 2 + * 2 9 10 + * 3 10 9 + * 4 2 0 + * 5 1 1 + * 6 4 7 + * 7 11 11 + * 8 12 12 + * 9 5 6 + * 10 8 5 + * 11 6 4 + * 12 7 3 + * Preorder: 0 5 4 1 6 9 11 12 10 2 3 7 8 + * Postorder: 4 5 1 12 11 10 9 6 0 3 2 7 8 + * Reverse postorder: 8 7 2 3 0 6 9 10 11 12 1 5 4 + * +""" +from algs4.queue import Queue +from algs4.stack import Stack +from algs4.digraph import Digraph + + +class DepthFirstOrder: + + def __init__(self, G): + self.marked = [False for _ in range(G.V)] + self.pre = Queue() + self.post = Queue() + for w in range(G.V): + if not self.marked[w]: + self.dfs(g, w) + + def dfs(self, G, v): + self.pre.enqueue(v) + self.marked[v] = True + + for w in G.adj[v]: + if not self.marked[w]: + self.dfs(G, w) + self.post.enqueue(v) + + def reversePost(self): + reverse = Stack() + for v in self.post: + reverse.push(v) + return reverse + + +if __name__ == '__main__': + import sys + g = Digraph(file=open(sys.argv[1])) + dfs = DepthFirstOrder(g) + + print("Preorder: ") + for v in dfs.pre: + print(v, " ", end="") + print() + + print("Postorder: ") + for v in dfs.post: + print(v, " ", end="") + print() + + print("ReversePostorder: ") + for v in dfs.reversePost(): + print(v, " ", end="") + print() diff --git a/algs4/digraph.py b/algs4/digraph.py index 72e937c..14d4052 100644 --- a/algs4/digraph.py +++ b/algs4/digraph.py @@ -25,16 +25,28 @@ 12: 9 """ +from algs4.bag import Bag class Digraph: - def __init__(self, v): + def __init__(self, v=0, **kwargs): self.V = v self.E = 0 self.adj = {} for v in range(self.V): - self.adj[v] = [] + self.adj[v] = Bag() + + if 'file' in kwargs: + # init a digraph by a file input + in_file = kwargs['file'] + self.V = int(in_file.readline()) + for v in range(self.V): + self.adj[v] = Bag() + E = int(in_file.readline()) + for i in range(E): + v, w = in_file.readline().split() + self.add_edge(int(v), int(w)) def __str__(self): s = "%d vertices, %d edges\n" % (self.V, self.E) @@ -44,7 +56,7 @@ def __str__(self): def add_edge(self, v, w): v, w = int(v), int(w) - self.adj[v].append(w) + self.adj[v].add(w) self.E += 1 def degree(self, v): @@ -73,6 +85,7 @@ def reverse(self): v += 1 return R + if __name__ == '__main__': import sys diff --git a/algs4/graph.py b/algs4/graph.py index b774a02..c35102a 100644 --- a/algs4/graph.py +++ b/algs4/graph.py @@ -31,6 +31,7 @@ 2: 141 110 108 86 79 51 42 18 14 ... """ +from algs4.bag import Bag class Graph: @@ -40,7 +41,7 @@ def __init__(self, v): self.E = 0 self.adj = {} for v in range(self.V): - self.adj[v] = [] + self.adj[v] = Bag() def __str__(self): s = "%d vertices, %d edges\n" % (self.V, self.E) @@ -50,8 +51,8 @@ def __str__(self): def add_edge(self, v, w): v, w = int(v), int(w) - self.adj[v].append(w) - self.adj[w].append(v) + self.adj[v].add(w) + self.adj[w].add(v) self.E += 1 def degree(self, v): @@ -71,6 +72,7 @@ def number_of_self_loops(self): count += 1 return count + if __name__ == '__main__': import sys