from graph import * # Priority queue implementation needs to allow user to keep a reference # to a node, update its value (distance field of vertex), and then update # its position in the heap. To support this, pqNodes need to hold an # indication of their index in the PQ's array, and the PQ needs to update # that indication when it moves nodes around. # (Class factoring isn't very good here; sorry.) class pqNode: def __init__(self, v): self.vertex = v self.index = -1 # should cause an error if used def __cmp__(self, other): return self.vertex.getDistance().__cmp__(other.vertex.getDistance()) class minHeap: def __init__(self): self.contents = [] def swap(self, i, j): self.contents[i], self.contents[j] = self.contents[j], self.contents[i] self.contents[i].index = i self.contents[j].index = j def percolateUp(self, i): # swap i with its parent and repeat as necessary def parent(i): return (i-1) / 2 while i > 0: if self.contents[i] > self.contents[parent(i)]: return self.swap(i, parent(i)) i = parent(i) def percolateDown(self, i): # swap i with its largest child and repeat as necessary max = len(self.contents) - 1 while True: lc = 2*i + 1; rc = 2*i + 2 if lc > max: return if rc <= max and self.contents[rc] < self.contents[lc] \ and self.contents[i] > self.contents[rc]: self.swap(i, rc) i = rc elif self.contents[i] > self.contents[lc]: self.swap(i, lc) i = lc else: return def insert(self, e): e.index = len(self.contents) self.contents.append(e) self.percolateUp(len(self.contents)-1) def deleteMin(self): if len(self.contents) == 1: return self.contents.pop() rtn = self.contents[0] self.contents[0] = self.contents.pop() self.contents[0].index = 0 self.percolateDown(0) return rtn def isEmpty(self): return len(self.contents) == 0 def dijkstra(G, start): PQ = minHeap() for v in G: v.setDistance(sys.maxint) v.setPred(None) start.setDistance(0) for v in G: v.pqn = pqNode(v) PQ.insert(v.pqn) while not PQ.isEmpty(): w = PQ.deleteMin().vertex for v in w.getAdj(): newDist = w.getDistance() + w.getCost(v) if newDist < v.getDistance(): v.setDistance(newDist) v.setPred(w) PQ.percolateUp(v.pqn.index) def prim(G): # use first vertex as start PQ = minHeap() for v in G: v.setDistance(sys.maxint) v.setPred(None) G.vertList.values()[0].setDistance(0) for v in G: v.pqn = pqNode(v) PQ.insert(v.pqn) while not PQ.isEmpty(): w = PQ.deleteMin().vertex for v in w.getAdj(): if v.pqn in PQ.contents and w.cost[v] < v.getDistance(): v.setDistance(w.cost[v]) v.setPred(w) PQ.percolateUp(v.pqn.index) def floyd(G): # use first vertex as start V = G.vertList.values() N = G.numVertices def cost(i, j): try: return V[i].cost[V[j]] except KeyError: return sys.maxint M = [[[None, cost(i, j)] # intermediary, cost for j in range(N)] for i in range(N)] for k in range(N): for i in range(N): for j in range(N): newCost = M[i][k][1] + M[k][j][1] if newCost < M[i][j][1]: M[i][j] = [k, newCost] for i in range(N): print V[i].getId() + ":", for j in range(N): print M[i][j], print def build26(): # construct Figure 6.26 from the text G = Graph() G.addEdge('u', 'v', 2); G.addEdge('v', 'u', 2) G.addEdge('u', 'w', 5); G.addEdge('w', 'u', 5) G.addEdge('u', 'x', 1); G.addEdge('x', 'u', 1) G.addEdge('v', 'w', 3); G.addEdge('w', 'v', 3) G.addEdge('v', 'x', 2); G.addEdge('x', 'v', 2) G.addEdge('w', 'x', 3); G.addEdge('x', 'w', 3) G.addEdge('w', 'y', 1); G.addEdge('y', 'w', 1) G.addEdge('w', 'z', 5); G.addEdge('z', 'w', 5) G.addEdge('y', 'x', 1); G.addEdge('x', 'y', 1) G.addEdge('y', 'z', 1); G.addEdge('z', 'y', 1) return G def build28(): # construct Figure 6.28 from the text G = Graph() G.addEdge('A', 'B', 2); G.addEdge('B', 'A', 2) G.addEdge('A', 'C', 3); G.addEdge('C', 'A', 3) G.addEdge('B', 'C', 1); G.addEdge('C', 'B', 1) G.addEdge('B', 'D', 1); G.addEdge('D', 'B', 1) G.addEdge('B', 'E', 4); G.addEdge('E', 'B', 4) G.addEdge('C', 'F', 5); G.addEdge('F', 'C', 5) G.addEdge('D', 'E', 1); G.addEdge('E', 'D', 1) G.addEdge('E', 'F', 1); G.addEdge('F', 'E', 1) G.addEdge('F', 'G', 1); G.addEdge('G', 'F', 1) return G def build3(): # graph with distinctly different shortest-distance and MST trees G = Graph() G.addEdge('A', 'B', 1); G.addEdge('B', 'A', 1) G.addEdge('B', 'C', 1); G.addEdge('C', 'B', 1) G.addEdge('C', 'D', 1); G.addEdge('D', 'C', 1) G.addEdge('D', 'E', 1); G.addEdge('E', 'D', 1) G.addEdge('A', 'C', 2); G.addEdge('C', 'A', 2) G.addEdge('A', 'D', 2); G.addEdge('D', 'A', 2) G.addEdge('A', 'E', 2); G.addEdge('E', 'A', 2) return G