Skip to content

Added Stack implementation and some traditional Stack problems #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions data_structures/Graph/Graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 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
61 changes: 61 additions & 0 deletions data_structures/Graph/P01_BreadthFirstSearch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Author: OMKAR PATHAK

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
61 changes: 61 additions & 0 deletions data_structures/Graph/P02_DepthFirstSearch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Author: OMKAR PATHAK

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
27 changes: 27 additions & 0 deletions data_structures/Stacks/Balanced_Parentheses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Author: OMKAR PATHAK

import Stack

def parseParenthesis(string):
balanced = 1
index = 0
myStack = Stack.Stack(len(string))
while (index < len(string)) and (balanced == 1):
check = string[index]
if check == '(':
myStack.push(check)
else:
if myStack.isEmpty():
balanced = 0
else:
myStack.pop()
index += 1

if balanced == 1 and myStack.isEmpty():
return True
else:
return False

if __name__ == '__main__':
print(parseParenthesis('((()))')) # True
print(parseParenthesis('((())')) # False
48 changes: 48 additions & 0 deletions data_structures/Stacks/Infix_To_Postfix_Conversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Author: OMKAR PATHAK

import Stack

def isOperand(char):
return (ord(char) >= ord('a') and ord(char) <= ord('z')) or (ord(char) >= ord('A') and ord(char) <= ord('Z'))

def precedence(char):
if char == '+' or char == '-':
return 1
elif char == '*' or char == '/':
return 2
elif char == '^':
return 3
else:
return -1

def infixToPostfix(myExp, myStack):
postFix = []
for i in range(len(myExp)):
if (isOperand(myExp[i])):
postFix.append(myExp[i])
elif(myExp[i] == '('):
myStack.push(myExp[i])
elif(myExp[i] == ')'):
topOperator = myStack.pop()
while(not myStack.isEmpty() and topOperator != '('):
postFix.append(topOperator)
topOperator = myStack.pop()
else:
while (not myStack.isEmpty()) and (precedence(myExp[i]) <= precedence(myStack.peek())):
postFix.append(myStack.pop())
myStack.push(myExp[i])

while(not myStack.isEmpty()):
postFix.append(myStack.pop())
return ' '.join(postFix)

if __name__ == '__main__':
myExp = 'a+b*(c^d-e)^(f+g*h)-i'
myExp = [i for i in myExp]
print('Infix:',' '.join(myExp))
myStack = Stack.Stack(len(myExp))
print('Postfix:',infixToPostfix(myExp, myStack))

# OUTPUT:
# Infix: a + b * ( c ^ d - e ) ^ ( f + g * h ) - i
# Postfix: a b c d ^ e - f g h * + ^ * + i -
50 changes: 50 additions & 0 deletions data_structures/Stacks/Stack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Author: OMKAR PATHAK

class Stack(object):
def __init__(self, limit = 10):
self.stack = []
self.limit = limit

# for printing the stack contents
def __str__(self):
return ' '.join([str(i) for i in self.stack])

# for pushing an element on to the stack
def push(self, data):
if len(self.stack) >= self.limit:
print('Stack Overflow')
else:
self.stack.append(data)

# for popping the uppermost element
def pop(self):
if len(self.stack) <= 0:
return -1
else:
return self.stack.pop()

# for peeking the top-most element of the stack
def peek(self):
if len(self.stack) <= 0:
return -1
else:
return self.stack[len(self.stack) - 1]

# to check if stack is empty
def isEmpty(self):
return self.stack == []

# for checking the size of stack
def size(self):
return len(self.stack)

if __name__ == '__main__':
myStack = Stack()
for i in range(10):
myStack.push(i)
print(myStack)
myStack.pop() # popping the top element
print(myStack)
myStack.peek() # printing the top element
myStack.isEmpty()
myStack.size()
56 changes: 56 additions & 0 deletions sorts/bucket_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env python
# Author: OMKAR PATHAK
# This program will illustrate how to implement bucket sort algorithm

# Wikipedia says: Bucket sort, or bin sort, is a sorting algorithm that works by distributing the
# elements of an array into a number of buckets. Each bucket is then sorted individually, either using
# a different sorting algorithm, or by recursively applying the bucket sorting algorithm. It is a
# distribution sort, and is a cousin of radix sort in the most to least significant digit flavour.
# Bucket sort is a generalization of pigeonhole sort. Bucket sort can be implemented with comparisons
# and therefore can also be considered a comparison sort algorithm. The computational complexity estimates
# involve the number of buckets.

# Time Complexity of Solution:
# Best Case O(n); Average Case O(n); Worst Case O(n)

from P26_InsertionSort import insertionSort
import math

DEFAULT_BUCKET_SIZE = 5

def bucketSort(myList, bucketSize=DEFAULT_BUCKET_SIZE):
if(len(myList) == 0):
print('You don\'t have any elements in array!')

minValue = myList[0]
maxValue = myList[0]

# For finding minimum and maximum values
for i in range(0, len(myList)):
if myList[i] < minValue:
minValue = myList[i]
elif myList[i] > maxValue:
maxValue = myList[i]

# Initialize buckets
bucketCount = math.floor((maxValue - minValue) / bucketSize) + 1
buckets = []
for i in range(0, bucketCount):
buckets.append([])

# For putting values in buckets
for i in range(0, len(myList)):
buckets[math.floor((myList[i] - minValue) / bucketSize)].append(myList[i])

# Sort buckets and place back into input array
sortedArray = []
for i in range(0, len(buckets)):
insertionSort(buckets[i])
for j in range(0, len(buckets[i])):
sortedArray.append(buckets[i][j])

return sortedArray

if __name__ == '__main__':
sortedArray = bucketSort([12, 23, 4, 5, 3, 2, 12, 81, 56, 95])
print(sortedArray)