├── .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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
13 |
14 | **Case 1 :** f(m1) < f(m2)
15 |
16 | * **Case 1.1:** m1 < m2 < M, so m1 < M
17 |
18 | 
19 |
20 | * **Case 1.2:** m1 < M < m2, so m1 < M
21 |
22 | 
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 | 
29 |
30 | **Case 2:** f(m1) >= f(m2)
31 |
32 | * **Case 2.1:** m1 < M < m2, so M < m2
33 |
34 | 
35 |
36 | * **Case 2.2:** M < m1 < m2, so M < m2
37 |
38 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------