Skip to content

Commit

Permalink
add acyclic and bellman ford sp
Browse files Browse the repository at this point in the history
  • Loading branch information
shellfly committed Feb 5, 2020
1 parent 95330f5 commit a2dbb97
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Try to keep the interface and variable name consistent with the original book wh
* [EdgeWeightedDigraph](algs4/edge_weighted_digraph.py)
* [DijkstraSP](algs4/dijkstra_sp.py)
* [AcyclicSP](algs4/acyclic_sp.py)
* [Bellman-FordSP](algs4/bellman_ford_sp.py)
* [BellmanFordSP](algs4/bellman_ford_sp.py)

* 5 STRING

Expand Down
35 changes: 35 additions & 0 deletions algs4/acyclic_sp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from algs4.stack import Stack
from algs4.topological import Topological

POSITIVE_INFINITY = 999999.0


class AcyclicSP:
def __init__(self, g, s):
self.edgeTo = [None for _ in range(g.V)]
self.distTo = [float("inf") for _ in range(g.V)]
for v in range(g.V):
self.distTo[v] = POSITIVE_INFINITY
self.distTo[s] = 0.0
top = Topological(g)
for e in top.order:
self.relax(e)

def relax(self, e):
v, w = e.From(), e.To()
if self.distTo[w] > self.distTo[v] + e.weight:
self.distTo[w] = self.distTo[v] + e.weight
self.edgeTo[w] = e

def has_path_to(self, v):
return self.distTo[v] < POSITIVE_INFINITY

def path_to(self, v):
if not self.has_path_to(v):
return None
edges = Stack()
e = self.edgeTo[v]
while e != None:
edges.push(e)
e = self.edgeTo[e.From()]
return edges
64 changes: 64 additions & 0 deletions algs4/bellman_ford_sp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from algs4.queue import Queue
from algs4.stack import Stack

POSITIVE_INFINITY = 999999.0


class DijkstraSP:
def __init__(self, g, s):
self.cost = 0
self.cycle = None
self.edgeTo = [None for _ in range(g.V)]
self.distTo = [float("inf") for _ in range(g.V)]
self.onQ = [false for _ in range(g.V)]
for v in range(g.V):
self.distTo[v] = POSITIVE_INFINITY
self.distTo[s] = 0.0

self.queue = Queue()
self.queue.enqueue(s)
self.onQ[s] = True
while not self.queue.is_empty() and not self.has_negative_cycle():
v = self.queue.dequeue()
self.onQ[v] = False
self.relax(g, v)

def relax(self, g, v):
for e in g.adj[v]:
w = e.To()
if self.distTo[w] > self.distTo[v]+e.weight:
self.distTo[w] = self.distTo[v] + e.weight
self.edgeTo[w] = e
if not self.onQ[w]:
self.queue.enqueue(w)
self.onQ[w] = True
self.cost += 1
if self.cost % g.V == 0:
self.find_negative_cycle()
if self.has_negative_cycle():
return

def find_negative_cycle(self):
V = len(self.edgeTo)
spt = EdgeWeightedDigraph(V)
for v in range(V):
if self.edgeTo[v] != None:
spt.add_edge(self.edgeTo[v])
finder = EdgeWeightedDirectedCycle(spt)
self.cycle = finder.cycle()

def has_negative_cycle(self):
return self.cycle != None

def has_path_to(self, v):
return self.distTo[v] < POSITIVE_INFINITY

def path_to(self, v):
if not self.has_path_to(v):
return None
edges = Stack()
e = self.edgeTo[v]
while e != None:
edges.push(e)
e = self.edgeTo[e.From()]
return edges

0 comments on commit a2dbb97

Please sign in to comment.