├── Searching And Sorting ├── SimpleSearch.py ├── CountingSort.py ├── InsertionSort.py ├── Bubblesort.py ├── BinarySearch.py ├── MergeSort.py ├── RotatedBinarySearch.py ├── QuickSort.py └── HeapSort.py ├── Miscellaneous Algorithms ├── CatalanNumber.py ├── RussianPeasantMultiplication.py ├── LogarithmicExponentiation.py ├── SquareRoot.py ├── MatrixRank.py ├── CountingInversionsBIT.py └── CountingInversions.py ├── Prime Numbers And Prime Factorization ├── nCrmodp.py ├── PrimeFactorisation.py ├── PollardRho.py ├── SieveOfEratosthene.py ├── SegmentedSieve.py └── PrimalityTest(I,II,III).py ├── Graph Algorithms ├── BFS.py ├── DFS.py ├── Floyd Warshall.py ├── Kruskal.py ├── TopologicalSort.py ├── Prim.py └── Dijakstra.py ├── Modulo Arithmetic Algorithms ├── ModularExponentiation.py ├── EuclideanAlgorithms.py ├── ModularMultiplicativeInverse.py ├── ChineseRemainderTheorem.py └── EulerTotientFunction.py ├── Dynamic Programming ├── NumberOfWaysToCoverDistance.py ├── LongestCommonSubsequence.py ├── LongestIncreasingSubsequence.py ├── MinimumPartition.py └── EditDistance.py ├── Data Structures ├── FenwickOrBinaryTree.py └── Tries.py └── README.md /Searching And Sorting /SimpleSearch.py: -------------------------------------------------------------------------------- 1 | nolist=map(int,raw_input("Enter nos: ").split()) 2 | key=input("Search key: ") 3 | 4 | def search(lista,key): 5 | for x in lista: 6 | if x==key: 7 | return True 8 | return False 9 | 10 | print search(nolist,key) 11 | -------------------------------------------------------------------------------- /Miscellaneous Algorithms/CatalanNumber.py: -------------------------------------------------------------------------------- 1 | import sys 2 | def catalan(n): 3 | if n <=1 : 4 | return 1 5 | res = 0 6 | for i in range(n): 7 | res += catalan(i) * catalan(n-i-1) 8 | return res 9 | if __name__ == "__main__" : 10 | if len(sys.argv) > 1: 11 | a=int(sys.argv[1]) 12 | print catalan(a) 13 | -------------------------------------------------------------------------------- /Searching And Sorting /CountingSort.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | nos=map(int,raw_input("Enter no for sort:").split()) 3 | def countingSort(array, mn, mx): 4 | count = defaultdict(int) 5 | for i in array: 6 | count[i] += 1 7 | result = [] 8 | for j in range(mn,mx+1): 9 | result += [j]* count[j] 10 | return result 11 | countingSort(nos,min(nos),max(nos)) 12 | print nos -------------------------------------------------------------------------------- /Miscellaneous Algorithms/RussianPeasantMultiplication.py: -------------------------------------------------------------------------------- 1 | import sys 2 | def russianPeasant(a,b): 3 | res = 0 4 | while b > 0: 5 | if b & 1 : 6 | res = res + a 7 | a = a << 1 8 | b = b >> 1 9 | return res 10 | 11 | if __name__ == "__main__" : 12 | if len(sys.argv) > 2: 13 | a=int(sys.argv[1]) 14 | b=int(sys.argv[1]) 15 | print russianPeasant(a,b) 16 | -------------------------------------------------------------------------------- /Searching And Sorting /InsertionSort.py: -------------------------------------------------------------------------------- 1 | nos=map(int,raw_input("Enter no for sort: ").split()) 2 | 3 | 4 | def sort(a): 5 | n=len(a) 6 | i=1 7 | while i=0 and a[j]>key: 11 | a[j+1]=a[j] 12 | j-=1 13 | a[j+1]=key 14 | i+=1 15 | 16 | 17 | sort(nos) 18 | print nos 19 | -------------------------------------------------------------------------------- /Miscellaneous Algorithms/LogarithmicExponentiation.py: -------------------------------------------------------------------------------- 1 | import sys 2 | def power(x,y): 3 | if y == 0 : 4 | return 1; 5 | elif y%2 == 0 : 6 | return power(x, y/2)*power(x, y/2) 7 | else : 8 | return x*power(x, y/2)*power(x, y/2) 9 | 10 | if __name__ == "__main__" : 11 | if len(sys.argv) > 2: 12 | a=int(sys.argv[1]) 13 | m=int(sys.argv[2]) 14 | print power(a,m) 15 | -------------------------------------------------------------------------------- /Prime Numbers And Prime Factorization /nCrmodp.py: -------------------------------------------------------------------------------- 1 | import math 2 | import sys 3 | def nCrModp(n, r, p): 4 | C=[0]*(r+1) 5 | C[0]=1 6 | i=1 7 | while i<=n : 8 | j=min(i,r) 9 | while j>0 : 10 | C[j] = (C[j] + C[j-1])%p 11 | j=j-1 12 | i=i+1 13 | return C[r] 14 | if __name__=="__main__": 15 | if len(sys.argv) > 3: 16 | print nCrModp(int(sys.argv[1]),int(sys.argv[2]),int(sys.argv[3])) 17 | -------------------------------------------------------------------------------- /Prime Numbers And Prime Factorization /PrimeFactorisation.py: -------------------------------------------------------------------------------- 1 | import math 2 | import sys 3 | def primeFactor(n): 4 | while n%2==0: 5 | print 2, 6 | n/=2 7 | 8 | i=3 9 | while i*i < n : 10 | if n%i ==0: 11 | print i, 12 | n/=i 13 | i+=2 14 | if n>2 : 15 | print n, 16 | 17 | if __name__=="__main__": 18 | if len(sys.argv) > 1: 19 | primeFactor(int(sys.argv[1])) 20 | -------------------------------------------------------------------------------- /Prime Numbers And Prime Factorization /PollardRho.py: -------------------------------------------------------------------------------- 1 | from random import randint 2 | from fractions import gcd 3 | from math import * 4 | 5 | def PollardRho(n): 6 | i=0; 7 | xi=randint(0,n-1); 8 | k=2 9 | y=xi 10 | while i< n: 11 | i=i+1 12 | xi=((xi^2)-1)%n 13 | d=gcd(y-xi,n) 14 | if d!=1 and d!=n: 15 | print d; 16 | if i==k: 17 | y=xi 18 | k=2*k 19 | if __name__=="__main__": 20 | if len(sys.argv) > 1: 21 | PollardRho(int(sys.argv[1])) 22 | -------------------------------------------------------------------------------- /Graph Algorithms/BFS.py: -------------------------------------------------------------------------------- 1 | def bfs( start, end, graph ): 2 | todo = [(start, [start])] 3 | while len( todo ): 4 | node, path = todo.pop( 0 ) 5 | for next_node in graph[node]: 6 | if next_node in path: 7 | continue 8 | elif next_node == end: 9 | yield path + [next_node] 10 | else: 11 | todo.append( (next_node, path + [next_node]) ) 12 | 13 | 14 | if __name__ == '__main__': 15 | graph = { 'A': ['B','C'], 16 | 'B': ['D'], 17 | 'C': ['E'], 18 | 'D': ['E', 'F'], 19 | 'E': [] } 20 | [ print( x ) for x in bfs( 'A', 'F', graph ) ] 21 | -------------------------------------------------------------------------------- /Modulo Arithmetic Algorithms/ModularExponentiation.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def modExponentiation(x,e,m): 4 | X = x 5 | E = e 6 | Y = 1 7 | while E > 0: 8 | if E % 2 == 0: 9 | X = (X * X) % m 10 | E = E/2 11 | else: 12 | Y = (X * Y) % m 13 | E = E - 1 14 | return Y 15 | 16 | if __name__ == "__main__" : 17 | if len(sys.argv) > 3: 18 | a=int(sys.argv[1]) 19 | m=int(sys.argv[2]) 20 | x=int(sys.argv[3]) 21 | print modExponentiation(a,m,x) 22 | -------------------------------------------------------------------------------- /Searching And Sorting /Bubblesort.py: -------------------------------------------------------------------------------- 1 | nos=map(int,raw_input("Enter no for sort:").split()) 2 | 3 | 4 | def sort(lst): 5 | n=len(lst) 6 | i=0 7 | while ilst[j+1]: 12 | tm=lst[j] 13 | lst[j]=lst[j+1] 14 | lst[j+1]=tm 15 | hk=True 16 | j+=1 17 | if not hk: 18 | break 19 | i+=1 20 | 21 | 22 | 23 | sort(nos) 24 | print nos 25 | -------------------------------------------------------------------------------- /Searching And Sorting /BinarySearch.py: -------------------------------------------------------------------------------- 1 | nos=map(int,raw_input("Enter nos: ").split()) 2 | key=input("searching key: ") 3 | 4 | 5 | def bsearch(lst,left,right,key): 6 | if left 1 : 20 | n=int(sys.argv[1]) 21 | pr=primRange() 22 | pr.eratosthenes(n) 23 | -------------------------------------------------------------------------------- /Modulo Arithmetic Algorithms/EuclideanAlgorithms.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def gcd(a,b): 5 | if a==0: 6 | return b 7 | return gcd(b%a,a) 8 | 9 | 10 | def agcdUtil(a,b,p): 11 | if a==0: 12 | p[0]=0 13 | p[1]=1 14 | return b 15 | ans=agcdUtil(b%a,a,p) 16 | x=p[1]-int(b/a)*p[0] 17 | y=p[0] 18 | p[0]=x 19 | p[1]=y 20 | return ans 21 | 22 | def agcd(a,b): 23 | point=[0,0] 24 | return agcdUtil(a,b,point) 25 | 26 | 27 | if __name__ == "__main__" : 28 | if len(sys.argv) > 2: 29 | a=int(sys.argv[1]) 30 | b=int(sys.argv[2]) 31 | print gcd(a,b),agcd(a,b) 32 | -------------------------------------------------------------------------------- /Prime Numbers And Prime Factorization /SegmentedSieve.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def prime_sieve(n): 4 | """Use the Sieve of Eratosthenes to list primes 0 to n.""" 5 | primes = range(n+1) 6 | primes[1] = 0 7 | for i in range(4, n+1, 2): 8 | primes[i] = 0 9 | for x in range(3, int(math.sqrt(n))+1, 2): 10 | if primes[x]: 11 | for i in range(2*primes[x], n+1, primes[x]): 12 | primes[i] = 0 13 | return filter(None, primes) 14 | 15 | def ranged_primes(x, y): 16 | """List primes between x and y.""" 17 | primes = prime_sieve(int(math.sqrt(y))) 18 | return [n for n in range(x, y) if all(n % p for p in primes)] 19 | if __name__=="__main__": 20 | if len(sys.argv) > 2: 21 | print primeFactor(int(sys.argv[1]),int(sys.argv[2])) 22 | -------------------------------------------------------------------------------- /Dynamic Programming/NumberOfWaysToCoverDistance.py: -------------------------------------------------------------------------------- 1 | def printCountRec(dist,n) : 2 | if dist<0: 3 | return 0 4 | if dist==0: 5 | return 1 6 | x=0 7 | for i in range(1,n+1): 8 | x=x+printCountRec(dist-i) 9 | return x 10 | 11 | def printCountDP(int dist,n): 12 | count=[0]*(dist+1) 13 | count[0] = 1, count[1] = 1, count[2] = 2 14 | for i in range(3,dist+1): 15 | for j in range(1,n+1): 16 | count[i]=count[i]+count[i-j] 17 | return count[dist] 18 | 19 | if __name__ == "__main__" : 20 | if len(sys.argv) > 2: 21 | distance=int(sys.argv[1]) 22 | maxnumberOfSteps=int(sys.argv[2]) 23 | print "Recursive Solution: ",printCountRec(distance,maxnumberOfSteps) 24 | print "Recursive Solution: ",printCountDP(distance,maxnumberOfSteps) 25 | -------------------------------------------------------------------------------- /Searching And Sorting /MergeSort.py: -------------------------------------------------------------------------------- 1 | nos=map(int,raw_input("Enter no's for sort: ").split()) 2 | 3 | 4 | def merge(a,l,m,r): 5 | L=a[l:m+1] 6 | R=a[m+1:r+1] 7 | i=0 8 | j=0 9 | k=l 10 | while i 0: 18 | sum +=self.bit[x] 19 | x -=x&-x 20 | return sum 21 | 22 | 23 | 24 | 25 | if __name__ == "__main__": 26 | a=[1,23,3,4,4,4,4,4,4,5,5] 27 | bt = Bit(a) 28 | print "query(4)", bt.query(4) 29 | print "update(2,6)" 30 | bt.update(2,6) 31 | print "query(4)",bt.query(4) 32 | -------------------------------------------------------------------------------- /Dynamic Programming/LongestCommonSubsequence.py: -------------------------------------------------------------------------------- 1 | def lcs(X, Y, m, n): 2 | if m == 0 or n == 0: 3 | return 0; 4 | elif X[m-1] == Y[n-1]: 5 | return 1 + lcs(X, Y, m-1, n-1); 6 | else: 7 | return max(lcs(X, Y, m, n-1), lcs(X, Y, m-1, n)) 8 | 9 | def lcsDynamic(X , Y): 10 | m = len(X) 11 | n = len(Y) 12 | L = [[None]*(n+1) for i in xrange(m+1)] 13 | for i in range(m+1): 14 | for j in range(n+1): 15 | if i == 0 or j == 0 : 16 | L[i][j] = 0 17 | elif X[i-1] == Y[j-1]: 18 | L[i][j] = L[i-1][j-1]+1 19 | else: 20 | L[i][j] = max(L[i-1][j] , L[i][j-1]) 21 | return L[m][n] 22 | 23 | 24 | X = raw_input("Enter first string") 25 | Y = raw_input("Enter second string") 26 | print "Length of LCS By 2^n solution is ", lcs(X , Y, len(X), len(Y)) 27 | print "Length of LCS By Dynamic solution is ", lcsDynamic(X , Y, len(X), len(Y)) 28 | -------------------------------------------------------------------------------- /Modulo Arithmetic Algorithms/ModularMultiplicativeInverse.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | """ 4 | a x= 1 (mod m) 5 | 6 | """ 7 | 8 | 9 | 10 | 11 | def modInverse(a,m): 12 | i=2 13 | while i < m: 14 | if (a*i)%m ==1: 15 | return i 16 | i+=1 17 | return -1 18 | 19 | 20 | def gcdExtend(a,b,p): 21 | if a==0: 22 | p[0]=0 23 | p[1]=1 24 | return b 25 | ans=gcdExtend(b%a,a,p) 26 | x=p[1]-int(b/a)*p[0] 27 | y=p[0] 28 | p[0]=x 29 | p[1]=y 30 | return ans 31 | 32 | def amodInv(a,m): 33 | p=[0,0] 34 | g=gcdExtend(a,m,p) 35 | if not g == 1: 36 | print "provided numbers are not coprime" 37 | else: 38 | res=(p[0]%m+m)%m 39 | return res 40 | 41 | 42 | 43 | if __name__ == "__main__" : 44 | if len(sys.argv) > 2: 45 | a=int(sys.argv[1]) 46 | m=int(sys.argv[2]) 47 | print modInverse(a,m) 48 | print amodInv(a,m) 49 | -------------------------------------------------------------------------------- /Graph Algorithms/Floyd Warshall.py: -------------------------------------------------------------------------------- 1 | V = 4 2 | INF = 1000000000 3 | def floydWarshall(graph): 4 | dist = map(lambda i : map(lambda j : j , i) , graph) 5 | for k in range(V): 6 | for i in range(V): 7 | for j in range(V): 8 | dist[i][j] = min(dist[i][j] , 9 | dist[i][k]+ dist[k][j] 10 | ) 11 | printSolution(dist) 12 | def printSolution(dist): 13 | print "Following matrix shows the shortest distances\ 14 | between every pair of vertices" 15 | for i in range(V): 16 | for j in range(V): 17 | if(dist[i][j] == INF): 18 | print "%7s" %("INF"), 19 | else: 20 | print "%7d\t" %(dist[i][j]), 21 | if j == V-1: 22 | print "" 23 | graph = [[0,5,INF,10], 24 | [INF,0,3,INF], 25 | [INF, INF, 0, 1], 26 | [INF, INF, INF, 0] 27 | ] 28 | floydWarshall(graph); 29 | -------------------------------------------------------------------------------- /Modulo Arithmetic Algorithms/ChineseRemainderTheorem.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def findMinX(n,r): 4 | x=1 5 | while True: 6 | j=0 7 | while j < len(n): 8 | if not x%n[j]==r[j]: 9 | break 10 | j+=1 11 | if j==len(n): 12 | return x 13 | x+=1 14 | 15 | def minv(a,m): 16 | i=2 17 | while i < m: 18 | if (a*i)%m ==1: 19 | return i 20 | i+=1 21 | return -1 22 | 23 | def crtheorem(n,r): 24 | prod=1 25 | for x in n: 26 | prod*=x 27 | pp=[] 28 | inv=[] 29 | for a in n: 30 | pp.append(prod/a) 31 | 32 | i=0 33 | while i< len(n): 34 | inv.append(minv(pp[i],n[i])) 35 | i+=1 36 | x=sum([x*y*z for x,y,z in zip(r,pp,inv)]) 37 | return x%prod 38 | 39 | 40 | if __name__== "__main__": 41 | n=[3, 4, 5] 42 | r=[2, 3, 1] 43 | print findMinX(n,r),crtheorem(n,r) 44 | -------------------------------------------------------------------------------- /Miscellaneous Algorithms/SquareRoot.py: -------------------------------------------------------------------------------- 1 | import sys 2 | def floorSqrt(x): 3 | if x == 0 || x == 1 : 4 | return x 5 | i = 1 6 | result = 1 7 | while result < x : 8 | if result == x : 9 | return result 10 | i=i+1 11 | result = i*i 12 | return i-1 13 | 14 | def floorSqrtBinarySearch(x): 15 | if x == 0 || x == 1 : 16 | return x 17 | start = 1 18 | end = x 19 | ans=0 20 | while start <= end : 21 | mid = (start + end) / 2 22 | if mid*mid == x : 23 | return mid 24 | if mid*mid < x : 25 | start = mid + 1 26 | ans = mid 27 | else : 28 | end = mid - 1 29 | return ans 30 | 31 | if __name__ == "__main__" : 32 | if len(sys.argv) > 1: 33 | x=int(sys.argv[1]) 34 | print "O(n) Solution :" 35 | print floorSqrt(x) 36 | print "Solution By Binary Search :" 37 | print floorSqrtBinarySearch(x) 38 | -------------------------------------------------------------------------------- /Graph Algorithms/Kruskal.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from UnionFind import UnionFind 3 | from Graphs import isUndirected 4 | 5 | def MinimumSpanningTree(G): 6 | if not isUndirected(G): 7 | raise ValueError("MinimumSpanningTree: input is not undirected") 8 | for u in G: 9 | for v in G[u]: 10 | if G[u][v] != G[v][u]: 11 | raise ValueError("MinimumSpanningTree: asymmetric weights") 12 | subtrees = UnionFind() 13 | tree = [] 14 | for W,u,v in sorted((G[u][v],u,v) for u in G for v in G[u]): 15 | if subtrees[u] != subtrees[v]: 16 | tree.append((u,v)) 17 | subtrees.union(u,v) 18 | return tree 19 | 20 | class MSTTest(unittest.TestCase): 21 | def testMST(self): 22 | G = {0:{1:11,2:13,3:12},1:{0:11,3:14},2:{0:13,3:10},3:{0:12,1:14,2:10}} 23 | T = [(2,3),(0,1),(0,3)] 24 | for e,f in zip(MinimumSpanningTree(G),T): 25 | self.assertEqual(min(e),min(f)) 26 | self.assertEqual(max(e),max(f)) 27 | 28 | if __name__ == "__main__": 29 | unittest.main() 30 | -------------------------------------------------------------------------------- /Searching And Sorting /RotatedBinarySearch.py: -------------------------------------------------------------------------------- 1 | nos=map(int,raw_input("Enter nos: ").split()) 2 | key=input("Enter key to search: ") 3 | 4 | def pivot(lst,l,r): 5 | if l>r: 6 | return -1 7 | if l==r: 8 | return l 9 | mid=(l+r)/2 10 | 11 | if mid < r and lst[mid]>lst[mid+1]: 12 | return mid 13 | if mid > l and lst[mid] < lst[mid-1]: 14 | return mid-1 15 | if lst[l] >= lst[mid]: 16 | return pivot(lst,l,mid-1) 17 | return pivot(lst,mid+1,r) 18 | 19 | 20 | def findPivot(lista): 21 | return pivot(lista,0,len(lista)) 22 | 23 | def rbsearch(lst,l,r,k): 24 | mid=(l+r)/2 25 | if l > r: 26 | return -1 27 | if lst[mid]==k: 28 | return mid 29 | if lst[l]<=lst[mid]: 30 | if k >= lst[l] and k <= lst[mid]: 31 | return rbsearch(lst,l,mid-1,k) 32 | return rbsearch(lst,mid+1,r,k) 33 | if k >=lst[mid] and k <= lst[r]: 34 | return rbsearch(lst,mid+1,r,k) 35 | return rbsearch(lst,l,mid-1,k) 36 | 37 | 38 | print findPivot(nos) 39 | print rbsearch(nos,0,len(nos)-1,key) 40 | -------------------------------------------------------------------------------- /Modulo Arithmetic Algorithms/EulerTotientFunction.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | """ 4 | 5 | phi(n)=no of prime factor of n 6 | 7 | """ 8 | def gcd(a,b): 9 | if a==0: 10 | return b 11 | return gcd(b%a,a) 12 | 13 | def phi(n): 14 | result=0 15 | i=1 16 | while i < n: 17 | if gcd(i,n)==1: 18 | result+=1 19 | i+=1 20 | return result 21 | 22 | def aphi(n): 23 | p=2 24 | result=n 25 | while p*p <= n: 26 | if n%p == 0: 27 | while n%p==0: 28 | n/=p 29 | result*=(1.0-(1.0/float(p))) 30 | p+=1 31 | if n > 1: 32 | result*=(1.0-(1.0/float(n))) 33 | return int(result) 34 | 35 | 36 | def aaphi(n): 37 | p=2 38 | result=n 39 | while p*p <= n : 40 | if n%p == 0: 41 | while n%p == 0: 42 | n/=p 43 | result-=result/p 44 | p+=1 45 | if n >1: 46 | result-=result/n 47 | return result 48 | 49 | 50 | if __name__ == "__main__": 51 | if len(sys.argv) > 1: 52 | a=int(sys.argv[1]) 53 | print "aaphi(a)",aaphi(a) 54 | print "aphi(a)",aphi(a) 55 | print "phi(a)",phi(a) 56 | -------------------------------------------------------------------------------- /Searching And Sorting /QuickSort.py: -------------------------------------------------------------------------------- 1 | def quickSort(alist): 2 | quickSortHelper(alist,0,len(alist)-1) 3 | 4 | def quickSortHelper(alist,first,last): 5 | if first= pivotvalue and rightmark >= leftmark: 26 | rightmark = rightmark -1 27 | 28 | if rightmark < leftmark: 29 | done = True 30 | else: 31 | temp = alist[leftmark] 32 | alist[leftmark] = alist[rightmark] 33 | alist[rightmark] = temp 34 | 35 | temp = alist[first] 36 | alist[first] = alist[rightmark] 37 | alist[rightmark] = temp 38 | 39 | 40 | return rightmark 41 | 42 | alist = nos=map(int,raw_input("Enter no for sort:").split()) 43 | quickSort(alist) 44 | print(alist) 45 | -------------------------------------------------------------------------------- /Graph Algorithms/TopologicalSort.py: -------------------------------------------------------------------------------- 1 | graph1 = { 2 | "a": ["b", "c", "d"], 3 | "b": [], 4 | "c": ["d"], 5 | "d": [] 6 | } 7 | 8 | graph2 = { 9 | "a": ["b", "c", "d"], 10 | "b": [], 11 | "c": ["d"], 12 | "d": [], 13 | "e": ["g", "f", "q"], 14 | "g": [], 15 | "f": [], 16 | "q": [] 17 | } 18 | 19 | graph3 = { 20 | "a": ["b", "c", "d"], 21 | "b": [], 22 | "c": ["d", "e"], 23 | "d": [], 24 | "e": ["g", "f", "q"], 25 | "g": ["c"], 26 | "f": [], 27 | "q": [] 28 | } 29 | 30 | from collections import deque 31 | 32 | GRAY, BLACK = 0, 1 33 | 34 | def topological(graph): 35 | order, enter, state = deque(), set(graph), {} 36 | 37 | def dfs(node): 38 | state[node] = GRAY 39 | for k in graph.get(node, ()): 40 | sk = state.get(k, None) 41 | if sk == GRAY: raise ValueError("cycle") 42 | if sk == BLACK: continue 43 | enter.discard(k) 44 | dfs(k) 45 | order.appendleft(node) 46 | state[node] = BLACK 47 | 48 | while enter: dfs(enter.pop()) 49 | return order 50 | 51 | print topological(graph1) 52 | print topological(graph2) 53 | try: topological(graph3) 54 | except ValueError: print "Cycle!" 55 | -------------------------------------------------------------------------------- /Miscellaneous Algorithms/MatrixRank.py: -------------------------------------------------------------------------------- 1 | def swap(mat,row1,row2,col): 2 | for i in range(col): 3 | temp = mat[row1][i] 4 | mat[row1][i] = mat[row2][i] 5 | mat[row2][i] = temp 6 | 7 | def rankOfMatrix(mat,C,R): 8 | rank = C 9 | for row in range(rank): 10 | if mat[row][row]!=0 : 11 | for col in range(R): 12 | if col != row : 13 | mult = mat[col][row] /mat[row][row] 14 | for i in range(rank): 15 | mat[col][i] = mat[col][i] - mult * mat[row][i] 16 | else : 17 | reducemat = true 18 | for i range(row+1,R): 19 | if mat[i][row] !=0: 20 | swap(mat, row, i, rank) 21 | reducemat = false 22 | break 23 | if reducemat == true : 24 | rank=rank-1 25 | for i in range(R): 26 | mat[i][row] = mat[i][rank] 27 | row=row-1; 28 | return rank; 29 | R=input("No. of Rows") 30 | C=input("Np. of Columns") 31 | mat=[[0]*C for i range(R)] 32 | print "Enter Matrix Elements" 33 | for i in range(R): 34 | for j in range(C): 35 | mat[i][j]=input() 36 | 37 | print "Rank of MAtrix", rankOfMatrix(mat,C,R) 38 | -------------------------------------------------------------------------------- /Dynamic Programming/LongestIncreasingSubsequence.py: -------------------------------------------------------------------------------- 1 | """ A naive Python implementation of LIS problem """ 2 | from collections import defaultdict 3 | global maximum 4 | def _lis(arr , n ): 5 | global maximum 6 | if n == 1 : 7 | return 1 8 | maxEndingHere = 1 9 | for i in xrange(1, n): 10 | res = _lis(arr , i) 11 | if arr[i-1] < arr[n-1] and res+1 > maxEndingHere: 12 | maxEndingHere = res +1 13 | maximum = max(maximum , maxEndingHere) 14 | return maxEndingHere 15 | 16 | def lis(arr): 17 | global maximum 18 | n = len(arr) 19 | maximum = 1 20 | _lis(arr , n) 21 | return maximum 22 | 23 | """ Dynamic programming Python implementation of LIS problem """ 24 | 25 | def lisDynamicSolution(arr): 26 | n = len(arr) 27 | lis = [1]*n 28 | for i in range (1 , n): 29 | for j in range(0 , i): 30 | if arr[i] > arr[j] and lis[i]< lis[j] + 1 : 31 | lis[i] = lis[j]+1 32 | maximum = 0 33 | for i in range(n): 34 | maximum = max(maximum , lis[i]) 35 | return maximum 36 | 37 | arr = map(int,raw_input("Enter number present in array:").split()) 38 | print "Navie Solution :" 39 | print "Length of LIS is ", lis(arr) 40 | print "Dynamic Solution :" 41 | print "Length of LIS is ", lisDynamicSolution(arr) 42 | -------------------------------------------------------------------------------- /Dynamic Programming/MinimumPartition.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | numList=map(int,raw_input("Enter number present in array:").split()) 3 | def findMinRec(arr, i,sumCalculated,sumTotal): 4 | if i==0: 5 | return abs((sumTotal-sumCalculated) - sumCalculated) 6 | return min(findMinRec(arr, i-1, sumCalculated+arr[i-1], sumTotal),findMinRec(arr, i-1, sumCalculated, sumTotal)) 7 | 8 | def findMin(arr,n): 9 | sumTotal = 0 10 | for i in range(n): 11 | sumTotal = sumTotal + arr[i] 12 | return findMinRec(arr, n, 0, sumTotal); 13 | 14 | def findMinDP(arr,n): 15 | sumTotal = 0; 16 | for i in range(n): 17 | sumTotal = sumTotal + arr[i] 18 | dp=[[0]*(sumTotal+1) for i in range(n+1)] 19 | for i in range(1,n+1): 20 | dp[i][0] = 1 21 | for i in range(1,sumTotal+1): 22 | dp[0][i] = 0; 23 | for i in range(n+1): 24 | for j in range(1,sumTotal+1): 25 | dp[i][j] = dp[i-1][j] 26 | if arr[i-1] <= j: 27 | dp[i][j] = dp[i][j]|dp[i-1][j-arr[i-1]] 28 | diff = 1000000000 29 | j=sumTotal/2; 30 | while j>=0: 31 | if dp[n][j] == 1 : 32 | diff = sumTotal-2*j 33 | break 34 | return diff 35 | print "Recursive Solution ",findMin(numList,len(numList)) 36 | print "Dynamic Solution ", findMinDP(numList,len(numList)) 37 | -------------------------------------------------------------------------------- /Searching And Sorting /HeapSort.py: -------------------------------------------------------------------------------- 1 | class Heap: 2 | def __init__(self): 3 | self.arr=[] 4 | self.Size=len(self.arr) 5 | 6 | def maxHeapify(self,idx): 7 | largest=idx 8 | left=2*idx+1 9 | right=2*idx+2 10 | 11 | if leftself.arr[largest]: 12 | largest=left 13 | if rightself.arr[largest]: 14 | largest=right 15 | if not largest==idx: 16 | self.arr[largest],self.arr[idx]=self.arr[idx],self.arr[largest] 17 | self.maxHeapify(largest) 18 | 19 | 20 | def buildHeap(self,array): 21 | self.Size=len(array) 22 | self.arr=array 23 | i=(self.Size-2)/2 24 | while i>=0: 25 | self.maxHeapify(i) 26 | i-=1 27 | 28 | 29 | 30 | def heapSort(heap): 31 | while heap.Size >1: 32 | heap.arr[0],heap.arr[heap.Size-1]=heap.arr[heap.Size-1],heap.arr[0] 33 | heap.Size-=1 34 | heap.maxHeapify(0) 35 | 36 | nos=map(int,raw_input("Enter no's: ").split()) 37 | h=Heap() 38 | h.buildHeap(nos) 39 | print nos 40 | heapSort(h) 41 | print nos 42 | -------------------------------------------------------------------------------- /Data Structures/Tries.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | """docstring for Node""" 3 | def __init__(self,key=26): 4 | self.data=[None]*key 5 | self.isword=False 6 | 7 | 8 | class Trie: 9 | """simple trie by using list.""" 10 | def __init__(self): 11 | self.head=None 12 | def insert(self,word): 13 | if self.head==None: 14 | self.head=Node() 15 | temNode=self.head 16 | for letter in word: 17 | key=lambda x:ord(x.lower())-ord('a') 18 | if not temNode.data[key(letter)]: 19 | temNode.data[key(letter)]=Node() 20 | temNode=temNode.data[key(letter)] 21 | temNode.isword=True 22 | 23 | def find(self,word): 24 | temNode=self.head 25 | key=lambda x:ord(x.lower())-ord('a') 26 | if temNode: 27 | for letter in word: 28 | if temNode.data[key(letter)]: 29 | temNode=temNode.data[key(letter)] 30 | if temNode.isword: 31 | return True 32 | else: 33 | return False 34 | else: 35 | return False 36 | 37 | 38 | 39 | 40 | if __name__=="__main__": 41 | a=Trie() 42 | a.insert("hitesh") 43 | a.insert("aditi") 44 | a.insert("gudan") 45 | print a.find("aditi") 46 | print a.find("haikent") 47 | -------------------------------------------------------------------------------- /Dynamic Programming/EditDistance.py: -------------------------------------------------------------------------------- 1 | """ A Naive recursive Python program to fin minimum number """ 2 | def editDistance(str1, str2, m , n): 3 | if m==0: 4 | return n 5 | if n==0: 6 | return m 7 | if str1[m-1]==str2[n-1]: 8 | return editDistance(str1,str2,m-1,n-1) 9 | return 1 + min(editDistance(str1, str2, m, n-1), # Insert 10 | editDistance(str1, str2, m-1, n), # Remove 11 | editDistance(str1, str2, m-1, n-1) # Replace 12 | ) 13 | 14 | def editDistDP(str1, str2, m, n): 15 | dp = [[0 for x in range(n+1)] for x in range(m+1)] 16 | for i in range(m+1): 17 | for j in range(n+1): 18 | if i == 0: 19 | dp[i][j] = j 20 | elif j == 0: 21 | dp[i][j] = i 22 | elif str1[i-1] == str2[j-1]: 23 | dp[i][j] = dp[i-1][j-1] 24 | else: 25 | dp[i][j] = 1 + min(dp[i][j-1], # Insert 26 | dp[i-1][j], # Remove 27 | dp[i-1][j-1]) # Replace 28 | 29 | return dp[m][n] 30 | str1 = raw_input("Enter first string") 31 | str2 = raw_input("Enter second string") 32 | print "Naive Solution :" 33 | print editDistance(str1, str2, len(str1), len(str2)) 34 | print "Dynamic Solution" 35 | print editDistDP(str1, str2, len(str1), len(str2)) 36 | -------------------------------------------------------------------------------- /Graph Algorithms/Prim.py: -------------------------------------------------------------------------------- 1 | 2 | def weight(A, u, v): 3 | return A[u][v] 4 | def adjacent(A, u): 5 | L = [] 6 | for x in range(len(A)): 7 | if A[u][x] > 0 and x <> u: 8 | L.insert(0,x) 9 | return L 10 | def extractMin(Q): 11 | q = Q[0] 12 | Q.remove(Q[0]) 13 | return q 14 | def decreaseKey(Q, K): 15 | for i in range(len(Q)): 16 | for j in range(len(Q)): 17 | if K[Q[i]] < K[Q[j]]: 18 | s = Q[i] 19 | Q[i] = Q[j] 20 | Q[j] = s 21 | def prim(V, A, r): 22 | u = 0 23 | v = 0 24 | P=[None]*len(V) 25 | K = [999999]*len(V) 26 | Q=[0]*len(V) 27 | for u in range(len(Q)): 28 | Q[u] = V[u] 29 | K[r] = 0 30 | decreaseKey(Q, K) 31 | while len(Q) > 0: 32 | u = extractMin(Q) 33 | Adj = adjacent(A, u) 34 | for v in Adj: 35 | w = weight(A, u, v) 36 | if Q.count(v)>0 and w < K[v]: 37 | P[v] = u 38 | K[v] = w 39 | decreaseKey(Q, K) 40 | return P 41 | 42 | A = [ [0, 4, 0, 0, 0, 0, 0, 8, 0], 43 | [4, 0, 8, 0, 0, 0, 0, 11, 0], 44 | [0, 8, 0, 7, 0, 4, 0, 0, 2], 45 | [0, 0, 7, 0, 9, 14, 0, 0, 0], 46 | [0, 0, 0, 9, 0, 10, 0, 0, 0], 47 | [0, 0, 4, 14, 10, 0, 2, 0, 0], 48 | [0, 0, 0, 0, 0, 2, 0, 1, 6], 49 | [8, 11, 0, 0, 0, 0, 1, 0, 7], 50 | [0, 0, 2, 0, 0, 0, 6, 7, 0]] 51 | V = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ] 52 | 53 | P = prim(V, A, 0) 54 | print P 55 | -------------------------------------------------------------------------------- /Miscellaneous Algorithms/CountingInversionsBIT.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | numList=map(int,raw_input("Enter number present in array:").split()) 3 | 4 | def getSum(BITree,index): 5 | sum = 0 6 | while index > 0: 7 | sum = sum + BITree[index] 8 | index = index - index & (-index) 9 | return sum 10 | 11 | def updateBIT(BITree,n,index,val): 12 | while index <= n: 13 | BITree[index] =BITree[index]+ val 14 | index = index+index & (-index) 15 | 16 | def getInvCount(arr,n): 17 | invcount = 0 18 | maxElement = 0; 19 | for i in range(n): 20 | if maxElement < arr[i]: 21 | maxElement = arr[i] 22 | BIT[maxElement+1]; 23 | for i in range(1,maxElement+1): 24 | BIT[i] = 0 25 | i=n-1 26 | while i>=0: 27 | invcount = invcount + getSum(BIT, arr[i]-1) 28 | updateBIT(BIT, maxElement, arr[i], 1) 29 | i=i-1 30 | return invcount 31 | 32 | def convert(arr,n): 33 | temp=[0]*n; 34 | for i in range(n): 35 | temp[i] = arr[i] 36 | temp.sort(); 37 | for i in range(n): 38 | arr[i] = temp.index(arr[i])+1 39 | 40 | def getInvCountAdvance(arr,n): 41 | invcount = 0 42 | convert(arr, n) 43 | BIT=[0]*(n+1); 44 | for i in range(n+1): 45 | BIT[i] = 0; 46 | i=n-1 47 | while i>=0: 48 | invcount = invcount+getSum(BIT, arr[i]-1) 49 | updateBIT(BIT, n, arr[i], 1) 50 | i=i-1 51 | return invcount 52 | 53 | print "Navie Bit solution" 54 | print getInvCount(numList,len(numList)) 55 | print "Θ(n) solution solution" 56 | print getInvCountAdvance(numList,len(numList)) 57 | -------------------------------------------------------------------------------- /Miscellaneous Algorithms/CountingInversions.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | numList=map(int,raw_input("Enter number present in array:").split()) 3 | 4 | count = 0 5 | def getInvCount(arr,n): 6 | inv_count = 0 7 | for i in range(n): 8 | for i in range(i+1,n): 9 | if arr[i]>arr[j] : 10 | inv_coun=inv_count+1 11 | return inv_count 12 | 13 | def inversionsCount(x): 14 | global count 15 | midsection = len(x) / 2 16 | leftArray = x[:midsection] 17 | rightArray = x[midsection:] 18 | if len(x) > 1: 19 | # Divid and conquer with recursive calls 20 | # to left and right arrays similar to 21 | # merge sort algorithm 22 | inversionsCount(leftArray) 23 | inversionsCount(rightArray) 24 | 25 | # Merge sorted sub-arrays and keep 26 | # count of split inversions 27 | i, j = 0, 0 28 | a = leftArray; b = rightArray 29 | for k in range(len(a) + len(b) + 1): 30 | if a[i] <= b[j]: 31 | x[k] = a[i] 32 | i += 1 33 | if i == len(a) and j != len(b): 34 | while j != len(b): 35 | k +=1 36 | x[k] = b[j] 37 | j += 1 38 | break 39 | elif a[i] > b[j]: 40 | x[k] = b[j] 41 | count += (len(a) - i) 42 | j += 1 43 | if j == len(b) and i != len(a): 44 | while i != len(a): 45 | k+= 1 46 | x[k] = a[i] 47 | i += 1 48 | break 49 | return x 50 | print "Logrithmic solution" 51 | inversionsCount(numList) 52 | print count 53 | print "nsaquare solution solution" 54 | print getInvCount(numList,len(numList)) 55 | -------------------------------------------------------------------------------- /Prime Numbers And Prime Factorization /PrimalityTest(I,II,III).py: -------------------------------------------------------------------------------- 1 | import math 2 | import sys 3 | import random 4 | def log2(n): 5 | return math.log(n)/math.log(2) 6 | 7 | 8 | def power(x,y,p): 9 | '(x^y)%p' 10 | res=1 11 | x=x%p 12 | while y: 13 | if y & 1: 14 | res=(res*x)%p 15 | x=(x*x)%p 16 | y=y>>1 17 | return res 18 | 19 | class primalityTest: 20 | """ 21 | 1.O(n) 22 | 2.O(n^1/2) 23 | 3.Fermat O(k Log n) 24 | 4.Miller-Rabin Miller-Rabin 25 | """ 26 | def __init__(self): 27 | pass 28 | 29 | def isPrime(self,n,test=1): 30 | if test==1 : 31 | return self.isPrimeTest1(n) 32 | elif test==2: 33 | return self.isPrimeTest2(n) 34 | elif test==3: 35 | return self.isPrimeTest3(n) 36 | elif test==4: 37 | return self.isPrimeTest4(n) 38 | else: 39 | print "out of range method index" 40 | 41 | def isPrimeTest1(self,n): 42 | i=2 43 | while i < n-1 : 44 | if n%i==0: 45 | return False 46 | i+=1 47 | return True 48 | 49 | def isPrimeTest2(self,n): 50 | if n <=1 : 51 | return False 52 | if n <=3 : 53 | return True 54 | 55 | if n%2==0 or n%3==0 : 56 | return False 57 | 58 | i=5 59 | while i*i < n : 60 | if n%i==0 or n%(i+2)==0: 61 | return False 62 | i+=6 63 | return True 64 | def isPrimeTest3(self,n): 65 | '''Fermat Method''' 66 | if n <=1 or n==4 : 67 | return False 68 | if n <= 3 : 69 | return True 70 | maxk=int(math.ceil(log2(n))) 71 | k=maxk 72 | while k : 73 | a=random.randint(2,n-1) 74 | if not power(a,n-1,n)==1: 75 | return False 76 | k-=1 77 | return True 78 | 79 | def millerRabinTest(self,n,d): 80 | a=random.randint(2,n-1) 81 | x=power(a,d,n) # (a^d)%n 82 | if x==1 or x==n-1 : 83 | return True 84 | while not d==n-1: 85 | x=(x*x)%n 86 | d*=2 87 | if x==1: 88 | return False 89 | if x==n-1: 90 | return True 91 | return False 92 | 93 | def isPrimeTest4(self,n): 94 | 'Miller-Rabin Method' 95 | d=n-1 96 | while d%2==0: 97 | d /=2 98 | k=5 99 | if n<=1 or n==4 : 100 | return False 101 | if n <= 3 : 102 | return True 103 | 104 | while k : 105 | if self.millerRabinTest(n,d)==False : 106 | return False 107 | k-=1 108 | return True 109 | 110 | 111 | if __name__=="__main__": 112 | if len(sys.argv) > 1: 113 | n=int(sys.argv[1]) 114 | if len(sys.argv) > 2 : 115 | t=int(sys.argv[2]) 116 | else: 117 | t=1 118 | pt=primalityTest() 119 | r=pt.isPrime(n,t) 120 | print r 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Top10algoritms 2 | Top 10 Algorithms and Data Structures for Competitive Programming 3 | 4 | ### GraphAlgorithms 5 | 6 | 1. Breadth First Search (BFS) 7 | 2. Depth First Search (DFS) 8 | 3. Shortest Path from source to all vertices **Dijkstra** 9 | 4. Shortest Path from every vertex to every other vertex **Floyd Warshall** 10 | 5. Minimum Spanning tree **Prim** 11 | 6. Minimum Spanning tree **Kruskal** 12 | 7. Topological Sort 13 | 8. Johnson’s algorithm 14 | 9. Articulation Points (or Cut Vertices) in a Graph 15 | 10. Bridges in a graph 16 | 17 | 18 | 19 | ### Dynamic Programming 20 | 21 | 1. Longest Common Subsequence 22 | 2. Longest Increasing Subsequence 23 | 3. Edit Distance 24 | 4. Minimum Partition 25 | 5. Ways to Cover a Distance 26 | 6. Longest Path In Matrix 27 | 7. Subset Sum Problem - P 28 | 8. Optimal Strategy for a Game 29 | 9. 0-1 Knapsack Problem 30 | 10. Assembly Line Scheduling 31 | 32 | 33 | 34 | 35 | 36 | ### Searching And Sorting 37 | 38 | 1. Binary Search 39 | 2. Quick Sort 40 | 3. Merge Sort 41 | 4. Order Statistics 42 | 5. KMP algorithm 43 | 6. Rabin karp 44 | 7. Z’s algorithm 45 | 8. Aho Corasick String Matching 46 | 9. Counting Sort 47 | 10. Manacher’s algorithm: Part 1, Part 2 and Part 3 48 | 49 | ## Number theory and Other Mathematical 50 | 51 | #### Prime Numbers and Prime Factorization 52 | 53 | 1. Primality Test 54 | 1. Set 1 (Introduction and School Method) 55 | 2. Set 2 (Fermat Method) 56 | 3. Set 3 (Miller–Rabin) 57 | 2. Sieve of Eratosthenes 58 | 3. Segmented Sieve 59 | 4. Wilson’s Theorem - P 60 | 5. Prime Factorisation 61 | 6. Pollard’s rho algorithm 62 | 63 | 64 | #### Modulo Arithmetic Algorithms 65 | 66 | 1. Basic and Extended Euclidean algorithms 67 | 2. Euler’s Totient Function 68 | 3. Modular Exponentiation 69 | 4. Modular Multiplicative Inverse 70 | 5. Chinese remainder theorem and Modulo Inverse Implementation 71 | 6. nCr%m 72 | 73 | #### Miscellaneous Algorithms 74 | 75 | 1. Counting Inversions 76 | 2. Counting Inversions using BIT 77 | 3. logarithmic exponentiation 78 | 4. Square root of an integer 79 | 5. Heavy light Decomposition and this 80 | 6. Matrix Rank 81 | 7. Hungarian algorithm 82 | 8. Link cut 83 | 9. Mo’s algorithm and this 84 | 10. Russian Peasant Multiplication 85 | 11. Catalan Number 86 | 87 | 88 | 89 | ### Geometrical and Network Flow Algorithms 90 | 91 | 1. Convex Hull 92 | 2. Graham Scan 93 | 3. Line Intersection 94 | 4. Interval Tree 95 | 5. Matrix Exponentiation 96 | 6. Maxflow Ford Furkerson Algo and Edmond Karp Implementation 97 | 7. Min cut 98 | 8. Stable Marriage Problem 99 | 9. Hopcroft–Karp Algorithm for Maximum Matching 100 | 10. Dinic’s algo 101 | 102 | ### Data Structures 103 | 104 | 1. Binary Indexed Tree or Fenwick tree 105 | 2. Segment Tree (RMQ, Range Sum and Lazy Propagation) 106 | 3. K-D tree (See insert, minimum and delete) 107 | 4. Union Find Disjoint Set (Cycle Detection and By Rank and Path Compression) 108 | 5. Tries 109 | 6. Suffix array (this, this and this) 110 | 7. Sparse table 111 | 8. Suffix automata 112 | 9. Suffix automata II 113 | 10. LCA and RMQ 114 | 115 | ### Approximate sequence matching 116 | 1. Bitap algorithm 117 | 2. Phonetic algorithms 118 | 3. Daitch–Mokotoff Soundex 119 | 4. String metrics 120 | 5. Damerau–Levenshtein distance 121 | 6. Trigram search 122 | 123 | Source @ http://www.geeksforgeeks.org/top-algorithms-and-data-structures-for-competitive-programming/ 124 | -------------------------------------------------------------------------------- /Graph Algorithms/Dijakstra.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class Vertex: 4 | def __init__(self, node): 5 | self.id = node 6 | self.adjacent = {} 7 | # Set distance to infinity for all nodes 8 | self.distance = sys.maxint 9 | # Mark all nodes unvisited 10 | self.visited = False 11 | # Predecessor 12 | self.previous = None 13 | 14 | def add_neighbor(self, neighbor, weight=0): 15 | self.adjacent[neighbor] = weight 16 | 17 | def get_connections(self): 18 | return self.adjacent.keys() 19 | 20 | def get_id(self): 21 | return self.id 22 | 23 | def get_weight(self, neighbor): 24 | return self.adjacent[neighbor] 25 | 26 | def set_distance(self, dist): 27 | self.distance = dist 28 | 29 | def get_distance(self): 30 | return self.distance 31 | 32 | def set_previous(self, prev): 33 | self.previous = prev 34 | 35 | def set_visited(self): 36 | self.visited = True 37 | 38 | def __str__(self): 39 | return str(self.id) + ' adjacent: ' + str([x.id for x in self.adjacent]) 40 | 41 | class Graph: 42 | def __init__(self): 43 | self.vert_dict = {} 44 | self.num_vertices = 0 45 | 46 | def __iter__(self): 47 | return iter(self.vert_dict.values()) 48 | 49 | def add_vertex(self, node): 50 | self.num_vertices = self.num_vertices + 1 51 | new_vertex = Vertex(node) 52 | self.vert_dict[node] = new_vertex 53 | return new_vertex 54 | 55 | def get_vertex(self, n): 56 | if n in self.vert_dict: 57 | return self.vert_dict[n] 58 | else: 59 | return None 60 | 61 | def add_edge(self, frm, to, cost = 0): 62 | if frm not in self.vert_dict: 63 | self.add_vertex(frm) 64 | if to not in self.vert_dict: 65 | self.add_vertex(to) 66 | 67 | self.vert_dict[frm].add_neighbor(self.vert_dict[to], cost) 68 | self.vert_dict[to].add_neighbor(self.vert_dict[frm], cost) 69 | 70 | def get_vertices(self): 71 | return self.vert_dict.keys() 72 | 73 | def set_previous(self, current): 74 | self.previous = current 75 | 76 | def get_previous(self, current): 77 | return self.previous 78 | 79 | def shortest(v, path): 80 | ''' make shortest path from v.previous''' 81 | if v.previous: 82 | path.append(v.previous.get_id()) 83 | shortest(v.previous, path) 84 | return 85 | 86 | import heapq 87 | 88 | def dijkstra(aGraph, start): 89 | print '''Dijkstra's shortest path''' 90 | # Set the distance for the start node to zero 91 | start.set_distance(0) 92 | 93 | # Put tuple pair into the priority queue 94 | unvisited_queue = [(v.get_distance(),v) for v in aGraph] 95 | heapq.heapify(unvisited_queue) 96 | 97 | while len(unvisited_queue): 98 | # Pops a vertex with the smallest distance 99 | uv = heapq.heappop(unvisited_queue) 100 | current = uv[1] 101 | current.set_visited() 102 | 103 | #for next in v.adjacent: 104 | for next in current.adjacent: 105 | # if visited, skip 106 | if next.visited: 107 | continue 108 | new_dist = current.get_distance() + current.get_weight(next) 109 | 110 | if new_dist < next.get_distance(): 111 | next.set_distance(new_dist) 112 | next.set_previous(current) 113 | print 'updated : current = %s next = %s new_dist = %s' \ 114 | %(current.get_id(), next.get_id(), next.get_distance()) 115 | else: 116 | print 'not updated : current = %s next = %s new_dist = %s' \ 117 | %(current.get_id(), next.get_id(), next.get_distance()) 118 | 119 | # Rebuild heap 120 | # 1. Pop every item 121 | while len(unvisited_queue): 122 | heapq.heappop(unvisited_queue) 123 | # 2. Put all vertices not visited into the queue 124 | unvisited_queue = [(v.get_distance(),v) for v in aGraph if not v.visited] 125 | heapq.heapify(unvisited_queue) 126 | 127 | 128 | if __name__ == '__main__': 129 | 130 | g = Graph() 131 | 132 | g.add_vertex('a') 133 | g.add_vertex('b') 134 | g.add_vertex('c') 135 | g.add_vertex('d') 136 | g.add_vertex('e') 137 | g.add_vertex('f') 138 | 139 | g.add_edge('a', 'b', 7) 140 | g.add_edge('a', 'c', 9) 141 | g.add_edge('a', 'f', 14) 142 | g.add_edge('b', 'c', 10) 143 | g.add_edge('b', 'd', 15) 144 | g.add_edge('c', 'd', 11) 145 | g.add_edge('c', 'f', 2) 146 | g.add_edge('d', 'e', 6) 147 | g.add_edge('e', 'f', 9) 148 | 149 | print 'Graph data:' 150 | for v in g: 151 | for w in v.get_connections(): 152 | vid = v.get_id() 153 | wid = w.get_id() 154 | print '( %s , %s, %3d)' % ( vid, wid, v.get_weight(w)) 155 | 156 | 157 | dijkstra(g, g.get_vertex('a')) 158 | 159 | target = g.get_vertex('e') 160 | path = [target.get_id()] 161 | shortest(target, path) 162 | print 'The shortest path : %s' %(path[::-1]) 163 | 164 | --------------------------------------------------------------------------------