increment 1

This commit is contained in:
Alex Brown
2018-10-19 07:48:01 -05:00
parent 90979777c7
commit 718b99ae39
130 changed files with 0 additions and 14879 deletions

View File

@ -1,181 +0,0 @@
"""
An AVL tree
"""
from __future__ import print_function
class Node:
def __init__(self, label):
self.label = label
self._parent = None
self._left = None
self._right = None
self.height = 0
@property
def right(self):
return self._right
@right.setter
def right(self, node):
if node is not None:
node._parent = self
self._right = node
@property
def left(self):
return self._left
@left.setter
def left(self, node):
if node is not None:
node._parent = self
self._left = node
@property
def parent(self):
return self._parent
@parent.setter
def parent(self, node):
if node is not None:
self._parent = node
self.height = self.parent.height + 1
else:
self.height = 0
class AVL:
def __init__(self):
self.root = None
self.size = 0
def insert(self, value):
node = Node(value)
if self.root is None:
self.root = node
self.root.height = 0
self.size = 1
else:
# Same as Binary Tree
dad_node = None
curr_node = self.root
while True:
if curr_node is not None:
dad_node = curr_node
if node.label < curr_node.label:
curr_node = curr_node.left
else:
curr_node = curr_node.right
else:
node.height = dad_node.height
dad_node.height += 1
if node.label < dad_node.label:
dad_node.left = node
else:
dad_node.right = node
self.rebalance(node)
self.size += 1
break
def rebalance(self, node):
n = node
while n is not None:
height_right = n.height
height_left = n.height
if n.right is not None:
height_right = n.right.height
if n.left is not None:
height_left = n.left.height
if abs(height_left - height_right) > 1:
if height_left > height_right:
left_child = n.left
if left_child is not None:
h_right = (left_child.right.height
if (left_child.right is not None) else 0)
h_left = (left_child.left.height
if (left_child.left is not None) else 0)
if (h_left > h_right):
self.rotate_left(n)
break
else:
self.double_rotate_right(n)
break
else:
right_child = n.right
if right_child is not None:
h_right = (right_child.right.height
if (right_child.right is not None) else 0)
h_left = (right_child.left.height
if (right_child.left is not None) else 0)
if (h_left > h_right):
self.double_rotate_left(n)
break
else:
self.rotate_right(n)
break
n = n.parent
def rotate_left(self, node):
aux = node.parent.label
node.parent.label = node.label
node.parent.right = Node(aux)
node.parent.right.height = node.parent.height + 1
node.parent.left = node.right
def rotate_right(self, node):
aux = node.parent.label
node.parent.label = node.label
node.parent.left = Node(aux)
node.parent.left.height = node.parent.height + 1
node.parent.right = node.right
def double_rotate_left(self, node):
self.rotate_right(node.getRight().getRight())
self.rotate_left(node)
def double_rotate_right(self, node):
self.rotate_left(node.getLeft().getLeft())
self.rotate_right(node)
def empty(self):
if self.root is None:
return True
return False
def preShow(self, curr_node):
if curr_node is not None:
self.preShow(curr_node.left)
print(curr_node.label, end=" ")
self.preShow(curr_node.right)
def preorder(self, curr_node):
if curr_node is not None:
self.preShow(curr_node.left)
self.preShow(curr_node.right)
print(curr_node.label, end=" ")
def getRoot(self):
return self.root
t = AVL()
t.insert(1)
t.insert(2)
t.insert(3)
# t.preShow(t.root)
# print("\n")
# t.insert(4)
# t.insert(5)
# t.preShow(t.root)
# t.preorden(t.root)

View File

@ -1,3 +0,0 @@
arr = [10, 20, 30, 40]
arr[1] = 30
print(arr)

View File

@ -1,29 +0,0 @@
from __future__ import print_function
class FenwickTree:
def __init__(self, SIZE): # create fenwick tree with size SIZE
self.Size = SIZE
self.ft = [0 for i in range (0,SIZE)]
def update(self, i, val): # update data (adding) in index i in O(lg N)
while (i < self.Size):
self.ft[i] += val
i += i & (-i)
def query(self, i): # query cumulative data from index 0 to i in O(lg N)
ret = 0
while (i > 0):
ret += self.ft[i]
i -= i & (-i)
return ret
if __name__ == '__main__':
f = FenwickTree(100)
f.update(1,20)
f.update(4,4)
print (f.query(1))
print (f.query(3))
print (f.query(4))
f.update(2,-5)
print (f.query(1))
print (f.query(3))

View File

@ -1,91 +0,0 @@
from __future__ import print_function
import math
class SegmentTree:
def __init__(self, N):
self.N = N
self.st = [0 for i in range(0,4*N)] # approximate the overall size of segment tree with array N
self.lazy = [0 for i in range(0,4*N)] # create array to store lazy update
self.flag = [0 for i in range(0,4*N)] # flag for lazy update
def left(self, idx):
return idx*2
def right(self, idx):
return idx*2 + 1
def build(self, idx, l, r, A):
if l==r:
self.st[idx] = A[l-1]
else :
mid = (l+r)//2
self.build(self.left(idx),l,mid, A)
self.build(self.right(idx),mid+1,r, A)
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
# update with O(lg N) (Normal segment tree without lazy update will take O(Nlg N) for each update)
def update(self, idx, l, r, a, b, val): # update(1, 1, N, a, b, v) for update val v to [a,b]
if self.flag[idx] == True:
self.st[idx] = self.lazy[idx]
self.flag[idx] = False
if l!=r:
self.lazy[self.left(idx)] = self.lazy[idx]
self.lazy[self.right(idx)] = self.lazy[idx]
self.flag[self.left(idx)] = True
self.flag[self.right(idx)] = True
if r < a or l > b:
return True
if l >= a and r <= b :
self.st[idx] = val
if l!=r:
self.lazy[self.left(idx)] = val
self.lazy[self.right(idx)] = val
self.flag[self.left(idx)] = True
self.flag[self.right(idx)] = True
return True
mid = (l+r)//2
self.update(self.left(idx),l,mid,a,b,val)
self.update(self.right(idx),mid+1,r,a,b,val)
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
return True
# query with O(lg N)
def query(self, idx, l, r, a, b): #query(1, 1, N, a, b) for query max of [a,b]
if self.flag[idx] == True:
self.st[idx] = self.lazy[idx]
self.flag[idx] = False
if l != r:
self.lazy[self.left(idx)] = self.lazy[idx]
self.lazy[self.right(idx)] = self.lazy[idx]
self.flag[self.left(idx)] = True
self.flag[self.right(idx)] = True
if r < a or l > b:
return -math.inf
if l >= a and r <= b:
return self.st[idx]
mid = (l+r)//2
q1 = self.query(self.left(idx),l,mid,a,b)
q2 = self.query(self.right(idx),mid+1,r,a,b)
return max(q1,q2)
def showData(self):
showList = []
for i in range(1,N+1):
showList += [self.query(1, 1, self.N, i, i)]
print (showList)
if __name__ == '__main__':
A = [1,2,-4,7,3,-5,6,11,-20,9,14,15,5,2,-8]
N = 15
segt = SegmentTree(N)
segt.build(1,1,N,A)
print (segt.query(1,1,N,4,6))
print (segt.query(1,1,N,7,11))
print (segt.query(1,1,N,7,12))
segt.update(1,1,N,1,3,111)
print (segt.query(1,1,N,1,15))
segt.update(1,1,N,7,8,235)
segt.showData()

View File

@ -1,71 +0,0 @@
from __future__ import print_function
import math
class SegmentTree:
def __init__(self, A):
self.N = len(A)
self.st = [0] * (4 * self.N) # approximate the overall size of segment tree with array N
self.build(1, 0, self.N - 1)
def left(self, idx):
return idx * 2
def right(self, idx):
return idx * 2 + 1
def build(self, idx, l, r):
if l == r:
self.st[idx] = A[l]
else:
mid = (l + r) // 2
self.build(self.left(idx), l, mid)
self.build(self.right(idx), mid + 1, r)
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
def update(self, a, b, val):
return self.update_recursive(1, 0, self.N - 1, a - 1, b - 1, val)
def update_recursive(self, idx, l, r, a, b, val): # update(1, 1, N, a, b, v) for update val v to [a,b]
if r < a or l > b:
return True
if l == r :
self.st[idx] = val
return True
mid = (l+r)//2
self.update_recursive(self.left(idx), l, mid, a, b, val)
self.update_recursive(self.right(idx), mid+1, r, a, b, val)
self.st[idx] = max(self.st[self.left(idx)] , self.st[self.right(idx)])
return True
def query(self, a, b):
return self.query_recursive(1, 0, self.N - 1, a - 1, b - 1)
def query_recursive(self, idx, l, r, a, b): #query(1, 1, N, a, b) for query max of [a,b]
if r < a or l > b:
return -math.inf
if l >= a and r <= b:
return self.st[idx]
mid = (l+r)//2
q1 = self.query_recursive(self.left(idx), l, mid, a, b)
q2 = self.query_recursive(self.right(idx), mid + 1, r, a, b)
return max(q1, q2)
def showData(self):
showList = []
for i in range(1,N+1):
showList += [self.query(i, i)]
print (showList)
if __name__ == '__main__':
A = [1,2,-4,7,3,-5,6,11,-20,9,14,15,5,2,-8]
N = 15
segt = SegmentTree(A)
print (segt.query(4, 6))
print (segt.query(7, 11))
print (segt.query(7, 12))
segt.update(1,3,111)
print (segt.query(1, 15))
segt.update(7,8,235)
segt.showData()

View File

@ -1,258 +0,0 @@
'''
A binary search Tree
'''
from __future__ import print_function
class Node:
def __init__(self, label, parent):
self.label = label
self.left = None
self.right = None
#Added in order to delete a node easier
self.parent = parent
def getLabel(self):
return self.label
def setLabel(self, label):
self.label = label
def getLeft(self):
return self.left
def setLeft(self, left):
self.left = left
def getRight(self):
return self.right
def setRight(self, right):
self.right = right
def getParent(self):
return self.parent
def setParent(self, parent):
self.parent = parent
class BinarySearchTree:
def __init__(self):
self.root = None
def insert(self, label):
# Create a new Node
new_node = Node(label, None)
# If Tree is empty
if self.empty():
self.root = new_node
else:
#If Tree is not empty
curr_node = self.root
#While we don't get to a leaf
while curr_node is not None:
#We keep reference of the parent node
parent_node = curr_node
#If node label is less than current node
if new_node.getLabel() < curr_node.getLabel():
#We go left
curr_node = curr_node.getLeft()
else:
#Else we go right
curr_node = curr_node.getRight()
#We insert the new node in a leaf
if new_node.getLabel() < parent_node.getLabel():
parent_node.setLeft(new_node)
else:
parent_node.setRight(new_node)
#Set parent to the new node
new_node.setParent(parent_node)
def delete(self, label):
if (not self.empty()):
#Look for the node with that label
node = self.getNode(label)
#If the node exists
if(node is not None):
#If it has no children
if(node.getLeft() is None and node.getRight() is None):
self.__reassignNodes(node, None)
node = None
#Has only right children
elif(node.getLeft() is None and node.getRight() is not None):
self.__reassignNodes(node, node.getRight())
#Has only left children
elif(node.getLeft() is not None and node.getRight() is None):
self.__reassignNodes(node, node.getLeft())
#Has two children
else:
#Gets the max value of the left branch
tmpNode = self.getMax(node.getLeft())
#Deletes the tmpNode
self.delete(tmpNode.getLabel())
#Assigns the value to the node to delete and keesp tree structure
node.setLabel(tmpNode.getLabel())
def getNode(self, label):
curr_node = None
#If the tree is not empty
if(not self.empty()):
#Get tree root
curr_node = self.getRoot()
#While we don't find the node we look for
#I am using lazy evaluation here to avoid NoneType Attribute error
while curr_node is not None and curr_node.getLabel() is not label:
#If node label is less than current node
if label < curr_node.getLabel():
#We go left
curr_node = curr_node.getLeft()
else:
#Else we go right
curr_node = curr_node.getRight()
return curr_node
def getMax(self, root = None):
if(root is not None):
curr_node = root
else:
#We go deep on the right branch
curr_node = self.getRoot()
if(not self.empty()):
while(curr_node.getRight() is not None):
curr_node = curr_node.getRight()
return curr_node
def getMin(self, root = None):
if(root is not None):
curr_node = root
else:
#We go deep on the left branch
curr_node = self.getRoot()
if(not self.empty()):
curr_node = self.getRoot()
while(curr_node.getLeft() is not None):
curr_node = curr_node.getLeft()
return curr_node
def empty(self):
if self.root is None:
return True
return False
def __InOrderTraversal(self, curr_node):
nodeList = []
if curr_node is not None:
nodeList.insert(0, curr_node)
nodeList = nodeList + self.__InOrderTraversal(curr_node.getLeft())
nodeList = nodeList + self.__InOrderTraversal(curr_node.getRight())
return nodeList
def getRoot(self):
return self.root
def __isRightChildren(self, node):
if(node == node.getParent().getRight()):
return True
return False
def __reassignNodes(self, node, newChildren):
if(newChildren is not None):
newChildren.setParent(node.getParent())
if(node.getParent() is not None):
#If it is the Right Children
if(self.__isRightChildren(node)):
node.getParent().setRight(newChildren)
else:
#Else it is the left children
node.getParent().setLeft(newChildren)
#This function traversal the tree. By default it returns an
#In order traversal list. You can pass a function to traversal
#The tree as needed by client code
def traversalTree(self, traversalFunction = None, root = None):
if(traversalFunction is None):
#Returns a list of nodes in preOrder by default
return self.__InOrderTraversal(self.root)
else:
#Returns a list of nodes in the order that the users wants to
return traversalFunction(self.root)
#Returns an string of all the nodes labels in the list
#In Order Traversal
def __str__(self):
list = self.__InOrderTraversal(self.root)
str = ""
for x in list:
str = str + " " + x.getLabel().__str__()
return str
def InPreOrder(curr_node):
nodeList = []
if curr_node is not None:
nodeList = nodeList + InPreOrder(curr_node.getLeft())
nodeList.insert(0, curr_node.getLabel())
nodeList = nodeList + InPreOrder(curr_node.getRight())
return nodeList
def testBinarySearchTree():
'''
Example
8
/ \
3 10
/ \ \
1 6 14
/ \ /
4 7 13
'''
'''
Example After Deletion
7
/ \
1 4
'''
t = BinarySearchTree()
t.insert(8)
t.insert(3)
t.insert(6)
t.insert(1)
t.insert(10)
t.insert(14)
t.insert(13)
t.insert(4)
t.insert(7)
#Prints all the elements of the list in order traversal
print(t.__str__())
if(t.getNode(6) is not None):
print("The label 6 exists")
else:
print("The label 6 doesn't exist")
if(t.getNode(-1) is not None):
print("The label -1 exists")
else:
print("The label -1 doesn't exist")
if(not t.empty()):
print(("Max Value: ", t.getMax().getLabel()))
print(("Min Value: ", t.getMin().getLabel()))
t.delete(13)
t.delete(10)
t.delete(8)
t.delete(3)
t.delete(6)
t.delete(14)
#Gets all the elements of the tree In pre order
#And it prints them
list = t.traversalTree(InPreOrder, t.root)
for x in list:
print(x)
if __name__ == "__main__":
testBinarySearchTree()

View File

@ -1,54 +0,0 @@
from __future__ import print_function
def printDist(dist, V):
print("\nVertex Distance")
for i in range(V):
if dist[i] != float('inf') :
print(i,"\t",int(dist[i]),end = "\t")
else:
print(i,"\t","INF",end="\t")
print()
def BellmanFord(graph, V, E, src):
mdist=[float('inf') for i in range(V)]
mdist[src] = 0.0
for i in range(V-1):
for j in range(V):
u = graph[j]["src"]
v = graph[j]["dst"]
w = graph[j]["weight"]
if mdist[u] != float('inf') and mdist[u] + w < mdist[v]:
mdist[v] = mdist[u] + w
for j in range(V):
u = graph[j]["src"]
v = graph[j]["dst"]
w = graph[j]["weight"]
if mdist[u] != float('inf') and mdist[u] + w < mdist[v]:
print("Negative cycle found. Solution not possible.")
return
printDist(mdist, V)
#MAIN
V = int(raw_input("Enter number of vertices: "))
E = int(raw_input("Enter number of edges: "))
graph = [dict() for j in range(E)]
for i in range(V):
graph[i][i] = 0.0
for i in range(E):
print("\nEdge ",i+1)
src = int(raw_input("Enter source:"))
dst = int(raw_input("Enter destination:"))
weight = float(raw_input("Enter weight:"))
graph[i] = {"src": src,"dst": dst, "weight": weight}
gsrc = int(raw_input("\nEnter shortest path source:"))
BellmanFord(graph, V, E, gsrc)

View File

@ -1,67 +0,0 @@
#!/usr/bin/python
# encoding=utf8
""" Author: OMKAR PATHAK """
from __future__ import print_function
class Graph():
def __init__(self):
self.vertex = {}
# for printing the Graph vertexes
def printGraph(self):
for i in self.vertex.keys():
print(i,' -> ', ' -> '.join([str(j) for j in self.vertex[i]]))
# for adding the edge beween two vertexes
def addEdge(self, fromVertex, toVertex):
# check if vertex is already present,
if fromVertex in self.vertex.keys():
self.vertex[fromVertex].append(toVertex)
else:
# else make a new vertex
self.vertex[fromVertex] = [toVertex]
def BFS(self, startVertex):
# Take a list for stoting already visited vertexes
visited = [False] * len(self.vertex)
# create a list to store all the vertexes for BFS
queue = []
# mark the source node as visited and enqueue it
visited[startVertex] = True
queue.append(startVertex)
while queue:
startVertex = queue.pop(0)
print(startVertex, end = ' ')
# mark all adjacent nodes as visited and print them
for i in self.vertex[startVertex]:
if visited[i] == False:
queue.append(i)
visited[i] = True
if __name__ == '__main__':
g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
g.printGraph()
print('BFS:')
g.BFS(2)
# OUTPUT:
# 0  ->  1 -> 2
# 1  ->  2
# 2  ->  0 -> 3
# 3  ->  3
# BFS:
# 2 0 3 1

View File

@ -1,66 +0,0 @@
#!/usr/bin/python
# encoding=utf8
""" Author: OMKAR PATHAK """
from __future__ import print_function
class Graph():
def __init__(self):
self.vertex = {}
# for printing the Graph vertexes
def printGraph(self):
print(self.vertex)
for i in self.vertex.keys():
print(i,' -> ', ' -> '.join([str(j) for j in self.vertex[i]]))
# for adding the edge beween two vertexes
def addEdge(self, fromVertex, toVertex):
# check if vertex is already present,
if fromVertex in self.vertex.keys():
self.vertex[fromVertex].append(toVertex)
else:
# else make a new vertex
self.vertex[fromVertex] = [toVertex]
def DFS(self):
# visited array for storing already visited nodes
visited = [False] * len(self.vertex)
# call the recursive helper function
for i in range(len(self.vertex)):
if visited[i] == False:
self.DFSRec(i, visited)
def DFSRec(self, startVertex, visited):
# mark start vertex as visited
visited[startVertex] = True
print(startVertex, end = ' ')
# Recur for all the vertexes that are adjacent to this node
for i in self.vertex.keys():
if visited[i] == False:
self.DFSRec(i, visited)
if __name__ == '__main__':
g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
g.printGraph()
print('DFS:')
g.DFS()
# OUTPUT:
# 0  ->  1 -> 2
# 1  ->  2
# 2  ->  0 -> 3
# 3  ->  3
# DFS:
# 0 1 2 3

View File

@ -1,57 +0,0 @@
from __future__ import print_function
def printDist(dist, V):
print("\nVertex Distance")
for i in range(V):
if dist[i] != float('inf') :
print(i,"\t",int(dist[i]),end = "\t")
else:
print(i,"\t","INF",end="\t")
print()
def minDist(mdist, vset, V):
minVal = float('inf')
minInd = -1
for i in range(V):
if (not vset[i]) and mdist[i] < minVal :
minInd = i
minVal = mdist[i]
return minInd
def Dijkstra(graph, V, src):
mdist=[float('inf') for i in range(V)]
vset = [False for i in range(V)]
mdist[src] = 0.0;
for i in range(V-1):
u = minDist(mdist, vset, V)
vset[u] = True
for v in range(V):
if (not vset[v]) and graph[u][v]!=float('inf') and mdist[u] + graph[u][v] < mdist[v]:
mdist[v] = mdist[u] + graph[u][v]
printDist(mdist, V)
#MAIN
V = int(raw_input("Enter number of vertices: "))
E = int(raw_input("Enter number of edges: "))
graph = [[float('inf') for i in range(V)] for j in range(V)]
for i in range(V):
graph[i][i] = 0.0
for i in range(E):
print("\nEdge ",i+1)
src = int(raw_input("Enter source:"))
dst = int(raw_input("Enter destination:"))
weight = float(raw_input("Enter weight:"))
graph[src][dst] = weight
gsrc = int(raw_input("\nEnter shortest path source:"))
Dijkstra(graph, V, gsrc)

View File

@ -1,48 +0,0 @@
from __future__ import print_function
def printDist(dist, V):
print("\nThe shortest path matrix using Floyd Warshall algorithm\n")
for i in range(V):
for j in range(V):
if dist[i][j] != float('inf') :
print(int(dist[i][j]),end = "\t")
else:
print("INF",end="\t")
print()
def FloydWarshall(graph, V):
dist=[[float('inf') for i in range(V)] for j in range(V)]
for i in range(V):
for j in range(V):
dist[i][j] = graph[i][j]
for k in range(V):
for i in range(V):
for j in range(V):
if dist[i][k]!=float('inf') and dist[k][j]!=float('inf') and dist[i][k]+dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
printDist(dist, V)
#MAIN
V = int(raw_input("Enter number of vertices: "))
E = int(raw_input("Enter number of edges: "))
graph = [[float('inf') for i in range(V)] for j in range(V)]
for i in range(V):
graph[i][i] = 0.0
for i in range(E):
print("\nEdge ",i+1)
src = int(raw_input("Enter source:"))
dst = int(raw_input("Enter destination:"))
weight = float(raw_input("Enter weight:"))
graph[src][dst] = weight
FloydWarshall(graph, V)

View File

@ -1,44 +0,0 @@
#!/usr/bin/python
# encoding=utf8
from __future__ import print_function
# Author: OMKAR PATHAK
# We can use Python's dictionary for constructing the graph
class AdjacencyList(object):
def __init__(self):
self.List = {}
def addEdge(self, fromVertex, toVertex):
# check if vertex is already present
if fromVertex in self.List.keys():
self.List[fromVertex].append(toVertex)
else:
self.List[fromVertex] = [toVertex]
def printList(self):
for i in self.List:
print((i,'->',' -> '.join([str(j) for j in self.List[i]])))
if __name__ == '__main__':
al = AdjacencyList()
al.addEdge(0, 1)
al.addEdge(0, 4)
al.addEdge(4, 1)
al.addEdge(4, 3)
al.addEdge(1, 0)
al.addEdge(1, 4)
al.addEdge(1, 3)
al.addEdge(1, 2)
al.addEdge(2, 3)
al.addEdge(3, 4)
al.printList()
# OUTPUT:
# 0 -> 1 -> 4
# 1 -> 0 -> 4 -> 3 -> 2
# 2 -> 3
# 3 -> 4
# 4 -> 1 -> 3

View File

@ -1,31 +0,0 @@
from __future__ import print_function
class Graph:
def __init__(self, vertex):
self.vertex = vertex
self.graph = [[0] for i in range(vertex)]
def add_edge(self, u, v):
self.graph[u - 1].append(v - 1)
def show(self):
for i in range(self.vertex):
print('%d: '% (i + 1), end=' ')
for j in self.graph[i]:
print('%d-> '% (j + 1), end=' ')
print(' ')
g = Graph(100)
g.add_edge(1,3)
g.add_edge(2,3)
g.add_edge(3,4)
g.add_edge(3,5)
g.add_edge(4,5)
g.show()

View File

@ -1,32 +0,0 @@
from __future__ import print_function
class Graph:
def __init__(self, vertex):
self.vertex = vertex
self.graph = [[0] * vertex for i in range(vertex) ]
def add_edge(self, u, v):
self.graph[u - 1][v - 1] = 1
self.graph[v - 1][u - 1] = 1
def show(self):
for i in self.graph:
for j in i:
print(j, end=' ')
print(' ')
g = Graph(100)
g.add_edge(1,4)
g.add_edge(4,2)
g.add_edge(4,5)
g.add_edge(2,5)
g.add_edge(5,3)
g.show()

View File

@ -1,212 +0,0 @@
# Title: Dijkstra's Algorithm for finding single source shortest path from scratch
# Author: Shubham Malik
# References: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
from __future__ import print_function
import math
import sys
# For storing the vertex set to retreive node with the lowest distance
class PriorityQueue:
# Based on Min Heap
def __init__(self):
self.cur_size = 0
self.array = []
self.pos = {} # To store the pos of node in array
def isEmpty(self):
return self.cur_size == 0
def min_heapify(self, idx):
lc = self.left(idx)
rc = self.right(idx)
if lc < self.cur_size and self.array(lc)[0] < self.array(idx)[0]:
smallest = lc
else:
smallest = idx
if rc < self.cur_size and self.array(rc)[0] < self.array(smallest)[0]:
smallest = rc
if smallest != idx:
self.swap(idx, smallest)
self.min_heapify(smallest)
def insert(self, tup):
# Inserts a node into the Priority Queue
self.pos[tup[1]] = self.cur_size
self.cur_size += 1
self.array.append((sys.maxsize, tup[1]))
self.decrease_key((sys.maxsize, tup[1]), tup[0])
def extract_min(self):
# Removes and returns the min element at top of priority queue
min_node = self.array[0][1]
self.array[0] = self.array[self.cur_size - 1]
self.cur_size -= 1
self.min_heapify(1)
del self.pos[min_node]
return min_node
def left(self, i):
# returns the index of left child
return 2 * i + 1
def right(self, i):
# returns the index of right child
return 2 * i + 2
def par(self, i):
# returns the index of parent
return math.floor(i / 2)
def swap(self, i, j):
# swaps array elements at indices i and j
# update the pos{}
self.pos[self.array[i][1]] = j
self.pos[self.array[j][1]] = i
temp = self.array[i]
self.array[i] = self.array[j]
self.array[j] = temp
def decrease_key(self, tup, new_d):
idx = self.pos[tup[1]]
# assuming the new_d is atmost old_d
self.array[idx] = (new_d, tup[1])
while idx > 0 and self.array[self.par(idx)][0] > self.array[idx][0]:
self.swap(idx, self.par(idx))
idx = self.par(idx)
class Graph:
def __init__(self, num):
self.adjList = {} # To store graph: u -> (v,w)
self.num_nodes = num # Number of nodes in graph
# To store the distance from source vertex
self.dist = [0] * self.num_nodes
self.par = [-1] * self.num_nodes # To store the path
def add_edge(self, u, v, w):
# Edge going from node u to v and v to u with weight w
# u (w)-> v, v (w) -> u
# Check if u already in graph
if u in self.adjList.keys():
self.adjList[u].append((v, w))
else:
self.adjList[u] = [(v, w)]
# Assuming undirected graph
if v in self.adjList.keys():
self.adjList[v].append((u, w))
else:
self.adjList[v] = [(u, w)]
def show_graph(self):
# u -> v(w)
for u in self.adjList:
print(u, '->', ' -> '.join(str("{}({})".format(v, w))
for v, w in self.adjList[u]))
def dijkstra(self, src):
# Flush old junk values in par[]
self.par = [-1] * self.num_nodes
# src is the source node
self.dist[src] = 0
Q = PriorityQueue()
Q.insert((0, src)) # (dist from src, node)
for u in self.adjList.keys():
if u != src:
self.dist[u] = sys.maxsize # Infinity
self.par[u] = -1
while not Q.isEmpty():
u = Q.extract_min() # Returns node with the min dist from source
# Update the distance of all the neighbours of u and
# if their prev dist was INFINITY then push them in Q
for v, w in self.adjList[u]:
new_dist = self.dist[u] + w
if self.dist[v] > new_dist:
if self.dist[v] == sys.maxsize:
Q.insert((new_dist, v))
else:
Q.decrease_key((self.dist[v], v), new_dist)
self.dist[v] = new_dist
self.par[v] = u
# Show the shortest distances from src
self.show_distances(src)
def show_distances(self, src):
print("Distance from node: {}".format(src))
for u in range(self.num_nodes):
print('Node {} has distance: {}'.format(u, self.dist[u]))
def show_path(self, src, dest):
# To show the shortest path from src to dest
# WARNING: Use it *after* calling dijkstra
path = []
cost = 0
temp = dest
# Backtracking from dest to src
while self.par[temp] != -1:
path.append(temp)
if temp != src:
for v, w in self.adjList[temp]:
if v == self.par[temp]:
cost += w
break
temp = self.par[temp]
path.append(src)
path.reverse()
print('----Path to reach {} from {}----'.format(dest, src))
for u in path:
print('{}'.format(u), end=' ')
if u != dest:
print('-> ', end='')
print('\nTotal cost of path: ', cost)
if __name__ == '__main__':
graph = Graph(9)
graph.add_edge(0, 1, 4)
graph.add_edge(0, 7, 8)
graph.add_edge(1, 2, 8)
graph.add_edge(1, 7, 11)
graph.add_edge(2, 3, 7)
graph.add_edge(2, 8, 2)
graph.add_edge(2, 5, 4)
graph.add_edge(3, 4, 9)
graph.add_edge(3, 5, 14)
graph.add_edge(4, 5, 10)
graph.add_edge(5, 6, 2)
graph.add_edge(6, 7, 1)
graph.add_edge(6, 8, 6)
graph.add_edge(7, 8, 7)
graph.show_graph()
graph.dijkstra(0)
graph.show_path(0, 4)
# OUTPUT
# 0 -> 1(4) -> 7(8)
# 1 -> 0(4) -> 2(8) -> 7(11)
# 7 -> 0(8) -> 1(11) -> 6(1) -> 8(7)
# 2 -> 1(8) -> 3(7) -> 8(2) -> 5(4)
# 3 -> 2(7) -> 4(9) -> 5(14)
# 8 -> 2(2) -> 6(6) -> 7(7)
# 5 -> 2(4) -> 3(14) -> 4(10) -> 6(2)
# 4 -> 3(9) -> 5(10)
# 6 -> 5(2) -> 7(1) -> 8(6)
# Distance from node: 0
# Node 0 has distance: 0
# Node 1 has distance: 4
# Node 2 has distance: 12
# Node 3 has distance: 19
# Node 4 has distance: 21
# Node 5 has distance: 11
# Node 6 has distance: 9
# Node 7 has distance: 8
# Node 8 has distance: 14
# ----Path to reach 4 from 0----
# 0 -> 7 -> 6 -> 5 -> 4
# Total cost of path: 21

View File

@ -1,70 +0,0 @@
"""
You are given a tree(a simple connected graph with no cycles). The tree has N
nodes numbered from 1 to N and is rooted at node 1.
Find the maximum number of edges you can remove from the tree to get a forest
such that each connected component of the forest contains an even number of
nodes.
Constraints
2 <= 2 <= 100
Note: The tree input will be such that it can always be decomposed into
components containing an even number of nodes.
"""
from __future__ import print_function
# pylint: disable=invalid-name
from collections import defaultdict
def dfs(start):
"""DFS traversal"""
# pylint: disable=redefined-outer-name
ret = 1
visited[start] = True
for v in tree.get(start):
if v not in visited:
ret += dfs(v)
if ret % 2 == 0:
cuts.append(start)
return ret
def even_tree():
"""
2 1
3 1
4 3
5 2
6 1
7 2
8 6
9 8
10 8
On removing edges (1,3) and (1,6), we can get the desired result 2.
"""
dfs(1)
if __name__ == '__main__':
n, m = 10, 9
tree = defaultdict(list)
visited = {}
cuts = []
count = 0
edges = [
(2, 1),
(3, 1),
(4, 3),
(5, 2),
(6, 1),
(7, 2),
(8, 6),
(9, 8),
(10, 8),
]
for u, v in edges:
tree[u].append(v)
tree[v].append(u)
even_tree()
print(len(cuts) - 1)

View File

@ -1,90 +0,0 @@
#!/usr/bin/python
from __future__ import print_function, division
try:
raw_input # Python 2
except NameError:
raw_input = input # Python 3
class Heap:
def __init__(self):
self.h = []
self.currsize = 0
def leftChild(self,i):
if 2*i+1 < self.currsize:
return 2*i+1
return None
def rightChild(self,i):
if 2*i+2 < self.currsize:
return 2*i+2
return None
def maxHeapify(self,node):
if node < self.currsize:
m = node
lc = self.leftChild(node)
rc = self.rightChild(node)
if lc is not None and self.h[lc] > self.h[m]:
m = lc
if rc is not None and self.h[rc] > self.h[m]:
m = rc
if m!=node:
temp = self.h[node]
self.h[node] = self.h[m]
self.h[m] = temp
self.maxHeapify(m)
def buildHeap(self,a):
self.currsize = len(a)
self.h = list(a)
for i in range(self.currsize/2,-1,-1):
self.maxHeapify(i)
def getMax(self):
if self.currsize >= 1:
me = self.h[0]
temp = self.h[0]
self.h[0] = self.h[self.currsize-1]
self.h[self.currsize-1] = temp
self.currsize -= 1
self.maxHeapify(0)
return me
return None
def heapSort(self):
size = self.currsize
while self.currsize-1 >= 0:
temp = self.h[0]
self.h[0] = self.h[self.currsize-1]
self.h[self.currsize-1] = temp
self.currsize -= 1
self.maxHeapify(0)
self.currsize = size
def insert(self,data):
self.h.append(data)
curr = self.currsize
self.currsize+=1
while self.h[curr] > self.h[curr/2]:
temp = self.h[curr/2]
self.h[curr/2] = self.h[curr]
self.h[curr] = temp
curr = curr/2
def display(self):
print(self.h)
def main():
l = list(map(int, raw_input().split()))
h = Heap()
h.buildHeap(l)
h.heapSort()
h.display()
if __name__=='__main__':
main()

View File

@ -1,76 +0,0 @@
'''
- A linked list is similar to an array, it holds values. However, links in a linked list do not have indexes.
- This is an example of a double ended, doubly linked list.
- Each link references the next link and the previous one.
'''
from __future__ import print_function
class LinkedList:
def __init__(self):
self.head = None
self.tail = None
def insertHead(self, x):
newLink = Link(x) #Create a new link with a value attached to it
if(self.isEmpty() == True): #Set the first element added to be the tail
self.tail = newLink
else:
self.head.previous = newLink # newLink <-- currenthead(head)
newLink.next = self.head # newLink <--> currenthead(head)
self.head = newLink # newLink(head) <--> oldhead
def deleteHead(self):
temp = self.head
self.head = self.head.next # oldHead <--> 2ndElement(head)
self.head.previous = None # oldHead --> 2ndElement(head) nothing pointing at it so the old head will be removed
if(self.head is None):
self.tail = None
return temp
def insertTail(self, x):
newLink = Link(x)
newLink.next = None # currentTail(tail) newLink -->
self.tail.next = newLink # currentTail(tail) --> newLink -->
newLink.previous = self.tail #currentTail(tail) <--> newLink -->
self.tail = newLink # oldTail <--> newLink(tail) -->
def deleteTail(self):
temp = self.tail
self.tail = self.tail.previous # 2ndLast(tail) <--> oldTail --> None
self.tail.next = None # 2ndlast(tail) --> None
return temp
def delete(self, x):
current = self.head
while(current.value != x): # Find the position to delete
current = current.next
if(current == self.head):
self.deleteHead()
elif(current == self.tail):
self.deleteTail()
else: #Before: 1 <--> 2(current) <--> 3
current.previous.next = current.next # 1 --> 3
current.next.previous = current.previous # 1 <--> 3
def isEmpty(self): #Will return True if the list is empty
return(self.head is None)
def display(self): #Prints contents of the list
current = self.head
while(current != None):
current.displayLink()
current = current.next
print()
class Link:
next = None #This points to the link in front of the new link
previous = None #This points to the link behind the new link
def __init__(self, x):
self.value = x
def displayLink(self):
print("{}".format(self.value), end=" ")

View File

@ -1,22 +0,0 @@
class Node:
def __init__(self, item, next):
self.item = item
self.next = next
class LinkedList:
def __init__(self):
self.head = None
def add(self, item):
self.head = Node(item, self.head)
def remove(self):
if self.is_empty():
return None
else:
item = self.head.item
self.head = self.head.next
return item
def is_empty(self):
return self.head is None

View File

@ -1,70 +0,0 @@
from __future__ import print_function
class Node: # create a Node
def __init__(self, data):
self.data = data # given data
self.next = None # given next to None
class Linked_List:
def insert_tail(Head, data):
if Head.next is None:
Head.next = Node(data)
else:
Head.next.insert_tail(data)
def insert_head(Head, data):
tamp = Head
if tamp is None:
newNod = Node() # create a new Node
newNod.data = data
newNod.next = None
Head = newNod # make new node to Head
else:
newNod = Node()
newNod.data = data
newNod.next = Head # put the Head at NewNode Next
Head = newNod # make a NewNode to Head
return Head
def printList(Head): # print every node data
tamp = Head
while tamp is not None:
print(tamp.data)
tamp = tamp.next
def delete_head(Head): # delete from head
if Head is not None:
Head = Head.next
return Head # return new Head
def delete_tail(Head): # delete from tail
if Head is not None:
tamp = Node()
tamp = Head
while tamp.next.next is not None: # find the 2nd last element
tamp = tamp.next
# delete the last element by give next None to 2nd last Element
tamp.next = None
return Head
def isEmpty(Head):
return Head is None # Return if Head is none
def reverse(Head):
prev = None
current = Head
while current:
# Store the current node's next node.
next_node = current.next
# Make the current node's next point backwards
current.next = prev
# Make the previous node be the current node
prev = current
# Make the current node the next node (to progress iteration)
current = next_node
# Return prev in order to put the head at the end
Head = prev
return Head

View File

@ -1,40 +0,0 @@
from __future__ import print_function
# Python code to demonstrate working of
# extend(), extendleft(), rotate(), reverse()
# importing "collections" for deque operations
import collections
# initializing deque
de = collections.deque([1, 2, 3,])
# using extend() to add numbers to right end
# adds 4,5,6 to right end
de.extend([4,5,6])
# printing modified deque
print ("The deque after extending deque at end is : ")
print (de)
# using extendleft() to add numbers to left end
# adds 7,8,9 to right end
de.extendleft([7,8,9])
# printing modified deque
print ("The deque after extending deque at beginning is : ")
print (de)
# using rotate() to rotate the deque
# rotates by 3 to left
de.rotate(-3)
# printing modified deque
print ("The deque after rotating deque is : ")
print (de)
# using reverse() to reverse the deque
de.reverse()
# printing modified deque
print ("The deque after reversing deque is : ")
print (de)

View File

@ -1,45 +0,0 @@
"""Queue represented by a python list"""
class Queue():
def __init__(self):
self.entries = []
self.length = 0
self.front=0
def __str__(self):
printed = '<' + str(self.entries)[1:-1] + '>'
return printed
"""Enqueues {@code item}
@param item
item to enqueue"""
def put(self, item):
self.entries.append(item)
self.length = self.length + 1
"""Dequeues {@code item}
@requirement: |self.length| > 0
@return dequeued
item that was dequeued"""
def get(self):
self.length = self.length - 1
dequeued = self.entries[self.front]
self.front-=1
self.entries = self.entries[self.front:]
return dequeued
"""Rotates the queue {@code rotation} times
@param rotation
number of times to rotate queue"""
def rotate(self, rotation):
for i in range(rotation):
self.put(self.get())
"""Enqueues {@code item}
@return item at front of self.entries"""
def front(self):
return self.entries[0]
"""Returns the length of this.entries"""
def size(self):
return self.length

View File

@ -1,50 +0,0 @@
"""Queue represented by a pseudo stack (represented by a list with pop and append)"""
class Queue():
def __init__(self):
self.stack = []
self.length = 0
def __str__(self):
printed = '<' + str(self.stack)[1:-1] + '>'
return printed
"""Enqueues {@code item}
@param item
item to enqueue"""
def put(self, item):
self.stack.append(item)
self.length = self.length + 1
"""Dequeues {@code item}
@requirement: |self.length| > 0
@return dequeued
item that was dequeued"""
def get(self):
self.rotate(1)
dequeued = self.stack[self.length-1]
self.stack = self.stack[:-1]
self.rotate(self.length-1)
self.length = self.length -1
return dequeued
"""Rotates the queue {@code rotation} times
@param rotation
number of times to rotate queue"""
def rotate(self, rotation):
for i in range(rotation):
temp = self.stack[0]
self.stack = self.stack[1:]
self.put(temp)
self.length = self.length - 1
"""Reports item at the front of self
@return item at front of self.stack"""
def front(self):
front = self.get()
self.put(front)
self.rotate(self.length-1)
return front
"""Returns the length of this.stack"""
def size(self):
return self.length

View File

@ -1,52 +0,0 @@
'''
The stock span problem is a financial problem where we have a series of n daily
price quotes for a stock and we need to calculate span of stock's price for all n days.
The span Si of the stock's price on a given day i is defined as the maximum
number of consecutive days just before the given day, for which the price of the stock
on the current day is less than or equal to its price on the given day.
'''
from __future__ import print_function
def calculateSpan(price, S):
n = len(price)
# Create a stack and push index of fist element to it
st = []
st.append(0)
# Span value of first element is always 1
S[0] = 1
# Calculate span values for rest of the elements
for i in range(1, n):
# Pop elements from stack whlie stack is not
# empty and top of stack is smaller than price[i]
while( len(st) > 0 and price[st[0]] <= price[i]):
st.pop()
# If stack becomes empty, then price[i] is greater
# than all elements on left of it, i.e. price[0],
# price[1], ..price[i-1]. Else the price[i] is
# greater than elements after top of stack
S[i] = i+1 if len(st) <= 0 else (i - st[0])
# Push this element to stack
st.append(i)
# A utility function to print elements of array
def printArray(arr, n):
for i in range(0,n):
print (arr[i],end =" ")
# Driver program to test above function
price = [10, 4, 5, 90, 120, 80]
S = [0 for i in range(len(price)+1)]
# Fill the span values in array S[]
calculateSpan(price, S)
# Print the calculated span values
printArray(S, len(price))

View File

@ -1,23 +0,0 @@
class Stack:
def __init__(self):
self.stack = []
self.top = 0
def is_empty(self):
return (self.top == 0)
def push(self, item):
if self.top < len(self.stack):
self.stack[self.top] = item
else:
self.stack.append(item)
self.top += 1
def pop(self):
if self.is_empty():
return None
else:
self.top -= 1
return self.stack[self.top]

View File

@ -1,23 +0,0 @@
from __future__ import print_function
from __future__ import absolute_import
from .Stack import Stack
__author__ = 'Omkar Pathak'
def balanced_parentheses(parentheses):
""" Use a stack to check if a string of parentheses are balanced."""
stack = Stack(len(parentheses))
for parenthesis in parentheses:
if parenthesis == '(':
stack.push(parenthesis)
elif parenthesis == ')':
stack.pop()
return not stack.is_empty()
if __name__ == '__main__':
examples = ['((()))', '((())']
print('Balanced parentheses demonstration:\n')
for example in examples:
print(example + ': ' + str(balanced_parentheses(example)))

View File

@ -1,64 +0,0 @@
from __future__ import print_function
from __future__ import absolute_import
import string
from .Stack import Stack
__author__ = 'Omkar Pathak'
def is_operand(char):
return char in string.ascii_letters or char in string.digits
def precedence(char):
""" Return integer value representing an operator's precedence, or
order of operation.
https://en.wikipedia.org/wiki/Order_of_operations
"""
dictionary = {'+': 1, '-': 1,
'*': 2, '/': 2,
'^': 3}
return dictionary.get(char, -1)
def infix_to_postfix(expression):
""" Convert infix notation to postfix notation using the Shunting-yard
algorithm.
https://en.wikipedia.org/wiki/Shunting-yard_algorithm
https://en.wikipedia.org/wiki/Infix_notation
https://en.wikipedia.org/wiki/Reverse_Polish_notation
"""
stack = Stack(len(expression))
postfix = []
for char in expression:
if is_operand(char):
postfix.append(char)
elif char not in {'(', ')'}:
while (not stack.is_empty()
and precedence(char) <= precedence(stack.peek())):
postfix.append(stack.pop())
stack.push(char)
elif char == '(':
stack.push(char)
elif char == ')':
while not stack.is_empty() and stack.peek() != '(':
postfix.append(stack.pop())
# Pop '(' from stack. If there is no '(', there is a mismatched
# parentheses.
if stack.peek() != '(':
raise ValueError('Mismatched parentheses')
stack.pop()
while not stack.is_empty():
postfix.append(stack.pop())
return ' '.join(postfix)
if __name__ == '__main__':
expression = 'a+b*(c^d-e)^(f+g*h)-i'
print('Infix to Postfix Notation demonstration:\n')
print('Infix notation: ' + expression)
print('Postfix notation: ' + infix_to_postfix(expression))

View File

@ -1,17 +0,0 @@
from __future__ import print_function
# Function to print element and NGE pair for all elements of list
def printNGE(arr):
for i in range(0, len(arr), 1):
next = -1
for j in range(i+1, len(arr), 1):
if arr[i] < arr[j]:
next = arr[j]
break
print(str(arr[i]) + " -- " + str(next))
# Driver program to test above function
arr = [11,13,21,3]
printNGE(arr)

View File

@ -1,69 +0,0 @@
from __future__ import print_function
__author__ = 'Omkar Pathak'
class Stack(object):
""" A stack is an abstract data type that serves as a collection of
elements with two principal operations: push() and pop(). push() adds an
element to the top of the stack, and pop() removes an element from the top
of a stack. The order in which elements come off of a stack are
Last In, First Out (LIFO).
https://en.wikipedia.org/wiki/Stack_(abstract_data_type)
"""
def __init__(self, limit=10):
self.stack = []
self.limit = limit
def __bool__(self):
return not bool(self.stack)
def __str__(self):
return str(self.stack)
def push(self, data):
""" Push an element to the top of the stack."""
if len(self.stack) >= self.limit:
raise StackOverflowError
self.stack.append(data)
def pop(self):
""" Pop an element off of the top of the stack."""
if self.stack:
return self.stack.pop()
else:
raise IndexError('pop from an empty stack')
def peek(self):
""" Peek at the top-most element of the stack."""
if self.stack:
return self.stack[-1]
def is_empty(self):
""" Check if a stack is empty."""
return not bool(self.stack)
def size(self):
""" Return the size of the stack."""
return len(self.stack)
class StackOverflowError(BaseException):
pass
if __name__ == '__main__':
stack = Stack()
for i in range(10):
stack.push(i)
print('Stack demonstration:\n')
print('Initial stack: ' + str(stack))
print('pop(): ' + str(stack.pop()))
print('After pop(), the stack is now: ' + str(stack))
print('peek(): ' + str(stack.peek()))
stack.push(100)
print('After push(100), the stack is now: ' + str(stack))
print('is_empty(): ' + str(stack.is_empty()))
print('size(): ' + str(stack.size()))

View File

@ -1,75 +0,0 @@
"""
A Trie/Prefix Tree is a kind of search tree used to provide quick lookup
of words/patterns in a set of words. A basic Trie however has O(n^2) space complexity
making it impractical in practice. It however provides O(max(search_string, length of longest word)) lookup
time making it an optimal approach when space is not an issue.
"""
class TrieNode:
def __init__(self):
self.nodes = dict() # Mapping from char to TrieNode
self.is_leaf = False
def insert_many(self, words: [str]): # noqa: E999 This syntax is Python 3 only
"""
Inserts a list of words into the Trie
:param words: list of string words
:return: None
"""
for word in words:
self.insert(word)
def insert(self, word: str): # noqa: E999 This syntax is Python 3 only
"""
Inserts a word into the Trie
:param word: word to be inserted
:return: None
"""
curr = self
for char in word:
if char not in curr.nodes:
curr.nodes[char] = TrieNode()
curr = curr.nodes[char]
curr.is_leaf = True
def find(self, word: str) -> bool: # noqa: E999 This syntax is Python 3 only
"""
Tries to find word in a Trie
:param word: word to look for
:return: Returns True if word is found, False otherwise
"""
curr = self
for char in word:
if char not in curr.nodes:
return False
curr = curr.nodes[char]
return curr.is_leaf
def print_words(node: TrieNode, word: str): # noqa: E999 This syntax is Python 3 only
"""
Prints all the words in a Trie
:param node: root node of Trie
:param word: Word variable should be empty at start
:return: None
"""
if node.is_leaf:
print(word, end=' ')
for key, value in node.nodes.items():
print_words(value, word + key)
def test():
words = ['banana', 'bananas', 'bandana', 'band', 'apple', 'all', 'beast']
root = TrieNode()
root.insert_many(words)
# print_words(root, '')
assert root.find('banana')
assert not root.find('bandanas')
assert not root.find('apps')
assert root.find('apple')
test()

View File

@ -1,78 +0,0 @@
from __future__ import absolute_import
from .union_find import UnionFind
import unittest
class TestUnionFind(unittest.TestCase):
def test_init_with_valid_size(self):
uf = UnionFind(5)
self.assertEqual(uf.size, 5)
def test_init_with_invalid_size(self):
with self.assertRaises(ValueError):
uf = UnionFind(0)
with self.assertRaises(ValueError):
uf = UnionFind(-5)
def test_union_with_valid_values(self):
uf = UnionFind(10)
for i in range(11):
for j in range(11):
uf.union(i, j)
def test_union_with_invalid_values(self):
uf = UnionFind(10)
with self.assertRaises(ValueError):
uf.union(-1, 1)
with self.assertRaises(ValueError):
uf.union(11, 1)
def test_same_set_with_valid_values(self):
uf = UnionFind(10)
for i in range(11):
for j in range(11):
if i == j:
self.assertTrue(uf.same_set(i, j))
else:
self.assertFalse(uf.same_set(i, j))
uf.union(1, 2)
self.assertTrue(uf.same_set(1, 2))
uf.union(3, 4)
self.assertTrue(uf.same_set(3, 4))
self.assertFalse(uf.same_set(1, 3))
self.assertFalse(uf.same_set(1, 4))
self.assertFalse(uf.same_set(2, 3))
self.assertFalse(uf.same_set(2, 4))
uf.union(1, 3)
self.assertTrue(uf.same_set(1, 3))
self.assertTrue(uf.same_set(1, 4))
self.assertTrue(uf.same_set(2, 3))
self.assertTrue(uf.same_set(2, 4))
uf.union(4, 10)
self.assertTrue(uf.same_set(1, 10))
self.assertTrue(uf.same_set(2, 10))
self.assertTrue(uf.same_set(3, 10))
self.assertTrue(uf.same_set(4, 10))
def test_same_set_with_invalid_values(self):
uf = UnionFind(10)
with self.assertRaises(ValueError):
uf.same_set(-1, 1)
with self.assertRaises(ValueError):
uf.same_set(11, 0)
if __name__ == '__main__':
unittest.main()

View File

@ -1,87 +0,0 @@
class UnionFind():
"""
https://en.wikipedia.org/wiki/Disjoint-set_data_structure
The union-find is a disjoint-set data structure
You can merge two sets and tell if one set belongs to
another one.
It's used on the Kruskal Algorithm
(https://en.wikipedia.org/wiki/Kruskal%27s_algorithm)
The elements are in range [0, size]
"""
def __init__(self, size):
if size <= 0:
raise ValueError("size should be greater than 0")
self.size = size
# The below plus 1 is because we are using elements
# in range [0, size]. It makes more sense.
# Every set begins with only itself
self.root = [i for i in range(size+1)]
# This is used for heuristic union by rank
self.weight = [0 for i in range(size+1)]
def union(self, u, v):
"""
Union of the sets u and v.
Complexity: log(n).
Amortized complexity: < 5 (it's very fast).
"""
self._validate_element_range(u, "u")
self._validate_element_range(v, "v")
if u == v:
return
# Using union by rank will guarantee the
# log(n) complexity
rootu = self._root(u)
rootv = self._root(v)
weight_u = self.weight[rootu]
weight_v = self.weight[rootv]
if weight_u >= weight_v:
self.root[rootv] = rootu
if weight_u == weight_v:
self.weight[rootu] += 1
else:
self.root[rootu] = rootv
def same_set(self, u, v):
"""
Return true if the elements u and v belongs to
the same set
"""
self._validate_element_range(u, "u")
self._validate_element_range(v, "v")
return self._root(u) == self._root(v)
def _root(self, u):
"""
Get the element set root.
This uses the heuristic path compression
See wikipedia article for more details.
"""
if u != self.root[u]:
self.root[u] = self._root(self.root[u])
return self.root[u]
def _validate_element_range(self, u, element_name):
"""
Raises ValueError if element is not in range
"""
if u < 0 or u > self.size:
msg = ("element {0} with value {1} "
"should be in range [0~{2}]")\
.format(element_name, u, self.size)
raise ValueError(msg)