diff --git a/data_structures/AVL/AVL.py b/data_structures/AVL/AVL.py index 0e3008dc1..9717f1b6e 100644 --- a/data_structures/AVL/AVL.py +++ b/data_structures/AVL/AVL.py @@ -7,40 +7,42 @@ class Node: def __init__(self, label): self.label = label - self.left = None - self.rigt = None - self.parent = None + self._parent = None + self._left = None + self._right = None self.height = 0 - def getLabel(self): - return self.label + @property + def right(self): + return self._right - def setLabel(self, label): - self.label = label + @right.setter + def right(self, node): + if node is not None: + node._parent = self + self._right = node - def getLeft(self): - return self.left + @property + def left(self): + return self._left - def setLeft(self, left): - self.left = left + @left.setter + def left(self, node): + if node is not None: + node._parent = self + self._left = node - def getRight(self): - return self.rigt + @property + def parent(self): + return self._parent - def setRight(self, right): - self.rigt = right - - def getParent(self): - return self.parent - - def setParent(self, parent): - self.parent = parent - - def setHeight(self, height): - self.height = height - - def getHeight(self, height): - return self.height + @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: @@ -51,8 +53,10 @@ class AVL: 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 @@ -64,63 +68,77 @@ class AVL: dad_node = curr_node - if node.getLabel() < curr_node.getLabel(): - curr_node = curr_node.getLeft() + if node.label < curr_node.label: + curr_node = curr_node.left else: - curr_node = curr_node.getRight() + curr_node = curr_node.right else: - if node.getLabel() < dad_node.getLabel(): - dad_node.setLeft(node) - dad_node.setHeight(dad_node.getHeight() + 1) - - if (dad_node.getRight().getHeight() - - dad_node.getLeft.getHeight() > 1): - self.rebalance(dad_node) - + node.height = dad_node.height + dad_node.height += 1 + if node.label < dad_node.label: + dad_node.left = node else: - dad_node.setRight(node) - dad_node.setHeight(dad_node.getHeight() + 1) - - if (dad_node.getRight().getHeight() - - dad_node.getLeft.getHeight() > 1): - self.rebalance(dad_node) + dad_node.right = node + self.rebalance(node) + self.size += 1 break def rebalance(self, node): - if (node.getRight().getHeight() - - node.getLeft.getHeight() > 1): - if (node.getRight().getHeight() > - node.getLeft.getHeight()): - pass - else: - pass - pass - elif (node.getRight().getHeight() - - node.getLeft.getHeight() > 2): - if (node.getRight().getHeight() > - node.getLeft.getHeight()): - pass - else: - pass - pass - pass + 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 = (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.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): - # TODO: is this pythonic enought? - aux = node.getLabel() - node = aux.getRight() - node.setHeight(node.getHeight() - 1) - node.setLeft(Node(aux)) - node.getLeft().setHeight(node.getHeight() + 1) - node.getRight().setHeight(node.getRight().getHeight() - 1) + 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.getLabel() - node = aux.getLeft() - node.setHeight(node.getHeight() - 1) - node.setRight(Node(aux)) - node.getLeft().setHeight(node.getHeight() + 1) - node.getLeft().setHeight(node.getLeft().getHeight() - 1) + 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()) @@ -129,3 +147,34 @@ class AVL: 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) diff --git a/data_structures/Binary Tree/binary_seach_tree.py b/data_structures/Binary Tree/binary_seach_tree.py index 0b1726534..9e468f775 100644 --- a/data_structures/Binary Tree/binary_seach_tree.py +++ b/data_structures/Binary Tree/binary_seach_tree.py @@ -68,7 +68,7 @@ class BinarySearchTree: return False def preShow(self, curr_node): - if curr_node is None: + if curr_node is not None: print(curr_node.getLabel(), end=" ") self.preShow(curr_node.getLeft()) diff --git a/data_structures/Stacks/Balanced_Parentheses.py b/data_structures/Stacks/Balanced_Parentheses.py deleted file mode 100644 index 6b7740380..000000000 --- a/data_structures/Stacks/Balanced_Parentheses.py +++ /dev/null @@ -1,27 +0,0 @@ -# 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 diff --git a/data_structures/Stacks/Infix_To_Postfix_Conversion.py b/data_structures/Stacks/Infix_To_Postfix_Conversion.py deleted file mode 100644 index e33926a3d..000000000 --- a/data_structures/Stacks/Infix_To_Postfix_Conversion.py +++ /dev/null @@ -1,48 +0,0 @@ -# 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 - diff --git a/data_structures/Stacks/Stack.py b/data_structures/Stacks/Stack.py deleted file mode 100644 index 41bbdc9d2..000000000 --- a/data_structures/Stacks/Stack.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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() diff --git a/data_structures/Stacks/balanced_parentheses.py b/data_structures/Stacks/balanced_parentheses.py new file mode 100644 index 000000000..1c9a84843 --- /dev/null +++ b/data_structures/Stacks/balanced_parentheses.py @@ -0,0 +1,21 @@ +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))) diff --git a/data_structures/Stacks/infix_to_postfix_conversion.py b/data_structures/Stacks/infix_to_postfix_conversion.py new file mode 100644 index 000000000..f0a8fd072 --- /dev/null +++ b/data_structures/Stacks/infix_to_postfix_conversion.py @@ -0,0 +1,62 @@ +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)) diff --git a/data_structures/Stacks/next.py b/data_structures/Stacks/next.py new file mode 100644 index 000000000..9765900c0 --- /dev/null +++ b/data_structures/Stacks/next.py @@ -0,0 +1,16 @@ +# 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) diff --git a/data_structures/Stacks/stack.py b/data_structures/Stacks/stack.py new file mode 100644 index 000000000..0b100abf3 --- /dev/null +++ b/data_structures/Stacks/stack.py @@ -0,0 +1,68 @@ +__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())) diff --git a/dynamic_programming/longest_increasing_subsequence_O(nlogn).py b/dynamic_programming/longest_increasing_subsequence_O(nlogn).py new file mode 100644 index 000000000..3ebb4a137 --- /dev/null +++ b/dynamic_programming/longest_increasing_subsequence_O(nlogn).py @@ -0,0 +1,40 @@ +############################# +# Author: Aravind Kashyap +# File: lis.py +# comments: This programme outputs the Longest Strictly Increasing Subsequence in O(NLogN) +# Where N is the Number of elements in the list +############################# +def CeilIndex(v,l,r,key): + while r-l > 1: + m = (l + r)/2 + if v[m] >= key: + r = m + else: + l = m + + return r + + +def LongestIncreasingSubsequenceLength(v): + if(len(v) == 0): + return 0 + + tail = [0]*len(v) + length = 1 + + tail[0] = v[0] + + for i in range(1,len(v)): + if v[i] < tail[0]: + tail[0] = v[i] + elif v[i] > tail[length-1]: + tail[length] = v[i] + length += 1 + else: + tail[CeilIndex(tail,-1,length-1,v[i])] = v[i] + + return length + + +v = [2, 5, 3, 7, 11, 8, 10, 13, 6] +print LongestIncreasingSubsequenceLength(v) diff --git a/other/LinearCongruentialGenerator.py b/other/LinearCongruentialGenerator.py new file mode 100644 index 000000000..b1eaa6119 --- /dev/null +++ b/other/LinearCongruentialGenerator.py @@ -0,0 +1,34 @@ +__author__ = "Tobias Carryer" + +from time import time + +class LinearCongruentialGenerator(object): + """ + A pseudorandom number generator. + """ + + def __init__( self, multiplier, increment, modulo, seed=int(time()) ): + """ + These parameters are saved and used when nextNumber() is called. + + modulo is the largest number that can be generated (exclusive). The most + efficent values are powers of 2. 2^32 is a common value. + """ + self.multiplier = multiplier + self.increment = increment + self.modulo = modulo + self.seed = seed + + def next_number( self ): + """ + The smallest number that can be generated is zero. + The largest number that can be generated is modulo-1. modulo is set in the constructor. + """ + self.seed = (self.multiplier * self.seed + self.increment) % self.modulo + return self.seed + +if __name__ == "__main__": + # Show the LCG in action. + lcg = LinearCongruentialGenerator(1664525, 1013904223, 2<<31) + while True : + print lcg.next_number() \ No newline at end of file diff --git a/other/binary_exponentiation.py b/other/binary_exponentiation.py new file mode 100644 index 000000000..1a30fb8fd --- /dev/null +++ b/other/binary_exponentiation.py @@ -0,0 +1,49 @@ +""" +* Binary Exponentiation for Powers +* This is a method to find a^b in a time complexity of O(log b) +* This is one of the most commonly used methods of finding powers. +* Also useful in cases where solution to (a^b)%c is required, +* where a,b,c can be numbers over the computers calculation limits. +* Done using iteration, can also be done using recursion + +* @author chinmoy159 +* @version 1.0 dated 10/08/2017 +""" + + +def b_expo(a, b): + res = 1 + while b > 0: + if b&1: + res *= a + + a *= a + b >>= 1 + + return res + + +def b_expo_mod(a, b, c): + res = 1 + while b > 0: + if b&1: + res = ((res%c) * (a%c)) % c + + a *= a + b >>= 1 + + return res + +""" +* Wondering how this method works ! +* It's pretty simple. +* Let's say you need to calculate a ^ b +* RULE 1 : a ^ b = (a*a) ^ (b/2) ---- example : 4 ^ 4 = (4*4) ^ (4/2) = 16 ^ 2 +* RULE 2 : IF b is ODD, then ---- a ^ b = a * (a ^ (b - 1)) :: where (b - 1) is even. +* Once b is even, repeat the process to get a ^ b +* Repeat the process till b = 1 OR b = 0, because a^1 = a AND a^0 = 1 +* +* As far as the modulo is concerned, +* the fact : (a*b) % c = ((a%c) * (b%c)) % c +* Now apply RULE 1 OR 2 whichever is required. +""" diff --git a/other/binary_exponentiation_2.py b/other/binary_exponentiation_2.py new file mode 100644 index 000000000..217a616c9 --- /dev/null +++ b/other/binary_exponentiation_2.py @@ -0,0 +1,50 @@ +""" +* Binary Exponentiation with Multiplication +* This is a method to find a*b in a time complexity of O(log b) +* This is one of the most commonly used methods of finding result of multiplication. +* Also useful in cases where solution to (a*b)%c is required, +* where a,b,c can be numbers over the computers calculation limits. +* Done using iteration, can also be done using recursion + +* @author chinmoy159 +* @version 1.0 dated 10/08/2017 +""" + + +def b_expo(a, b): + res = 0 + while b > 0: + if b&1: + res += a + + a += a + b >>= 1 + + return res + + +def b_expo_mod(a, b, c): + res = 0 + while b > 0: + if b&1: + res = ((res%c) + (a%c)) % c + + a += a + b >>= 1 + + return res + + +""" +* Wondering how this method works ! +* It's pretty simple. +* Let's say you need to calculate a ^ b +* RULE 1 : a * b = (a+a) * (b/2) ---- example : 4 * 4 = (4+4) * (4/2) = 8 * 2 +* RULE 2 : IF b is ODD, then ---- a * b = a + (a * (b - 1)) :: where (b - 1) is even. +* Once b is even, repeat the process to get a * b +* Repeat the process till b = 1 OR b = 0, because a*1 = a AND a*0 = 0 +* +* As far as the modulo is concerned, +* the fact : (a+b) % c = ((a%c) + (b%c)) % c +* Now apply RULE 1 OR 2, whichever is required. +""" diff --git a/searches/ternary_search.py b/searches/ternary_search.py new file mode 100644 index 000000000..3b1c75314 --- /dev/null +++ b/searches/ternary_search.py @@ -0,0 +1,112 @@ +''' +This is a type of divide and conquer algorithm which divides the search space into +3 parts and finds the target value based on the property of the array or list +(usually monotonic property). + +Time Complexity : O(log3 N) +Space Complexity : O(1) +''' + +import sys + +# This is the precision for this function which can be altered. +# It is recommended for users to keep this number greater than or equal to 10. +precision = 10 + +# This is the linear search that will occur after the search space has become smaller. +def lin_search(left, right, A, target): + for i in range(left, right+1): + if(A[i] == target): + return i + +# This is the iterative method of the ternary search algorithm. +def ite_ternary_search(A, target): + left = 0 + right = len(A) - 1; + while(True): + if(left