├── .gitignore ├── Data Structure ├── Heap │ ├── README.md │ ├── heap.py │ ├── max_heap_deletion_animation.gif │ └── test_heap.py ├── Linked List │ ├── README.md │ ├── linked-list.png │ ├── linked_list.py │ └── test.py ├── Queue │ ├── README.md │ ├── queue.py │ ├── queue.svg │ └── test.py └── Stack │ ├── README.md │ ├── stack.py │ ├── stack.svg │ └── test.py ├── Others └── Tower of Hanoi │ ├── README.md │ ├── images │ ├── tower_of_hanoi.gif │ ├── tower_of_hanoi.jpg │ └── tower_of_hanoi_two_disks.gif │ └── tower_of_hanoi.py ├── README.md ├── Searching ├── Binary Search │ ├── README.md │ ├── binary-and-linear-search-animations.gif │ ├── binary-search.png │ ├── search.py │ └── test.py ├── Linear Search │ ├── README.md │ ├── linear_search.gif │ ├── search.py │ └── test.py └── Ternary Search │ ├── README.md │ ├── images │ ├── ternarycase1.png │ ├── ternarycase11.png │ ├── ternarycase12.png │ ├── ternarycase2.png │ ├── ternarycase21.png │ ├── ternarycase22.png │ └── ternarysearch.png │ ├── search.py │ └── test.py └── Sorting └── Bubble Sort ├── README.md ├── bubble-sort.png └── bubble_sort.py /.gitignore: -------------------------------------------------------------------------------- 1 | **/__pycache__/* 2 | *.pyc 3 | -------------------------------------------------------------------------------- /Data Structure/Heap/README.md: -------------------------------------------------------------------------------- 1 | # Heap 2 | 3 | A **Heap** is a tree based data structure and it is a complete binary tree which satisfies the heap ordering property. The ordering can be one of two types: 4 | 5 | the **min-heap property:** the value of each node is greater than or equal to the value of its parent, with the minimum-value element at the root. 6 | 7 | the **max-heap property:** the value of each node is less than or equal to the value of its parent, with the maximum-value element at the root. 8 | 9 | ![heap](max_heap_deletion_animation.gif) 10 | 11 | **Basic Operations:** 12 | 13 | Following are the basic operations supported by a list. 14 | 15 | * **Insertion** − Adds an element at the max heap. 16 | 17 | * **Deletion** − Deletes an element at the beginning of the heap. 18 | 19 | * **Display** − Displays the complete heap. 20 | 21 | * **Max** − Get the max element from the heap. 22 | 23 | 24 | #### Complexity Analysis 25 | - Space - O(n) 26 | - Search - O(n) 27 | - Insertion - O(1) 28 | - Delete - O(log n) (Deletion from beginning) 29 | - Peek - O(1) 30 | ### More on this topic 31 | - https://en.wikipedia.org/wiki/Heap_(data_structure) 32 | - https://www.hackerearth.com/practice/data-structures/trees/heapspriority-queues/tutorial/ 33 | - https://www.geeksforgeeks.org/binary-heap/ 34 | -------------------------------------------------------------------------------- /Data Structure/Heap/heap.py: -------------------------------------------------------------------------------- 1 | """MaxHeap implementation using python""" 2 | 3 | 4 | class MaxHeap(object): 5 | 6 | def __init__(self, maxSize=None): 7 | self.heap = [] 8 | self.HEAP_SIZE = maxSize 9 | 10 | def _swap(self,i,j): 11 | self.heap[i], self.heap[j] = self.heap[j], self.heap[i] 12 | 13 | def _heapIsFull(self): 14 | return (self.HEAP_SIZE != None and len(self.heap) >= self.HEAP_SIZE) 15 | 16 | def insert(self, item): 17 | if self._heapIsFull(): 18 | "Heap is full..." 19 | else: 20 | self.heap.append(item) 21 | # adjust parent node item 22 | self._bubbleUp(len(self.heap)-1) 23 | 24 | def _bubbleUp(self, currentPosition): 25 | if currentPosition >= 1: # no need to do bubbleUp for 1 element 26 | index = currentPosition 27 | parentIndex = (index-1)//2 28 | 29 | if parentIndex >= 0 and self.heap[parentIndex] < self.heap[index]: 30 | self._swap(parentIndex, index) 31 | self._bubbleUp(parentIndex) 32 | 33 | def peek(self): 34 | return self.heap[0] if self.heap else None 35 | 36 | def pop(self): 37 | element = self.peek() 38 | if element: 39 | self._swap(0, len(self.heap) - 1) 40 | self.heap.pop() 41 | self._bubbleDown(0) 42 | return element 43 | 44 | def _bubbleDown(self, index): 45 | leftChildIndex = 2 * index + 1 46 | rightChildIndex = 2 * index + 2 47 | largest = index 48 | if len(self.heap) > leftChildIndex and self.heap[largest] < self.heap[leftChildIndex]: 49 | largest = leftChildIndex 50 | if len(self.heap) > rightChildIndex and self.heap[largest] < self.heap[rightChildIndex]: 51 | largest = rightChildIndex 52 | if largest!=index: 53 | self._swap(index, largest) 54 | self._bubbleDown(largest) 55 | -------------------------------------------------------------------------------- /Data Structure/Heap/max_heap_deletion_animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Data Structure/Heap/max_heap_deletion_animation.gif -------------------------------------------------------------------------------- /Data Structure/Heap/test_heap.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from heap import MaxHeap 3 | 4 | class MaxHeapTestCase(unittest.TestCase): 5 | """ Test for Heap.py""" 6 | def test(self): 7 | # test data 8 | ob = MaxHeap() 9 | ob.insert(10) 10 | self.assertEqual(ob.peek(), 10, msg="Max Element is not matched") 11 | ob.insert(5) 12 | self.assertEqual(ob.peek(), 10, msg="Max Element is not matched") 13 | ob.insert(6) 14 | self.assertEqual(ob.peek(), 10, msg="Max Element is not matched") 15 | ob.insert(3) 16 | self.assertEqual(ob.peek(), 10, msg="Max Element is not matched") 17 | ob.insert(8) 18 | self.assertEqual(ob.peek(), 10, msg="Max Element is not matched") 19 | ob.insert(20) 20 | self.assertEqual(ob.peek(), 20, msg="Max Element is not matched") 21 | ob.pop() 22 | self.assertEqual(ob.peek(), 10, msg="Max Element is not matched") 23 | ob.pop() 24 | self.assertEqual(ob.peek(), 8, msg="Max Element is not matched") 25 | ob.pop() 26 | self.assertEqual(ob.peek(), 6, msg="Max Element is not matched") 27 | ob.pop() 28 | self.assertEqual(ob.peek(), 5, msg="Max Element is not matched") 29 | ob.pop() 30 | self.assertEqual(ob.peek(), 3, msg="Max Element is not matched") 31 | ob.pop() 32 | self.assertEqual(ob.peek(), None, msg="Max Element is not matched") 33 | 34 | if __name__ == '__main__': 35 | unittest.main() 36 | -------------------------------------------------------------------------------- /Data Structure/Linked List/README.md: -------------------------------------------------------------------------------- 1 | # Linked List 2 | 3 | A **linked list** is a linear data structure where each element is a separate object. 4 | Each element (known as *node*) of a list is comprising of two items - the data and a reference to the next node. The last node has a reference to null. The entry point into a linked list is called the head of the list. It should be noted that head is not a separate node, but the reference to the first node. If the list is empty then the head is a null reference. 5 | 6 | ![Linked List](linked-list.png) 7 | 8 | A linked list is a dynamic data structure. The number of nodes in a list is not fixed and can grow and shrink on demand. Any application which has to deal with an unknown number of objects can use a linked list. 9 | 10 | 11 | **Basic Operations:** 12 | 13 | Following are the basic operations supported by a list. 14 | 15 | * **Insertion** − Adds an element at the beginning of the list. 16 | 17 | * **Deletion** − Deletes an element at the beginning of the list. 18 | 19 | * **Display** − Displays the complete list. 20 | 21 | * **Search** − Searches an element using the given key. 22 | 23 | * **Delete** − Deletes an element using the given key. 24 | 25 | 26 | #### Complexity Analysis 27 | - Search - O(n) 28 | - Insertion - O(1) 29 | - Deletion - O(1) (Deletion from beginning) 30 | - Deletion in middle - Searching O(n) and deleting O(1) 31 | - Space - O(n) 32 | 33 | #### Array vs Linked List 34 | http://www.geeksforgeeks.org/linked-list-vs-array/ 35 | 36 | ### More on this topic 37 | - https://en.wikipedia.org/wiki/Linked_list 38 | - https://www.hackerearth.com/practice/data-structures/linked-list/singly-linked-list/tutorial/ 39 | - https://www.tutorialspoint.com/data_structures_algorithms/linked_list_algorithms.htm 40 | -------------------------------------------------------------------------------- /Data Structure/Linked List/linked-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Data Structure/Linked List/linked-list.png -------------------------------------------------------------------------------- /Data Structure/Linked List/linked_list.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, item, next): 3 | self.item = item 4 | self.next = next 5 | 6 | class LinkedList: 7 | def __init__(self): 8 | self.head = None 9 | 10 | # Add an item to the head of the linked list 11 | def add(self, item): 12 | self.head = Node(item, self.head) 13 | 14 | # Delete the first item of the linked list 15 | def remove(self): 16 | if self.is_empty(): 17 | return None 18 | else: 19 | item = self.head.item 20 | self.head = self.head.next 21 | return item 22 | 23 | # Find and delete an given item 24 | def delete(self, item): 25 | if not self.is_empty() and self.head.item == item: 26 | self.remove() 27 | return True 28 | else: 29 | current = self.head 30 | prev = None 31 | while current != None: 32 | if current.item == item: 33 | prev.next = current.next 34 | return True 35 | prev = current 36 | current = current.next 37 | return False 38 | 39 | # Check if the linked list is empty 40 | def is_empty(self): 41 | return self.head == None 42 | 43 | # Search for an item in the list 44 | def find(self, item): 45 | node = self.head 46 | while node != None: 47 | if node.item == item: 48 | return True 49 | node = node.next 50 | 51 | return False 52 | 53 | # Print all the items in the list 54 | def show_all_items(self): 55 | print("Items in the list:") 56 | node = self.head 57 | while node != None: 58 | print(node.item) 59 | node = node.next 60 | -------------------------------------------------------------------------------- /Data Structure/Linked List/test.py: -------------------------------------------------------------------------------- 1 | from linked_list import LinkedList 2 | 3 | new_list = LinkedList() 4 | 5 | new_list.add(10) 6 | new_list.show_all_items() 7 | new_list.add(15) 8 | new_list.show_all_items() 9 | new_list.add(5) 10 | new_list.show_all_items() 11 | new_list.remove() 12 | new_list.show_all_items() 13 | new_list.add(2) 14 | new_list.show_all_items() 15 | print(new_list.find(50)) # Testing find with a invalid item 16 | print(new_list.find(10)) # Testing find with a valid item 17 | print(new_list.delete(15)) # Testing delete with a valid item 18 | print(new_list.delete(100)) # Testing delete with a invalid item 19 | -------------------------------------------------------------------------------- /Data Structure/Queue/README.md: -------------------------------------------------------------------------------- 1 | # Queue 2 | 3 | **Queue** is an abstract data structure, somewhat similar to Stacks. Unlike stacks, a queue is open at both its ends. One end is always used to insert data (enqueue) and the other is used to remove data (dequeue). Queue follows First-In-First-Out methodology, i.e., the data item stored first will be accessed first. 4 | 5 | A real-world example of queue can be a single-lane one-way road, where the vehicle enters first, exits first. More real-world examples can be seen as queues at the ticket windows and bus-stops. 6 | 7 | ![Queue](queue.svg) 8 | 9 | **Basic Operations:** 10 | 11 | Queue operations may involve initializing or defining the queue, utilizing it, and then completely erasing it from the memory.. Apart from these basic stuffs, a queue is used for the following two primary operations − 12 | 13 | - **enqueue()** − add (store) an item to the queue. 14 | - **dequeue()** − remove (access) an item from the queue. 15 | 16 | To use a queue efficiently, we need to check the status of queue as well. For the same purpose, the following functionality are available too − 17 | 18 | - **peek()** − get the first data element of the queue, without removing it. 19 | - **isEmpty()** − check if queue is empty. 20 | 21 | 22 | #### Complexity Analysis 23 | - Insertion - O(1) 24 | - Deletion - O(1) (If implemented with array, then deletion will take O(n) for shifting elements to rearrange the Queue) 25 | - Access - O(n) 26 | - Search - O(n) 27 | 28 | ### More on this topic 29 | - https://en.wikipedia.org/wiki/Queue_(abstract_data_type) 30 | - https://www.tutorialspoint.com/data_structures_algorithms/dsa_queue.htm 31 | - https://en.wikibooks.org/wiki/Data_Structures/Stacks_and_Queues 32 | -------------------------------------------------------------------------------- /Data Structure/Queue/queue.py: -------------------------------------------------------------------------------- 1 | """ Queue implementation using Python List """ 2 | 3 | class Queue(object): 4 | 5 | def __init__(self): 6 | self.items = [] 7 | 8 | def isEmpty(self): 9 | return (self.items == []) 10 | 11 | def enqueue(self, item): 12 | self.items.append(item) 13 | 14 | def peek(self): 15 | return self.items[0] 16 | 17 | def dequeue(self): 18 | if self.isEmpty(): 19 | return None 20 | return self.items.pop(0) #pops the first element from the list 21 | -------------------------------------------------------------------------------- /Data Structure/Queue/queue.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Data Structure/Queue/queue.svg -------------------------------------------------------------------------------- /Data Structure/Queue/test.py: -------------------------------------------------------------------------------- 1 | from queue import Queue 2 | 3 | queue = Queue() 4 | queue.enqueue(10) 5 | queue.enqueue(15) 6 | 7 | print(queue.isEmpty()) 8 | print(queue.peek()) 9 | print(queue.dequeue()) 10 | print(queue.dequeue()) 11 | print(queue.dequeue()) 12 | print(queue.isEmpty()) 13 | -------------------------------------------------------------------------------- /Data Structure/Stack/README.md: -------------------------------------------------------------------------------- 1 | # Stack 2 | 3 | A **stack** is an Abstract Data Type (ADT), commonly used in most programming languages. It is named stack as it behaves like a real-world stack, for example – a deck of cards or a pile of plates, etc. 4 | 5 | A real-world stack allows operations at one end only. For example, we can place or remove a card or plate from the top of the stack only. Likewise, Stack ADT allows all data operations at one end only. At any given time, we can only access the top element of a stack. 6 | 7 | This feature makes it LIFO data structure. LIFO stands for Last-in-first-out. Here, the element which is placed (inserted or added) last, is accessed first. In stack terminology, insertion operation is called PUSH operation and removal operation is called POP operation. 8 | 9 | 10 | Conceptually, a stack is simple: a data structure that allows adding and removing elements in a particular order. Every time an element is added, it goes on the top of the stack; the only element that can be removed is the element that was at the top of the stack. Consequently, a stack is said to have "first in last out" behavior (or "last in, first out"). The first item added to a stack will be the last item removed from a stack. 11 | 12 | ![Stack](stack.svg) 13 | 14 | **Basic Operations:** 15 | 16 | Stack operations may involve initializing the stack, using it and then de-initializing it. Apart from these basic stuffs, a stack is used for the following two primary operations − 17 | 18 | - **push()** − Pushing (storing) an element on the stack. 19 | - **pop()** − Removing (accessing) an element from the stack. 20 | 21 | To use a stack efficiently, we need to check the status of stack as well. For the same purpose, the following functionality are available too − 22 | 23 | - **peek()** − get the top data element of the stack, without removing it. 24 | - **isEmpty()** − check if stack is empty. 25 | 26 | 27 | #### Complexity Analysis 28 | - Insertion - O(1) 29 | - Deletion - O(1) 30 | - Access - O(n) 31 | - Search - O(n) 32 | 33 | 34 | ### More on this topic 35 | - https://en.wikipedia.org/wiki/Stack_(abstract_data_type) 36 | - https://www.tutorialspoint.com/data_structures_algorithms/stack_algorithm.htm 37 | - https://en.wikibooks.org/wiki/Data_Structures/Stacks_and_Queues 38 | -------------------------------------------------------------------------------- /Data Structure/Stack/stack.py: -------------------------------------------------------------------------------- 1 | """ Stack implementation using Python List """ 2 | 3 | class Stack(object): 4 | 5 | def __init__(self): 6 | self.items = [] 7 | 8 | def isEmpty(self): 9 | return (self.items == []) 10 | 11 | def push(self, item): 12 | self.items.append(item) 13 | 14 | def peek(self): 15 | return self.items[len(self.items) - 1] 16 | 17 | def pop(self): 18 | if self.isEmpty(): 19 | return None 20 | return self.items.pop() 21 | -------------------------------------------------------------------------------- /Data Structure/Stack/stack.svg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Data Structure/Stack/stack.svg -------------------------------------------------------------------------------- /Data Structure/Stack/test.py: -------------------------------------------------------------------------------- 1 | from stack import Stack 2 | 3 | stack = Stack() 4 | 5 | stack.push(10) 6 | stack.push(15) 7 | 8 | print(stack.isEmpty()) 9 | print(stack.peek()) 10 | print(stack.pop()) 11 | print(stack.pop()) 12 | print(stack.pop()) 13 | print(stack.isEmpty()) 14 | -------------------------------------------------------------------------------- /Others/Tower of Hanoi/README.md: -------------------------------------------------------------------------------- 1 | # Tower of Hanoi Problem 2 | 3 | **Tower of Hanoi** is a mathematical puzzle where we have three rods and n disks. The objective of the puzzle is to move the entire stack to another rod, obeying the following simple rules: 4 | 1. Only one disk can be moved at a time. 5 | 2. Each move consists of taking the upper disk from one of the stacks and placing it on top of another stack i.e. a disk can only be moved if it is the uppermost disk on a stack. 6 | 3. No disk can be placed on top of a smaller disk. 7 | 8 | ![Tower of Hanoi](./images/tower_of_hanoi.jpg) 9 | 10 | 11 | --- 12 | ### Solution 13 | 14 | To solve the problem, first we need to learn how to solve this problem with lesser amount of disks, say → 1 or 2. We mark three towers with name: **source**, **destination** and **aux** (only to help moving the disks). If we have only one disk, then it can easily be moved from source to destination peg. 15 | 16 | If we have 2 disks − 17 | 18 | - First, we move the smaller (top) disk to aux peg. 19 | - Then, we move the larger (bottom) disk to destination peg. 20 | - And finally, we move the smaller disk from aux to destination peg. 21 | 22 | ![Tower of Hanoi for two disks](./images/tower_of_hanoi_two_disks.gif) 23 | 24 | So now, we are in a position to design an algorithm for Tower of Hanoi with more than two disks. We divide the stack of disks in two parts. The largest disk (nth disk) is in one part and all other (n-1) disks are in the second part. 25 | 26 | Our ultimate aim is to move disk n from source to destination and then put all other (n - 1) disks onto it. We can imagine to apply the same in a recursive way for all given set of disks. 27 | 28 | The steps to follow are − 29 | 30 | - Step 1 − Move n-1 disks from **source** to **aux** 31 | - Step 2 − Move nth disk from **source** to **dest** 32 | - Step 3 − Move n-1 disks from **aux** to **dest** 33 | 34 | Image illustration for 3 disks : 35 | 36 | ![Tower of Hanoi solution for 3 disks](http://mathforum.org/dr.math/faq/faq.disk3.gif) 37 | 38 | With 3 disks, the puzzle can be solved in 7 moves. The minimal number of moves required to solve a Tower of Hanoi puzzle is 2n − 1, where n is the number of disks. 39 | 40 | An animated visualization for 3 disks: 41 | 42 | ![Tower of Hanoi GIF](./images/tower_of_hanoi.gif) 43 | 44 | ### More on this topic 45 | - [Tower of Hanoi - Wikipedia](https://en.wikipedia.org/wiki/Tower_of_Hanoi) 46 | - [Tower of Hanoi - khanacademy](https://www.khanacademy.org/computing/computer-science/algorithms/towers-of-hanoi/a/towers-of-hanoi) 47 | - [Tower of Hanoi - Tutorialspoint](https://www.tutorialspoint.com/data_structures_algorithms/tower_of_hanoi.htm) 48 | - [Tower of Hanoi - GeeksforGeeks](http://www.geeksforgeeks.org/c-program-for-tower-of-hanoi/) 49 | -------------------------------------------------------------------------------- /Others/Tower of Hanoi/images/tower_of_hanoi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Others/Tower of Hanoi/images/tower_of_hanoi.gif -------------------------------------------------------------------------------- /Others/Tower of Hanoi/images/tower_of_hanoi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Others/Tower of Hanoi/images/tower_of_hanoi.jpg -------------------------------------------------------------------------------- /Others/Tower of Hanoi/images/tower_of_hanoi_two_disks.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Others/Tower of Hanoi/images/tower_of_hanoi_two_disks.gif -------------------------------------------------------------------------------- /Others/Tower of Hanoi/tower_of_hanoi.py: -------------------------------------------------------------------------------- 1 | # Tower of Hanoi implementation in Python 2 | 3 | # This function will recursively show all the moves of the solution 4 | def TowerOfHanoi(count, source, aux, destination): 5 | # When there is only single disk move it from 'source' to 'destination' 6 | if count == 1: 7 | print("Move disk 1 from: {source} to: {destination}".format(source=source,destination=destination)) 8 | return 9 | 10 | # Move 'n-1' disks from 'source' to 'aux' 11 | TowerOfHanoi(count - 1, source, destination, aux) 12 | 13 | # Move n-th disk from 'source' to 'detination' 14 | print("Move disk {disk} from: {source} to: {destination}".format(disk=count,source=source,destination=destination)) 15 | 16 | # Move (n-1) disks from 'aux' to 'destination' 17 | TowerOfHanoi(count - 1, aux, source, destination); 18 | 19 | 20 | 21 | # Testing Tower of Hanoi code 22 | TowerOfHanoi(3, 'A', 'B', 'C'); 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Learn Data Structure and Algorithms by Python 2 | 3 | > You need to have basic understanding of the Python programming language to proceed with the codes from this repository. 4 | > Python 3 is used for the implementation of the data structures and Algorithms 5 | 6 | ## Table of Contents 7 | 8 | * [Introduction to Python](#introduction) 9 | * [Data Structure](./Data%20Structure/) 10 | * [Linked List](./Data%20Structure/Linked%20List/) 11 | * [Stack](./Data%20Structure/Stack/) 12 | * [Queue](./Data%20Structure/Queue/) 13 | * Binary Search Tree (BST) 14 | * [Heap](./Data%20Structure/Heap/) 15 | * Hash Table 16 | * Disjoint Set Union (Union Find) 17 | * Trie 18 | * Suffix Array 19 | * Segment Tree 20 | * Binary Indexed Tree (BIT) 21 | * Heavy Light Decomposition 22 | 23 | - [Searching](./Searching/) 24 | * [Linear Search](./Searching/Linear%20Search/) 25 | * [Binary Search](./Searching/Binary%20Search/) 26 | * [Ternary Search](./Searching/Ternary%20Search/) 27 | 28 | * [Sorting](./Sorting/) 29 | * Selection Sort 30 | * [Bubble Sort](./Sorting/Bubble%20Sort/) 31 | * Insertion Sort 32 | * Merge Sort 33 | * Quick Sort 34 | * Bucket Sort 35 | * Counting Sort 36 | * Heap Sort 37 | * Radix Sort 38 | 39 | - Graph Algorithms 40 | 41 | * Graph Representation 42 | * Breadth First Search (BFS) 43 | * Depth First Search (DFS) 44 | * Topological Sort 45 | * Strongly Connected Components (SCC) 46 | * Minimum Spanning Tree (MST) 47 | * All Pairs Shortest Path (Floyd Warshall's Algorithm) 48 | * Single Source Shortest Path Algorithm 49 | * Djkastra's Algorithm 50 | * Bellman Ford Algorithm 51 | * Directed Acyclic Graph 52 | * Bipartite Matching 53 | * Articulation Point, Bridge 54 | * Euler Tour/Path 55 | * Hamiltonian Cycle 56 | * Stable Marriage Problem 57 | * Chinese Postman Problem 58 | * 2-satisfiability 59 | * Flow Algorithms 60 | * Maximum Flow 61 | * Minimum Cut 62 | * Min-Cost Max Flow 63 | * Maximum Bipartite Matching 64 | * Vertex Cover 65 | 66 | - Dynamic Programming 67 | * Rod Cutting 68 | * Maximum Sum (1D, 2D) 69 | * Coin Change 70 | * Longest Common Subsequence 71 | * Longest Increasing Subsequence 72 | * Matrix Multiplication 73 | * Edit Distance (Levenshtein distance) 74 | * 0/1 Knapsack 75 | * Travelling Salesman Problem 76 | * Optimal Binary Search Tree 77 | 78 | * Greedy Algorithms 79 | * Activity Selection/Task Scheduling 80 | * Huffman Coding 81 | * Knapsack Problem (Fractional Knapsack) 82 | 83 | - String Algorithms 84 | * Rabin-Karp Algorithm 85 | * Knuth-Morris-Pratt Algorithm 86 | * Z Algorithm 87 | * Aho-Korasick Algorithm 88 | * Manachers Algorithm 89 | * Boyr-Moore Algorithm 90 | 91 | * Number Theory 92 | * Greatest Common Divisor (GCD) 93 | * Longest Common Multiplier (LCM) 94 | * Euler Totient (Phi) 95 | * Primality Testing 96 | * Prime finding(Sieve of Eratosthenes) 97 | * Prime factorization 98 | * Factorial 99 | * Fibonacci 100 | * Counting, Permutation, combination 101 | * Exponentiation 102 | * Big Mod 103 | * Euclid, Extended euclid 104 | * Josephus Problem 105 | * Farey Sequence 106 | * Catalan numbers 107 | * Burnside's lemma/circular permutation 108 | * Modular inverse 109 | * Probability 110 | * Chinese Remainder Theorem 111 | * Gaussian Elimination method 112 | * Dilworth's Theorem 113 | * Matrix Exponentiation 114 | 115 | - Computational Geometry 116 | * Pick's Theorem 117 | * Convex hull 118 | * Line Intersection 119 | * Point in a polygon 120 | * Area of a polygon 121 | * Line Sweeping 122 | * Polygon intersection 123 | * Closest Pair 124 | 125 | * Game Theory 126 | 127 | * Take Away Game 128 | * Nim's Game 129 | * Sprague-grundy Number 130 | 131 | * Others 132 | * BackTracking 133 | * N-Queen's Problem 134 | * [Tower of Hanoi Problem](./Others/Tower%20of%20Hanoi/) 135 | 136 | --- 137 | 138 | ## Introduction 139 | 140 | ### Big-O Notation and Time Complexity Analysis 141 | 142 | [Algorithms in plain English: time complexity and Big-O notation](https://medium.freecodecamp.com/time-is-complex-but-priceless-f0abd015063c) 143 | 144 | [Big-O Cheat Sheet Link](http://bigocheatsheet.com/) 145 | 146 | ### How to Use 147 | 148 | Install Python 3.x in your machine [from here](https://www.python.org/downloads/release/python-343/) (if it's already not installed) and add it to your environment path so that it is accessible in terminal commands. 149 | 150 | Then you can run a Python file like this: 151 | 152 | ```python 153 | python file.py 154 | ``` 155 | 156 | or 157 | 158 | ```python 159 | python3 file.py 160 | ``` 161 | 162 | ### Useful Links: 163 | 164 | * [Algorithms, 4th Edition (book by: Robert Sedgewick and Kevin Wayne)](http://algs4.cs.princeton.edu/home/) 165 | * [Khan Academy tutorial on Algorithms](https://www.khanacademy.org/computing/computer-science/algorithms) 166 | * [Topcoder Tutorials](https://www.topcoder.com/community/data-science/data-science-tutorials/) 167 | * [GeeksforGeeks](http://www.geeksforgeeks.org/) 168 | * [hackerearth Tutorial](https://www.hackerearth.com/practice/) 169 | -------------------------------------------------------------------------------- /Searching/Binary Search/README.md: -------------------------------------------------------------------------------- 1 | # Binary Search 2 | 3 | **Binary search** is an efficient algorithm for finding an item from an ordered list of items. It works by repeatedly dividing in half the portion of the list that could contain the item, until you've narrowed down the possible locations to just one. 4 | 5 | ![Binary Search](binary-search.png) 6 | 7 | For a binary search to work, it is mandatory for the target array to be sorted. 8 | 9 | In the sequential search, when we compare against the first item, there are at most *(n−1)* more items to look through if the first item is not what we are looking for. Instead of searching the list in sequence, a binary search will start by examining the middle item. If that item is the one we are searching for, we are done. If it is not the correct item, we can use the ordered nature of the list to eliminate half of the remaining items. If the item we are searching for is greater than the middle item, we know that the entire lower half of the list as well as the middle item can be eliminated from further consideration. The item, if it is in the list, must be in the upper half. 10 | 11 | We can then repeat the process with the upper half. Start at the middle item and compare it against what we are looking for. Again, we either find it or split the list in half, therefore eliminating another large part of our possible search space. 12 | 13 | 14 | #### Linear Search vs. Binary Search 15 | A linear search looks down a list, one item at a time, without jumping. In complexity terms this is an O(n) search - the time taken to search the list gets bigger at the same rate as the list does. 16 | 17 | A binary search is when you start with the middle of a sorted list, and see whether that's greater than or less than the value you're looking for, which determines whether the value is in the first or second half of the list. Jump to the half way through the sub-list, and compare again etc. In complexity terms this is an O(log n) search - the number of search operations grows more slowly than the list does, because you're halving the "search space" with each operation. 18 | 19 | ![Linear Vs. Binary Search](binary-and-linear-search-animations.gif) 20 | 21 | #### Complexity Analysis 22 | - Worst Case - O(logn) 23 | - Best Case - O(1) 24 | - Average Case - O(logn) 25 | 26 | 27 | ### More on this topic 28 | - https://en.wikipedia.org/wiki/Binary_search_algorithm 29 | - https://www.khanacademy.org/computing/computer-science/algorithms/binary-search/a/binary-search 30 | - https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/ 31 | - https://www.tutorialspoint.com/data_structures_algorithms/binary_search_algorithm.htm 32 | -------------------------------------------------------------------------------- /Searching/Binary Search/binary-and-linear-search-animations.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Binary Search/binary-and-linear-search-animations.gif -------------------------------------------------------------------------------- /Searching/Binary Search/binary-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Binary Search/binary-search.png -------------------------------------------------------------------------------- /Searching/Binary Search/search.py: -------------------------------------------------------------------------------- 1 | def binarySearch(item, item_list): 2 | low, high = 0, len(item_list) - 1 3 | 4 | found = False 5 | 6 | while low <= high and not found: 7 | mid = (low + high) // 2 8 | 9 | if item_list[mid] == item: 10 | found = True # You can catch the found value or it's position here too 11 | else: 12 | if item < item_list[mid]: 13 | high = mid - 1 14 | else: 15 | low = mid + 1 16 | 17 | return found 18 | -------------------------------------------------------------------------------- /Searching/Binary Search/test.py: -------------------------------------------------------------------------------- 1 | from search import binarySearch 2 | 3 | # This list must be sorted. If it is not given as sorted, sort it first, then call the binarySearch method 4 | testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42] 5 | print(binarySearch(3, testlist)) 6 | print(binarySearch(13, testlist)) 7 | -------------------------------------------------------------------------------- /Searching/Linear Search/README.md: -------------------------------------------------------------------------------- 1 | # Linear Search 2 | 3 | **Linear search** is a very simple search algorithm. In this type of search, a sequential search is made over all items one by one. Every item is checked and if a match is found then that particular item is returned, otherwise the search continues till the end of the data collection. 4 | 5 | ![Linear Search](linear_search.gif) 6 | 7 | 8 | #### Python Implementation 9 | 10 | Though it is very easy in python to check for [an item's existence in a list](http://stackoverflow.com/a/7571665/4230330) by: 11 | 12 | `item in list` 13 | 14 | and [finding an item's index](http://stackoverflow.com/a/176921/4230330) by: 15 | 16 | `list.index(item)` 17 | 18 | but sometimes you might need to do some customization on the searching algorithm. Like- *'finding the last occurrence of the item in the list'* etc. This linear search implementation will help you to do that. 19 | 20 | #### Complexity Analysis 21 | - Worst Case - O(n) 22 | - Best Case - O(1) 23 | - Average Case - O(n) 24 | 25 | 26 | ### More on this topic 27 | - https://en.wikipedia.org/wiki/Linear_search 28 | - https://www.tutorialspoint.com/data_structures_algorithms/linear_search_algorithm.htm 29 | -------------------------------------------------------------------------------- /Searching/Linear Search/linear_search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Linear Search/linear_search.gif -------------------------------------------------------------------------------- /Searching/Linear Search/search.py: -------------------------------------------------------------------------------- 1 | def linearSearch(item, item_list): 2 | for index, val in enumerate(item_list): 3 | if val == item: 4 | return True #You can return the index of the found element by 'return index' 5 | return False 6 | -------------------------------------------------------------------------------- /Searching/Linear Search/test.py: -------------------------------------------------------------------------------- 1 | from search import linearSearch 2 | 3 | hayStack = ['book','pencil','pen','note book','sharpener','rubber'] 4 | needle = input('What do you want to find: ') 5 | 6 | if linearSearch(needle, hayStack): 7 | print('Found') 8 | else: 9 | print('Not Found') 10 | -------------------------------------------------------------------------------- /Searching/Ternary Search/README.md: -------------------------------------------------------------------------------- 1 | # Ternary Search 2 | 3 | **Ternary search** algorithm is a technique in computer science for finding the minimum or maximum of a [unimodal](https://en.wikipedia.org/wiki/Unimodality) function. A ternary search determines either that the minimum or maximum cannot be in the first third of the domain or that it cannot be in the last third of the domain, then repeats on the remaining two-thirds. 4 | Unimodal functions are functions that, have a single highest/lowest value. 5 | 6 | Suppose we have a function f(x) with only one max point between A and B. We want to find the point (M, f(M)) where f(M) is the maximum between A and B. 7 | 8 | We split the range from A to B into three intervals. At every iteration of our algorithm, we can narrow down the range by 1/3 and we have a new interval. At every step, we can remove one of the intervals based on the following: 9 | 10 | Let m1 by 1/3 of the way from A and B and let m2 be 2/3 of the way from B. 11 | 12 | ![Ternary Search](./images/ternarysearch.png) 13 | 14 | **Case 1 :** f(m1) < f(m2) 15 | 16 | * **Case 1.1:** m1 < m2 < M, so m1 < M 17 | 18 | ![Ternary Search 1.1](./images/ternarycase11.png) 19 | 20 | * **Case 1.2:** m1 < M < m2, so m1 < M 21 | 22 | ![Ternary Search 1.2](./images/ternarycase12.png) 23 | 24 | * **Case 1.3:** M < m1 < m2 is not possible. 25 | 26 | Thus if f(m1) < f(m2), then m1 < M, so we only need to search from m1 to B. 27 | 28 | ![Ternary Search 1](./images/ternarycase1.png) 29 | 30 | **Case 2:** f(m1) >= f(m2) 31 | 32 | * **Case 2.1:** m1 < M < m2, so M < m2 33 | 34 | ![Ternary Search 2.1](./images/ternarycase21.png) 35 | 36 | * **Case 2.2:** M < m1 < m2, so M < m2 37 | 38 | ![Ternary Search 2.2](./images/ternarycase22.png) 39 | 40 | * **Case 2.3:** m1 < m2 < M is not possible 41 | 42 | Thus, if f(m1) >= f(m2), then M < m2, so we only need to search from A to m2. 43 | 44 | ![Ternary Search 2](./images/ternarycase2.png) 45 | 46 | Therefore, based on the values of f(m1) and f(m2), we can always remove a third of the range. We can keep repeating this until the range is within a very small threshold/absolute Precision such as 0.0001. 47 | 48 | #### Binary Search vs. Ternary Search 49 | Binary search looks a zero or a specific value in case of monotonic(Non-increasing or non-decreasing) input; ternary search is used to locate an extremum for unimodal(Having a single extremum) inputs. 50 | 51 | 52 | #### Complexity Analysis 53 | - Average Case - O(logn) 54 | 55 | 56 | ### More on this topic 57 | - https://en.wikipedia.org/wiki/Ternary_search 58 | - https://www.hackerearth.com/practice/algorithms/searching/ternary-search/tutorial/ 59 | - http://matteolandi.blogspot.com/2012/11/ternary-search.html 60 | - http://www.thecshandbook.com/Ternary_Search 61 | -------------------------------------------------------------------------------- /Searching/Ternary Search/images/ternarycase1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Ternary Search/images/ternarycase1.png -------------------------------------------------------------------------------- /Searching/Ternary Search/images/ternarycase11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Ternary Search/images/ternarycase11.png -------------------------------------------------------------------------------- /Searching/Ternary Search/images/ternarycase12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Ternary Search/images/ternarycase12.png -------------------------------------------------------------------------------- /Searching/Ternary Search/images/ternarycase2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Ternary Search/images/ternarycase2.png -------------------------------------------------------------------------------- /Searching/Ternary Search/images/ternarycase21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Ternary Search/images/ternarycase21.png -------------------------------------------------------------------------------- /Searching/Ternary Search/images/ternarycase22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Ternary Search/images/ternarycase22.png -------------------------------------------------------------------------------- /Searching/Ternary Search/images/ternarysearch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Searching/Ternary Search/images/ternarysearch.png -------------------------------------------------------------------------------- /Searching/Ternary Search/search.py: -------------------------------------------------------------------------------- 1 | def simpleTernarySearch(item_list): 2 | """ 3 | Find the maximum value in a strictly increasing and then strictly decreasing list 4 | N.B.- This method won't work if the list does not represent an unimodal function 5 | e.g. if the maximum value present in the first or last index of the list 6 | """ 7 | left, right = 0, len(item_list) - 1 8 | 9 | found = False 10 | precision = 3 11 | 12 | while left <= right: 13 | if (right - left) < precision: #Here 3 is the smallest range to divide the left and right value 14 | found = True 15 | break 16 | 17 | leftThird = left + (right - left) // 3 18 | rightThird = right - (right - left) // 3 19 | 20 | #To find the minimum in an unimodal function change the following comparison to > 21 | if item_list[leftThird] < item_list[rightThird]: 22 | left = leftThird 23 | else: 24 | right = rightThird 25 | 26 | return (left + right) // 2 27 | 28 | 29 | def ternarySearch(func, left, right, absolutePrecision): 30 | """ 31 | Find maximum of unimodal function func() within [left, right] 32 | To find the minimum, reverse the if/else statement or reverse the comparison. 33 | """ 34 | while True: 35 | #left and right are the current bounds; the maximum is between them 36 | if abs(right - left) < absolutePrecision: 37 | return (left + right)/2 38 | 39 | leftThird = left + (right - left)/3 40 | rightThird = right - (right - left)/3 41 | 42 | if func(leftThird) < func(rightThird): 43 | left = leftThird 44 | else: 45 | right = rightThird 46 | 47 | 48 | def ternarySearchRecursive(func, left, right, absolutePrecision): 49 | """ 50 | left and right are the current bounds. the maximum is between them 51 | """ 52 | if abs(right - left) < absolutePrecision: 53 | return (left + right)/2 54 | 55 | leftThird = (2*left + right)/3 56 | rightThird = (left + 2*right)/3 57 | 58 | if func(leftThird) < func(rightThird): 59 | return ternarySearch(func, leftThird, right, absolutePrecision) 60 | else: 61 | return ternarySearch(func, left, rightThird, absolutePrecision) 62 | -------------------------------------------------------------------------------- /Searching/Ternary Search/test.py: -------------------------------------------------------------------------------- 1 | from search import * 2 | 3 | def main(): 4 | # This list must be sorted. If it is not given as sorted, sort it first, then call the binarySearch method 5 | testlist = [1, 50, 20, 10, 2, 1] 6 | index = simpleTernarySearch(testlist) 7 | print(testlist[index]) 8 | 9 | result = ternarySearch(func, 0, 1, 1e-6) 10 | print(func(result)) 11 | 12 | result = ternarySearchRecursive(func, 0, 1, 1e-6) 13 | print(func(result)) 14 | 15 | 16 | def func(x): 17 | return -1*1*x*x + 2*x +3 # (-a*x*x + b*x + c) is an unimodal function, here a = 1, b = 2, c = 3 18 | 19 | if __name__ == '__main__': 20 | main() 21 | -------------------------------------------------------------------------------- /Sorting/Bubble Sort/README.md: -------------------------------------------------------------------------------- 1 | # Bubble Sort 2 | 3 | **Bubble Sort** is an algorithm which is used to sort **N** elements that are given in a memory for eg: an Array with N number of elements. Bubble Sort compares all the element one by one and sort them based on their values. 4 | 5 | It is called Bubble sort, because *with each iteration the smaller element in the list bubbles up towards the first place*, just like a water bubble rises up to the water surface. 6 | 7 | Sorting takes place by stepping through all the data items one-by-one in pairs and comparing adjacent data items and swapping each pair that is out of order. 8 | ![bubble sort demonstration](bubble-sort.png) 9 | -------------------------------------------------------------------------------- /Sorting/Bubble Sort/bubble-sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Algorithm-archive/Learn-Data_Structure-Algorithm-by-Python/1c0ce915906640e57c91da7cbb270cb6f95d11f1/Sorting/Bubble Sort/bubble-sort.png -------------------------------------------------------------------------------- /Sorting/Bubble Sort/bubble_sort.py: -------------------------------------------------------------------------------- 1 | # Python program for implementation of Bubble Sort 2 | 3 | def bubbleSort(arr): 4 | n = len(arr) 5 | 6 | # Traverse through all array elements 7 | for i in range(n): 8 | 9 | # Last i elements are already in place, so the inner loops will run until it reaches the last i elements 10 | for j in range(0, n-i-1): 11 | 12 | # traverse the array from 0 to n-i-1 13 | # Swap if the element found is greater than the next element 14 | if arr[j] > arr[j+1] : 15 | arr[j], arr[j+1] = arr[j+1], arr[j] 16 | 17 | 18 | def modifiedBubbleSort(arr): 19 | n = len(arr) 20 | 21 | # Traverse through all array elements 22 | for i in range(n): 23 | # Taking a flag variable 24 | flag = 0 25 | # Last i elements are already in place 26 | for j in range(0, n-i-1): 27 | 28 | # traverse the array from 0 to n-i-1 29 | # Swap if the element found is greater 30 | # than the next element 31 | if arr[j] > arr[j+1] : 32 | arr[j], arr[j+1] = arr[j+1], arr[j] 33 | # Setting the flag, if swapping occurs 34 | flag = 1 35 | 36 | # If not swapped, that means the list has already sorted 37 | if flag == 0: 38 | break 39 | 40 | # Main code 41 | arr = [64, 34, 25, 12, 22, 11, 90] 42 | 43 | bubbleSort(arr) 44 | # modifiedBubbleSort(arr) 45 | 46 | print ("Sorted array is:") 47 | for i in range(len(arr)): 48 | print ("%d" %arr[i]), 49 | --------------------------------------------------------------------------------