Repository: ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python
Branch: master
Commit: 7ecd98a4537a
Files: 128
Total size: 157.9 KB
Directory structure:
gitextract_x7v3a_w5/
├── .gitignore
├── LICENSE
├── README.md
├── analysis/
│ ├── anagrams-linear-solution.py
│ ├── anagrams-loglinear-solution.py
│ ├── anagrams-quadratic-solution.py
│ ├── time-iterative-approach.py
│ └── time-noniterative-approach.py
├── deque/
│ ├── circular-deque.py
│ ├── deque.py
│ └── deque_linked_list_impl.py
├── graphs/
│ ├── bellman-ford/
│ │ └── graph.py
│ ├── bellman-ford-negative-weight-cycle/
│ │ └── graph.py
│ ├── breadth-first-search/
│ │ ├── graph.py
│ │ ├── main.py
│ │ └── queue.py
│ ├── cycle-detection/
│ │ ├── Cycle.md
│ │ ├── cycle-directed-graph/
│ │ │ ├── graph.py
│ │ │ └── main.py
│ │ └── cycle-undirected-graph/
│ │ ├── graph.py
│ │ └── main.py
│ ├── depth-first-search/
│ │ ├── depth-first-search/
│ │ │ ├── graph.py
│ │ │ ├── main.py
│ │ │ └── stack.py
│ │ └── depth-first-search-recursive/
│ │ ├── graph.py
│ │ └── main.py
│ ├── dijkstra/
│ │ ├── adjacency-list-impl/
│ │ │ ├── main.py
│ │ │ └── vertex.py
│ │ ├── matrix-impl/
│ │ │ ├── graph.py
│ │ │ ├── main.py
│ │ │ └── vertex.py
│ │ └── priority-queue-impl-adjacency-map/
│ │ ├── graph.py
│ │ ├── main.py
│ │ ├── priorityqueue.py
│ │ └── vertex.py
│ ├── is-graph-bipartite/
│ │ ├── graph.py
│ │ ├── main.py
│ │ └── queue.py
│ ├── kosarajus-algorithm/
│ │ ├── graph.py
│ │ ├── main.py
│ │ └── stack.py
│ ├── minimum-spanning-tree/
│ │ ├── breadth-first-search/
│ │ │ ├── graph.py
│ │ │ ├── main.py
│ │ │ └── queue.py
│ │ ├── kruskals-algorithm/
│ │ │ ├── graph.py
│ │ │ └── main.py
│ │ └── prims-algorithm/
│ │ ├── graph.py
│ │ ├── main.py
│ │ ├── priorityqueue.py
│ │ └── vertex.py
│ ├── topological-sorting/
│ │ ├── graph.py
│ │ └── main.py
│ └── union-find/
│ ├── number-of-connected-components/
│ │ └── graph.py
│ └── union-find-path-compression/
│ ├── graph.py
│ ├── main.py
│ └── vertex.py
├── hash-table/
│ ├── chaining.py
│ └── linear-probing.py
├── linked-lists/
│ ├── circular-doubly-linked-list/
│ │ ├── list.py
│ │ └── node.py
│ ├── circular-singly-linked-list/
│ │ ├── list.py
│ │ └── node.py
│ ├── doubly-linked-list/
│ │ ├── list.py
│ │ └── node.py
│ └── singly-linked-list/
│ ├── list.py
│ └── node.py
├── queue/
│ ├── circular-queue-fixed-size-array-impl.py
│ ├── queue-array-impl.py
│ ├── queue-fixed-size-array-impl.py
│ ├── queue-linked-list-impl.py
│ └── queue-two-stacks-impl.py
├── recursion/
│ ├── convert-number-iterative.py
│ ├── convert-number.py
│ ├── factorial.py
│ ├── fibonacci-iterative.py
│ ├── fibonacci-memoization.py
│ ├── fibonacci-recursive-worst-solution.py
│ ├── fibonacci-recursive.py
│ ├── fibonacci-sum-iterative.py
│ ├── fibonacci-sum-recursive.py
│ ├── maze.py
│ ├── palindrome.py
│ ├── reverse-linked-list-iterative-stack.py
│ ├── reverse-linked-list-iterative.py
│ ├── reverse-linked-list.py
│ ├── reverse-list.py
│ ├── reverse-string.py
│ ├── stack.py
│ ├── sum-numbers-binary-recursion.py
│ ├── sum-numbers-pointer.py
│ ├── sum-numbers-slicing.py
│ └── towers-of-hanoi.py
├── searching/
│ ├── binary-search-iterative.py
│ ├── binary-search-recursive-pointers.py
│ ├── binary-search-recursive.py
│ ├── sequential-search-ordered-list.py
│ └── sequential-search-unordered-list.py
├── sorting/
│ ├── bubble-sort.py
│ ├── insertion-sort.py
│ ├── merge-sort.py
│ ├── quicksort-return-new-array.py
│ ├── quicksort.py
│ ├── selection-sort.py
│ └── short-bubble.py
├── stack/
│ ├── examples/
│ │ ├── balanced-brackets.py
│ │ ├── number_converter.py
│ │ └── stack.py
│ ├── stack-array-impl-less-efficient.py
│ ├── stack-array-impl.py
│ ├── stack-fixed-size-array-impl.py
│ ├── stack-linked-list-impl.py
│ └── stack_two_queues.py
├── stack_two_queues.py
├── substring-search/
│ └── brute_force.py
├── trees/
│ ├── avl-tree.py
│ ├── binary-heap.py
│ ├── binary-search-tree.py
│ ├── class-representation.py
│ ├── list-representation.py
│ ├── parse-tree.py
│ ├── stack.py
│ └── tree-traversal/
│ ├── functions.py
│ ├── inorder-traversal-example.py
│ ├── postorder-traversal-example.py
│ ├── preorder-traversal-example.py
│ ├── stack.py
│ └── treenode.py
└── trie/
└── trie.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/__pycache__/
/venv/
/.idea/
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 Ivan Markovic
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Problem-Solving-with-Algorithms-and-Data-Structures-using-Python
I started the project by learning data structures and algorithms from a book *Problem Solving with Algorithms and Data Structures using Python*.
It does not contain everything from the book,
nor is everything implemented in the same way,
but it also contains other data structures, algorithms and problems.
[Book website](https://runestone.academy/runestone/books/published/pythonds/index.html)
[Videos](https://teklern.blogspot.com/p/blog-page.html)
### [Algorithm analysis](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/analysis)
- [Anagrams - quadratic solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/analysis/anagrams-quadratic-solution.py)
- [Anagrams - log linear solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/analysis/anagrams-loglinear-solution.py)
- [Anagrams - linear solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/analysis/anagrams-linear-solution.py)
- [Time - iterative solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/analysis/time-iterative-approach.py)
- [Time - non-iterative solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/analysis/time-noniterative-approach.py)
### [Stack](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/stack)
- [Stack - array implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/stack/stack-array-impl.py)
- [Stack - less efficient array implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/stack/stack-array-impl-less-efficient.py)
- [Stack - fixed size array implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/stack/stack-fixed-size-array-impl.py)
- [Stack two queues](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/stack/stack_two_queues.py)
- [Stack - linked list implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/stack/stack-linked-list-impl.py)
- [Examples](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/stack/examples)
- [Balanced brackets](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/stack/examples/balanced-brackets.py)
- [Number converter](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/stack/examples/number_converter.py)
### [Queue](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/queue)
- [Queue - array implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/queue/queue-array-impl.py)
- [Queue - fixed size array implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/queue/queue-fixed-size-array-impl.py)
- [Queue - linked list implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/queue/queue-linked-list-impl.py)
- [Circular queue - fixed size array implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/queue/circular-queue-fixed-size-array-impl.py)
- [Queue - two stacks implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/queue/queue-two-stacks-impl.py)
### [Deque](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/deque)
- [Deque - array implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/deque/deque.py)
- [Circular deque - fixed size array implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/deque/circular-deque.py)
- [Deque - linked list implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/deque/deque_linked_list_impl.py)
### [Linked lists](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/linked-lists)
- [Singly linked list](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/linked-lists/singly-linked-list)
- [Doubly linked list](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/linked-lists/doubly-linked-list)
- [Circular singly linked list](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/linked-lists/circular-singly-linked-list)
- [Circular doubly linked list](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/linked-lists/circular-doubly-linked-list)
### [Recursion](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/recursion)
- [Convert number - recursive solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/convert-number.py)
- [Convert number - iterative solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/convert-number-iterative.py)
- [Factorial](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/factorial.py)
- [Fibonacci - iterative solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-iterative.py)
- [Fibonacci - recursive worst solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-recursive-worst-solution.py)
- [Fibonacci - memoization](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-memoization.py)
- [Fibonacci - recursive solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-recursive.py)
- [Fibonacci sum recursive](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-sum-recursive.py)
- [Fibonacci sum iterative](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-sum-iterative.py)
- [Maze - path finder](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/maze.py)
- [Palindrome](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/palindrome.py)
- [Reverse linked list - recursive solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/reverse-linked-list.py)
- [Reverse linked list - iterative solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/reverse-linked-list-iterative.py)
- [Reverse linked list - iterative solution stack](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/reverse-linked-list-iterative-stack.py)
- [Reverse list](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/reverse-list.py)
- [Reverse string](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/reverse-string.py)
- [Sum numbers - binary recursion](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/sum-numbers-binary-recursion.py)
- [Sum numbers - recursion with pointer](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/sum-numbers-pointer.py)
- [Sum numbers - recursion with slicing](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/sum-numbers-slicing.py)
- [Towers of Hanoi](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/towers-of-hanoi.py)
### [Searching](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/searching)
- [Sequential search - unordered list](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/searching/sequential-search-unordered-list.py)
- [Sequential search - ordered list](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/searching/sequential-search-ordered-list.py)
- [Binary search iterative](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/searching/binary-search-iterative.py)
- [Binary search recursive](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/searching/binary-search-recursive.py)
- [Binary search recursive pointers](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/searching/binary-search-recursive-pointers.py)
### [Hash table](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/hash-table)
- [Linear probing](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/hash-table/linear-probing.py)
- [Chaining](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/hash-table/chaining.py)
### [Trees](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/trees)
- [List of lists representation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/list-representation.py)
- [Class representation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/class-representation.py)
- [Parse tree](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/parse-tree.py)
- [Tree traversal](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/trees/tree-traversal)
- [Methods](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/tree-traversal/treenode.py)
- [Functions](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/tree-traversal/functions.py)
- [Preorder traversal example](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/tree-traversal/preorder-traversal-example.py)
- [Inorder traversal example](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/tree-traversal/inorder-traversal-example.py)
- [Postorder traversal example](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/tree-traversal/postorder-traversal-example.py)
- [Binary Heap - min heap implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/binary-heap.py)
- [Binary Search Tree](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/binary-search-tree.py)
- [AVL tree](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/trees/avl-tree.py)
### [Sorting](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/sorting)
- [Bubble sort](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/sorting/bubble-sort.py)
- [Short bubble](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/sorting/short-bubble.py)
- [Insertion sort](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/sorting/insertion-sort.py)
- [Selection sort](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/sorting/selection-sort.py)
- [Merge sort](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/sorting/merge-sort.py)
- [Quicksort in place](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/sorting/quicksort.py)
- [Quicksort - return new array](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/sorting/quicksort-return-new-array.py)
### [Graphs](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs)
- [Breadth first search](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/breadth-first-search)
- [Depth first search](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/depth-first-search)
- [Depth first search - stack](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/depth-first-search/depth-first-search)
- [Depth first search - recursive](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/depth-first-search/depth-first-search-recursive)
- [Cycle detection](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/cycle-detection)
- [Cycle detection directed graph](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/cycle-detection/cycle-directed-graph)
- [Cycle detection undirected graph](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/cycle-detection/cycle-undirected-graph)
- [Topological sorting](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/topological-sorting)
- [Dijkstra algorithm - Shortest path](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/dijkstra)
- [Priority Queue implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/dijkstra/priority-queue-impl-adjacency-map)
- [Matrix implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/dijkstra/matrix-impl)
- [Adjacency list implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/dijkstra/adjacency-list-impl)
- [Bellman-Ford algorithm](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/bellman-ford)
- [Bellman-Ford algorithm - negative weight cycle](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/bellman-ford-negative-weight-cycle)
- [Minimum Spanning Tree](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/minimum-spanning-tree)
- [Minimum Spanning Tree in undirected graph](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/minimum-spanning-tree/breadth-first-search)
- [Prim's algorithm - Minimum Spanning Tree in undirected weighted graph](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/minimum-spanning-tree/prims-algorithm)
- [Kruskal's algorithm - Minimum Spanning Tree in undirected weighted graph](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/minimum-spanning-tree/kruskals-algorithm)
- [Is graph bipartite](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/is-graph-bipartite)
- [Union find](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/union-find)
- [Number of connected components](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/union-find/number-of-connected-components)
- [Union find path compression](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/union-find/union-find-path-compression)
- [Kosaraju's algorithm](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/kosarajus-algorithm)
### [Trie](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/trie)
- [Trie](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/trie)
### [Substring search](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/substring-search)
- [Brute force algorithm](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/substring-search/brute_force.py)
================================================
FILE: analysis/anagrams-linear-solution.py
================================================
# O(n)
def anagrams(string1: str, string2: str) -> bool:
if len(string1) != len(string2):
return False
is_anagram: bool = True
list1: list = [0] * 26
list2: list = [0] * 26
count_characters(string1, list1)
count_characters(string2, list2)
pos: int = 0
while pos < len(list1) and is_anagram: # 26 steps max
if list1[pos] != list2[pos]:
is_anagram = False
else:
pos += 1
return is_anagram
def count_characters(string: str, arr: list):
for character in string:
index: int = ord(character) - ord('a')
arr[index] += 1
print(anagrams("python", "typhon"))
print(anagrams("abba", "baba"))
print(anagrams("abba", "abbb"))
================================================
FILE: analysis/anagrams-loglinear-solution.py
================================================
# O(nlogn)
def anagrams(string1: str, string2: str) -> bool:
if len(string1) != len(string2):
return False
is_anagram: bool = True
list1: list = list(string1)
list2: list = list(string2)
list1.sort() # sorting is O(nlogn)
list2.sort() # sorting is O(nlogn)
pos: int = 0
# loop is O(n)
while pos < len(list1) and is_anagram:
if list1[pos] != list2[pos]:
is_anagram = False
else:
pos += 1
return is_anagram
print(anagrams("python", "typhon"))
print(anagrams("abba", "baba"))
print(anagrams("abba", "abbb"))
================================================
FILE: analysis/anagrams-quadratic-solution.py
================================================
# O(n2)
def anagrams(string1: str, string2: str) -> bool:
if len(string1) != len(string2):
return False
is_anagram: bool = True
list2: list = list(string2)
pos1: int = 0
while pos1 < len(string1) and is_anagram:
character = string1[pos1]
character_found: bool = False
pos2: int = 0
while pos2 < len(list2) and not character_found:
if list2[pos2] == character:
list2[pos2] = None
character_found = True
else:
pos2 += 1
if not character_found:
is_anagram = False
else:
pos1 += 1
return is_anagram
print(anagrams("python", "typhon"))
print(anagrams("abba", "baba"))
print(anagrams("abba", "abbb"))
================================================
FILE: analysis/time-iterative-approach.py
================================================
import time
def sum_nums(n: int) -> int:
start = time.time()
total: int = 0
for i in range(n + 1):
total += i
end = time.time()
print("For ", n, " numbers time is", end - start)
return total
nums: list = [100, 10000, 100000, 1000000]
for n in nums:
print(sum_nums(n))
================================================
FILE: analysis/time-noniterative-approach.py
================================================
import time
def sum_nums(n: int) -> int:
start = time.time()
total: int = n * (n + 1) / 2
end = time.time()
print("For ", n, " numbers time is", end - start)
return total
nums: list = [100, 10000, 100000, 1000000]
for n in nums:
print(sum_nums(n))
================================================
FILE: deque/circular-deque.py
================================================
from typing import Any, List
class Deque:
def __init__(self, capacity: int = 10) -> None:
self.capacity: int = capacity
self.length: int = 0
self._deque: List[Any] = [None] * self.capacity
self.front: int = -1
self.rear: int = -1
def is_empty(self) -> bool:
return self.front == -1
def is_full(self) -> bool:
return (self.rear + 1) % self.capacity == self.front
def size(self) -> int:
return self.length
def add_front(self, item: Any):
if self.is_full():
raise Exception('Deque is full')
if self.is_empty(): # self.rear == -1
self.front = self.rear = 0
elif self.front == 0:
self.front = self.capacity - 1
else:
self.front -= 1
self._deque[self.front] = item
self.length += 1
def add_rear(self, item: Any):
if self.is_full():
raise Exception('Deque is full')
if self.is_empty(): # self.rear == -1
self.front = self.rear = 0
else:
self.rear = (self.rear + 1) % self.capacity
self._deque[self.rear] = item
self.length += 1
def remove_front(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
item: Any = self._deque[self.front]
if self.front == self.rear:
self.front = self.rear = -1
else:
self.front = (self.front + 1) % self.capacity
self.length -= 1
return item
def remove_rear(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
item: Any = self._deque[self.rear]
if self.rear == self.front:
self.rear = self.front = -1
elif self.rear == 0:
self.rear = self.capacity - 1
else:
self.rear -= 1
self.length -= 1
return item
def get_front(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
return self._deque[self.front]
def get_rear(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
return self._deque[self.rear]
def is_palindrome(string:str='') -> bool:
d: Deque = Deque()
for character in string:
d.add_rear(character)
palindrome: bool = True
while d.size() > 1 and palindrome:
if d.remove_front() != d.remove_rear():
palindrome = False
return palindrome
print(is_palindrome('radar'))
print(is_palindrome('radr'))
print(is_palindrome('r'))
print(is_palindrome(''))
================================================
FILE: deque/deque.py
================================================
from typing import Any, List
class Deque:
def __init__(self) -> None:
self._deque: List[Any] = []
def is_empty(self) -> bool:
return len(self._deque) == 0
def size(self) -> int:
return len(self._deque)
def add_front(self, item: Any):
self._deque.insert(0, item)
def add_rear(self, item: Any):
self._deque.append(item)
def remove_front(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
return self._deque.pop(0)
def remove_rear(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
return self._deque.pop()
def is_palindrome(string:str='') -> bool:
d: Deque = Deque()
for character in string:
d.add_rear(character)
palindrome: bool = True
while d.size() > 1 and palindrome:
if d.remove_front() != d.remove_rear():
palindrome = False
return palindrome
print(is_palindrome('radar'))
print(is_palindrome('radr'))
print(is_palindrome('r'))
print(is_palindrome(''))
================================================
FILE: deque/deque_linked_list_impl.py
================================================
from typing import List, Any
class ListNode:
def __init__(self, key:Any = None, prev:'ListNode' = None, next:'ListNode' = None):
self.key:Any = key
self.prev:'ListNode' = prev
self.next:'ListNode' = next
class Deque:
def __init__(self):
self._head:ListNode = None
self._tail:ListNode = None
self._length:int = 0
def size(self) -> int:
return self._length
def is_empty(self) -> bool:
return self._length == 0
def add_front(self, e:Any) -> None:
if self.is_empty():
self._head = self._tail = ListNode(e)
else:
self._head = ListNode(e, None, self._head)
self._head.next.prev = self._head
self._length += 1
def add_rear(self, e:Any) -> None:
if self.is_empty():
self._head = self._tail = ListNode(e)
else:
self._tail.next = ListNode(e, self._tail, None)
self._tail = self._tail.next
self._length += 1
def remove_front(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
e:Any = self._head.key
if self._head == self._tail:
self._head = self._tail = None
else:
self._head = self._head.next
self._head.prev = None
self._length -= 1
return e
def remove_rear(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
e:Any = self._tail.key
if self._head == self._tail:
self._head = self._tail = None
else:
self._tail = self._tail.prev
self._tail.next = None
self._length -= 1
return e
def get_front(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
return self._head.key
def remove_rear(self) -> Any:
if self.is_empty():
raise Exception('Deque is empty')
return self._tail.key
================================================
FILE: graphs/bellman-ford/graph.py
================================================
# Bellman-Ford algorithm
# Find shortest paths from one vertex,
# to all other vertices in weighted graph.
# Runtime O(V*E)
from typing import Set, Dict, List, Tuple
class Graph:
def __init__(self) -> None:
self.vertices:Set[str] = set()
self.edges:List[Tuple[str, str, int]] = list()
self.prev:Dict[str, str] = dict()
self.distances:Dict[str, int] = dict()
def add_vertex(self, label:str) -> None:
self.vertices.add(label)
self.prev[label] = None
self.distances[label] = None
def add_edge(self, v1:str, v2:str, distance:int) -> None:
self.edges.append((v1, v2, distance))
def bellman_ford(self, label:str) -> None:
self.distances[label] = 0
for _ in range(len(self.vertices) - 1):
for v1, v2, distance in self.edges:
if self.distances[v1] is None:
continue
if self.distances[v2] is None or self.distances[v2] > self.distances[v1] + distance:
self.distances[v2] = self.distances[v1] + distance
self.prev[v2] = v1
# Check for negative-weight cycles
for v1, v2, distance in self.edges:
if self.distances[v1] is not None and self.distances[v2] > self.distances[v1] + distance:
raise ValueError("Graph contains a negative-weight cycle")
self._print_paths(label)
def _print_paths(self, label:str) -> None:
for v in self.vertices:
if v == label:
continue
if self.distances[v] is not None:
print(f'Path from {label} to {v} is {self._return_path(v)} and distance is {self.distances[v]}')
else:
print(f'No path from {label} to {v}')
def _return_path(self, label:str) -> str:
if self.prev[label] is None:
return label
return self._return_path(self.prev[label]) + ' -> ' + label
g = Graph()
for v in ['A', 'B', 'C', 'D']:
g.add_vertex(v)
g.add_edge('A', 'B', 1)
g.add_edge('B', 'C', 3)
g.add_edge('A', 'C', 10)
g.add_edge('C', 'D', 2)
g.add_edge('D', 'B', 4)
g.bellman_ford('A')
================================================
FILE: graphs/bellman-ford-negative-weight-cycle/graph.py
================================================
# Bellman-Ford algorithm
# Find shortest paths from one vertex,
# to all other vertices in weighted graph.
# Runtime O(V*E)
# Negative weight cycle will be found with one more loop through edges
# If there is a need to update distance than it is a negative weight cycle
class Graph:
def __init__(self):
self.vertices: list = []
self.edges: list = []
self.distance: dict = {}
self.prev: dict = {}
def add_vertex(self, label: str):
self.vertices.append(label)
self.distance[label] = None
self.prev[label] = None
def add_edge(self, label1: str, label2: str, weight: int):
self.edges.append([label1, label2, weight])
def bellman_ford(self, source: str):
self.distance[source] = 0
for _ in range(len(self.vertices)):
for edge in self.edges:
label1: str = edge[0]
label2: str = edge[1]
weight: int = edge[2]
if self.distance[label1] is None:
continue
if self.distance[label2] is None:
self.distance[label2] = self.distance[label1] + weight
self.prev[label2] = label1
continue
if self.distance[label1] + weight < self.distance[label2]:
self.distance[label2] = self.distance[label1] + weight
self.prev[label2] = label1
continue
for edge in self.edges:
label1: str = edge[0]
label2: str = edge[1]
weight: int = edge[2]
if self.distance[label1] is None:
continue
if self.distance[label2] is None:
continue
if self.distance[label1] + weight < self.distance[label2]:
print(f'Negative weight cycle from {label1} to {label2}')
def print_distances(self, source: str):
for v in self.vertices:
if v != source:
distance: int = self.distance[v]
print(f'Distance from {source} to {v} is {distance}')
================================================
FILE: graphs/breadth-first-search/graph.py
================================================
from queue import Queue
class Graph:
def __init__(self):
self.vertices: list = []
self.adjacency_list: dict = {}
self.prev: dict = {}
self.distance: dict = {}
self.colors: dict = {}
def add_vertex(self, label: str):
self.vertices.append(label)
self.adjacency_list[label]: list = []
self.prev[label] = None
self.distance[label] = 0
self.colors[label] = "white"
def add_edge(self, label1: str, label2: str):
self.adjacency_list[label1].append(label2)
self.adjacency_list[label2].append(label1)
def bfs(self, label: str):
q: Queue = Queue()
q.enqueue(label)
self.colors[label] = "gray"
while not q.is_empty():
tmp: str = q.dequeue()
for neighbour in self.adjacency_list[tmp]:
if self.colors[neighbour] == "white":
self.prev[neighbour] = tmp
self.distance[neighbour] = self.distance[tmp] + 1
self.colors[neighbour] = "gray"
q.enqueue(neighbour)
self.colors[tmp] = "black"
def return_path(self, label: str) -> str:
if self.prev[label] is None:
return label
else:
return self.return_path(self.prev[label]) + " -> " + label
================================================
FILE: graphs/breadth-first-search/main.py
================================================
from graph import Graph
graph = Graph()
my_vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
# add vertices
for i in range(len(my_vertices)):
graph.add_vertex(my_vertices[i])
graph.add_edge('A', 'B')
graph.add_edge('A', 'C')
graph.add_edge('A', 'D')
graph.add_edge('C', 'D')
graph.add_edge('C', 'G')
graph.add_edge('D', 'G')
graph.add_edge('D', 'H')
graph.add_edge('B', 'E')
graph.add_edge('B', 'F')
graph.add_edge('E', 'I')
graph.bfs("A")
print(graph.return_path("H"))
================================================
FILE: graphs/breadth-first-search/queue.py
================================================
class Queue:
def __init__(self):
self.queue = []
def enqueue(self, item):
self.queue.insert(0, item)
def dequeue(self):
return self.queue.pop()
def size(self):
return len(self.queue)
def is_empty(self):
return self.queue == []
================================================
FILE: graphs/cycle-detection/Cycle.md
================================================
#Cycle - vertex is reachable from itself.
##Undirected graph
'''
edge(u, v)
'''
- v is in the stack, visited but not explored
- v is ancestor of u, but not parent
##Directed graph
'''
edge(u, v)
'''
- v is in the stack, visited but not explored
- v is ancestor of u
================================================
FILE: graphs/cycle-detection/cycle-directed-graph/graph.py
================================================
class Graph:
def __init__(self):
self.vertices: list = []
self.adjacency_list: dict = {}
self.prev: dict = {}
self.distance: dict = {}
self.colors: dict = {}
self.entry: dict = {}
self.exit: dict = {}
self.time: int = 0
def add_vertex(self, label: str):
self.vertices.append(label)
self.adjacency_list[label]: list = []
self.prev[label] = None
self.distance[label] = 0
self.colors[label] = "white"
def add_edge(self, label1: str, label2: str):
self.adjacency_list[label1].append(label2)
def dfs(self, label: str):
self.colors[label] = "gray"
self.time += 1
self.entry[label] = self.time
for neighbour in self.adjacency_list[label]:
if self.colors[neighbour] == "white":
self.prev[neighbour] = label
self.distance[neighbour] = self.distance[label] + 1
self.dfs(neighbour)
if self.colors[neighbour] == "gray":
print("Cycle", label, " - ", neighbour)
self.colors[label] = "black"
self.time += 1
self.exit[label] = self.time
def return_path(self, label: str) -> str:
if self.prev[label] is None:
return label
else:
return self.return_path(self.prev[label]) + " -> " + label
================================================
FILE: graphs/cycle-detection/cycle-directed-graph/main.py
================================================
from graph import Graph
graph: Graph = Graph()
vertices = ["a", "b", "c", "d"]
for vertex in vertices:
graph.add_vertex(vertex)
graph.add_edge("a", "b")
graph.add_edge("b", "c")
graph.add_edge("c", "d")
graph.add_edge("d", "b")
graph.dfs("a")
================================================
FILE: graphs/cycle-detection/cycle-undirected-graph/graph.py
================================================
class Graph:
def __init__(self):
self.vertices: list = []
self.adjacency_list: dict = {}
self.prev: dict = {}
self.distance: dict = {}
self.colors: dict = {}
self.entry: dict = {}
self.exit: dict = {}
self.time: int = 0
def add_vertex(self, label: str):
self.vertices.append(label)
self.adjacency_list[label]: list = []
self.prev[label] = None
self.distance[label] = 0
self.colors[label] = "white"
def add_edge(self, label1: str, label2: str):
self.adjacency_list[label1].append(label2)
self.adjacency_list[label2].append(label1)
def dfs(self, label: str):
self.colors[label] = "gray"
self.time += 1
self.entry[label] = self.time
for neighbour in self.adjacency_list[label]:
if self.colors[neighbour] == "white":
self.prev[neighbour] = label
self.distance[neighbour] = self.distance[label] + 1
self.dfs(neighbour)
if self.colors[neighbour] == "gray" and self.prev[label] != neighbour:
print("Cycle", label, " - ", neighbour)
self.colors[label] = "black"
self.time += 1
self.exit[label] = self.time
def return_path(self, label: str) -> str:
if self.prev[label] is None:
return label
else:
return self.return_path(self.prev[label]) + " -> " + label
================================================
FILE: graphs/cycle-detection/cycle-undirected-graph/main.py
================================================
from graph import Graph
graph: Graph = Graph()
vertices = ["a", "b", "c", "d"]
for vertex in vertices:
graph.add_vertex(vertex)
graph.add_edge("a", "b")
graph.add_edge("b", "c")
graph.add_edge("c", "d")
# graph.add_edge("d", "b")
graph.dfs("a")
================================================
FILE: graphs/depth-first-search/depth-first-search/graph.py
================================================
from stack import Stack
class Graph:
def __init__(self):
self.vertices: list = []
self.adjacency_list: dict = {}
self.prev: dict = {}
self.distance: dict = {}
self.colors: dict = {}
self.entry: dict = {}
self.exit: dict = {}
self.time: int = 0
def add_vertex(self, label: str):
self.vertices.append(label)
self.adjacency_list[label]: list = []
self.prev[label] = None
self.distance[label] = 0
self.colors[label] = "white"
def add_edge(self, label1: str, label2: str):
self.adjacency_list[label1].append(label2)
self.adjacency_list[label2].append(label1)
def dfs(self, label: str):
s: Stack = Stack()
s.push(label)
self.colors[label] = "gray"
self.time += 1
self.entry[label] = self.time
while not s.is_empty():
tmp: str = s.peek()
neighbour: str = self.find_unvisited_neighbour(tmp)
if neighbour is not None:
self.prev[neighbour] = tmp
self.distance[neighbour] = self.distance[tmp] + 1
self.colors[neighbour] = "gray"
self.time += 1
self.entry[neighbour] = self.time
s.push(neighbour)
else:
s.pop()
self.time += 1
self.exit[tmp] = self.time
self.colors[tmp] = "black"
def return_path(self, label: str) -> str:
if self.prev[label] is None:
return label
else:
return self.return_path(self.prev[label]) + " -> " + label
def find_unvisited_neighbour(self, tmp) -> str:
for n in self.adjacency_list[tmp]:
if self.colors[n] == "white":
return n
return None
================================================
FILE: graphs/depth-first-search/depth-first-search/main.py
================================================
from graph import Graph
graph = Graph()
my_vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
# add vertices
for i in range(len(my_vertices)):
graph.add_vertex(my_vertices[i])
graph.add_edge('A', 'B')
graph.add_edge('A', 'C')
graph.add_edge('A', 'D')
graph.add_edge('C', 'D')
graph.add_edge('C', 'G')
graph.add_edge('D', 'G')
graph.add_edge('D', 'H')
graph.add_edge('B', 'E')
graph.add_edge('B', 'F')
graph.add_edge('E', 'I')
graph.dfs("A")
print(graph.return_path("H"))
================================================
FILE: graphs/depth-first-search/depth-first-search/stack.py
================================================
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
================================================
FILE: graphs/depth-first-search/depth-first-search-recursive/graph.py
================================================
class Graph:
def __init__(self):
self.vertices: list = []
self.adjacency_list: dict = {}
self.prev: dict = {}
self.distance: dict = {}
self.colors: dict = {}
self.entry: dict = {}
self.exit: dict = {}
self.time: int = 0
def add_vertex(self, label: str):
self.vertices.append(label)
self.adjacency_list[label]: list = []
self.prev[label] = None
self.distance[label] = 0
self.colors[label] = "white"
def add_edge(self, label1: str, label2: str):
self.adjacency_list[label1].append(label2)
self.adjacency_list[label2].append(label1)
def dfs(self, label: str):
self.colors[label] = "gray"
self.time += 1
self.entry[label] = self.time
for neighbour in self.adjacency_list[label]:
if self.colors[neighbour] == "white":
self.prev[neighbour] = label
self.distance[neighbour] = self.distance[label] + 1
self.dfs(neighbour)
self.colors[label] = "black"
self.time += 1
self.exit[label] = self.time
def return_path(self, label: str) -> str:
if self.prev[label] is None:
return label
else:
return self.return_path(self.prev[label]) + " -> " + label
================================================
FILE: graphs/depth-first-search/depth-first-search-recursive/main.py
================================================
from graph import Graph
graph = Graph()
my_vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
# add vertices
for i in range(len(my_vertices)):
graph.add_vertex(my_vertices[i])
graph.add_edge('A', 'B')
graph.add_edge('A', 'C')
graph.add_edge('A', 'D')
graph.add_edge('C', 'D')
graph.add_edge('C', 'G')
graph.add_edge('D', 'G')
graph.add_edge('D', 'H')
graph.add_edge('B', 'E')
graph.add_edge('B', 'F')
graph.add_edge('E', 'I')
graph.dfs("A")
print(graph.return_path("H"))
================================================
FILE: graphs/dijkstra/adjacency-list-impl/main.py
================================================
from typing import List, Dict, Set
from vertex import Vertex
class Graph:
def __init__(self, capacity :int =10):
self.capacity :int = capacity
self.vertices :Dict[str, Vertex] = dict()
self.prev :Dict[str, str] = dict()
self.adjacency_list :Dict[str, List[Vertex]] = dict()
self.visited :Set[str] = set()
def add_vertex(self, label :str, weight :int = float('inf')) -> None:
v :Vertex = Vertex(label, weight)
self.vertices[v.label] = v
self.adjacency_list[label] = list()
self.prev[label] = None
def add_edge(self, label1 :str, label2 :str, weight :int) -> None:
v :Vertex = Vertex(label2, weight)
self.adjacency_list[label1].append(v)
def dijkstra(self, label :str) -> None:
v :Vertex = self.vertices[label]
v.weight = 0
while v is not None:
for n in self.adjacency_list[v.label]:
o :Vertex = self.vertices[n.label]
if v.weight + n.weight < o.weight:
o.weight = v.weight + n.weight
self.prev[o.label] = v.label
self.visited.add(v.label)
v = self._find_cheapest_vertex()
def show_path(self, label :str) -> str:
if self.prev[label] is None:
return label
return self.show_path(self.prev[label]) + '->' + label
def _find_cheapest_vertex(self) -> Vertex:
vertex :Vertex = None
for v in self.vertices.values():
if v.label not in self.visited:
if vertex is None:
vertex = v
elif vertex.weight > v.weight:
vertex = v
return vertex
graph: Graph = Graph()
graph.add_vertex("START")
graph.add_vertex("A")
graph.add_vertex("C")
graph.add_vertex("B")
graph.add_vertex("D")
graph.add_vertex("END")
graph.add_edge("START", "A", 0)
graph.add_edge("START", "C", 2)
graph.add_edge("A", "B", 18)
graph.add_edge("A", "D", 15)
graph.add_edge("C", "B", 3)
graph.add_edge("C", "D", 10)
graph.add_edge("B", "END", 150)
graph.add_edge("D", "END", 15)
graph.dijkstra("START")
print(graph.show_path("END"))
================================================
FILE: graphs/dijkstra/adjacency-list-impl/vertex.py
================================================
class Vertex:
def __init__(self, label :str, weight :int = float('inf')):
self.label :str = label
self.weight :int = weight
================================================
FILE: graphs/dijkstra/matrix-impl/graph.py
================================================
from vertex import Vertex
class Graph:
def __init__(self, size: int = 10):
self.size: int = size
self.index: int = 0
self.vertices_list: list = [None] * self.size
self.vertices: dict = {}
self.adjacency_matrix: list = [[None for i in range(self.size)] for j in range(self.size)]
self.prev: dict = {}
self.visited: dict = {}
def add_vertex(self, label: str):
if self.index == self.size: # matrix is full
return
vertex: Vertex = Vertex(label, float("inf"), self.index)
self.vertices_list[self.index] = vertex
self.vertices[vertex.label] = vertex
self.index += 1
self.prev[vertex.label] = None
self.visited[vertex.label] = False
def add_edge(self, label1: str, label2: str, weight: int):
index1: int = self.vertices[label1].index
index2: int = self.vertices[label2].index
self.adjacency_matrix[index1][index2] = weight
def dijkstra(self, label: str):
current_vertex: Vertex = self.vertices[label]
current_vertex.weight = 0
while current_vertex is not None:
self.visited[current_vertex.label] = True
for i in range(self.index):
if self.adjacency_matrix[current_vertex.index][i] is not None:
weight: int = self.adjacency_matrix[current_vertex.index][i]
neighbour: Vertex = self.vertices_list[i]
if current_vertex.weight + weight < neighbour.weight:
neighbour.weight = current_vertex.weight + weight
self.prev[neighbour.label] = current_vertex.label
current_vertex = self.find_minimum_weight_vertex()
def return_path(self, label: str) -> str:
if self.prev[label] is None:
return label
else:
return self.return_path(self.prev[label]) + " -> " + label
def find_minimum_weight_vertex(self):
vertex: Vertex = None
for label in self.vertices:
if not self.visited[label]:
if vertex is None:
vertex = self.vertices[label]
else:
if vertex.weight > self.vertices[label].weight:
vertex = self.vertices[label]
return vertex
================================================
FILE: graphs/dijkstra/matrix-impl/main.py
================================================
from graph import Graph
graph: Graph = Graph()
graph.add_vertex("START")
graph.add_vertex("A")
graph.add_vertex("C")
graph.add_vertex("B")
graph.add_vertex("D")
graph.add_vertex("END")
graph.add_edge("START", "A", 0)
graph.add_edge("START", "C", 2)
graph.add_edge("A", "B", 18)
graph.add_edge("A", "D", 15)
graph.add_edge("C", "B", 3)
graph.add_edge("C", "D", 10)
graph.add_edge("B", "END", 150)
graph.add_edge("D", "END", 15)
graph.dijkstra("START")
print(graph.return_path("END"))
================================================
FILE: graphs/dijkstra/matrix-impl/vertex.py
================================================
class Vertex:
def __init__(self, label: str = None, weight: int = float("inf"), index: int = None):
self.label: str = label
self.weight: int = weight
self.index: int = index
================================================
FILE: graphs/dijkstra/priority-queue-impl-adjacency-map/graph.py
================================================
from vertex import Vertex
from priorityqueue import PriorityQueue
class Graph:
def __init__(self):
self._vertices: dict = {}
self._adjacency_map: dict = {}
self._prev: dict = {}
def add_vertex(self, label: str):
v: Vertex = Vertex(label)
self._vertices[label] = v
self._adjacency_map[label]: list = []
self._prev[label] = None
def add_edge(self, label1: str, label2: str, weight: int):
self._adjacency_map[label1].append(Vertex(label2, weight))
def dijkstra(self, label: str):
self._vertices[label].weight = 0
pq: PriorityQueue = PriorityQueue()
for label in self._vertices:
pq.insert(self._vertices[label])
while not pq.is_empty():
current: Vertex = pq.delete_min()
for neighbour in self._adjacency_map[current.label]:
v: Vertex = self._vertices[neighbour.label]
if current.weight + neighbour.weight < v.weight:
v.weight = current.weight + neighbour.weight
self._prev[v.label] = current.label
pq.decrease_key(v.key)
def show_path(self, label: str) -> str:
if self._prev[label] is None:
return label
else:
return self.show_path(self._prev[label]) + " -> " + label
================================================
FILE: graphs/dijkstra/priority-queue-impl-adjacency-map/main.py
================================================
from graph import Graph
graph: Graph = Graph()
graph.add_vertex("START")
graph.add_vertex("A")
graph.add_vertex("C")
graph.add_vertex("B")
graph.add_vertex("D")
graph.add_vertex("END")
graph.add_edge("START", "A", 0)
graph.add_edge("START", "C", 2)
graph.add_edge("A", "B", 18)
graph.add_edge("A", "D", 15)
graph.add_edge("C", "B", 3)
graph.add_edge("C", "D", 10)
graph.add_edge("B", "END", 150)
graph.add_edge("D", "END", 15)
graph.dijkstra("START")
print(graph.show_path("END"))
================================================
FILE: graphs/dijkstra/priority-queue-impl-adjacency-map/priorityqueue.py
================================================
from vertex import Vertex
class PriorityQueue:
def __init__(self):
self.pq: list = [None]
self._pointer: int = 0
def is_empty(self) -> bool:
return self._pointer == 0
def insert(self, vertex: Vertex):
self.pq.append(vertex)
self._pointer += 1
vertex.key = self._pointer
self._perc_up(self._pointer)
def _perc_up(self, pointer: int):
while pointer // 2 > 0:
if self.pq[pointer // 2].weight > self.pq[pointer].weight:
self.pq[pointer // 2], self.pq[pointer] = self.pq[pointer], self.pq[pointer // 2]
self.pq[pointer // 2].key = pointer // 2
self.pq[pointer].key = pointer
pointer = pointer // 2
def decrease_key(self, pointer: int):
self._perc_up(pointer)
def delete_min(self) -> Vertex:
if self.is_empty():
raise Exception("Priority queue is empty")
v: Vertex = self.pq[1]
self.pq[1] = self.pq[self._pointer]
self.pq[1].key = 1
self.pq.pop()
self._pointer -= 1
self._perc_down(1)
return v
def _perc_down(self, pointer: int):
while pointer * 2 <= self._pointer:
min_index: int = self._find_swap_index(pointer)
if self.pq[pointer].weight > self.pq[min_index].weight:
self.pq[pointer], self.pq[min_index] = self.pq[min_index], self.pq[pointer]
self.pq[pointer].key = pointer
self.pq[min_index].key = min_index
pointer = min_index
def _find_swap_index(self, pointer: int) -> int:
if pointer * 2 + 1 > self._pointer:
return pointer * 2
else:
if self.pq[pointer * 2].weight <= self.pq[pointer * 2 + 1].weight:
return pointer * 2
else:
return pointer * 2 + 1
================================================
FILE: graphs/dijkstra/priority-queue-impl-adjacency-map/vertex.py
================================================
class Vertex:
def __init__(self, label: str = None, weight: int = float("inf"), key: int = None):
self.label: str = label
self.weight: int = weight
self.key: int = key
================================================
FILE: graphs/is-graph-bipartite/graph.py
================================================
from queue import Queue
class Graph:
def __init__(self):
self.vertices: list = []
self.adjacency_list: dict = {}
self.color: dict = {}
def add_vertex(self, label: str = None):
self.vertices.append(label)
self.adjacency_list[label]: list = []
self.color[label] = None
def add_edge(self, label1: str = None, label2: str = None):
self.adjacency_list[label1].append(label2)
self.adjacency_list[label2].append(label1)
def bipartite_check(self) -> bool:
for vertex in self.vertices:
if self.color[vertex] is not None:
continue
q: Queue = Queue()
self.color[vertex] = "red"
q.enqueue(vertex)
while not q.is_empty():
tmp: str = q.dequeue()
for neighbour in self.adjacency_list[tmp]:
if self.color[neighbour] == self.color[tmp]:
return False
if self.color[neighbour] is None:
if self.color[tmp] == "red":
self.color[neighbour] = "blue"
else:
self.color[neighbour] = "red"
q.enqueue(neighbour)
return True
================================================
FILE: graphs/is-graph-bipartite/main.py
================================================
from graph import Graph
g: Graph = Graph()
g.add_vertex("a")
g.add_vertex("b")
g.add_vertex("c")
g.add_vertex("d")
# a, b ||---|| c, d
g.add_edge("a", "c")
g.add_edge("a", "d")
g.add_edge("b", "c")
g.add_edge("b", "d")
# g.add_edge("a", "b")
print(g.bipartite_check())
================================================
FILE: graphs/is-graph-bipartite/queue.py
================================================
class Queue:
def __init__(self):
self._queue: list = []
def is_empty(self) -> bool:
return len(self._queue) == 0
def enqueue(self, vertex: str):
self._queue.append(vertex)
def dequeue(self):
if self.is_empty():
raise Exception("Queue is empty")
return self._queue.pop(0)
================================================
FILE: graphs/kosarajus-algorithm/graph.py
================================================
from typing import Dict, List, Set
from stack import Stack
class Graph:
def __init__(self) -> None:
self.vertices:Set[str] = set()
self.adjacency_list:Dict[str, Set[str]] = dict()
self.adjacency_list_reversed:Dict[str, Set[str]] = dict()
self.visited:Set[str] = set()
self.stack:Stack = Stack()
def add_vertex(self, label:str) -> None:
self.vertices.add(label)
self.adjacency_list[label] = set()
self.adjacency_list_reversed[label] = set()
def add_edge(self, label1:str, label2:str) -> None:
if label1 not in self.vertices or label2 not in self.vertices:
raise Exception('Vertices are not added')
self.adjacency_list[label1].add(label2)
self.adjacency_list_reversed[label2].add(label1)
def kosaraju(self) -> List[List[str]]:
for v in self.vertices:
if v not in self.visited:
self._dfs(v)
self.visited.clear()
connected_components:List[List[str]] = list()
while not self.stack.is_empty():
v:str = self.stack.pop()
if v not in self.visited:
connected:List[str] = list()
self._dfs_reversed(v, connected)
if len(connected) > 0:
connected_components.append(connected)
return list(connected_components)
def _dfs(self, label:str) -> None:
self.visited.add(label)
for n in self.adjacency_list[label]:
if n not in self.visited:
self._dfs(n)
self.stack.push(label)
def _dfs_reversed(self, v:str, connected:List[str]) -> None:
connected.append(v)
self.visited.add(v)
for n in self.adjacency_list_reversed[v]:
if n not in self.visited:
self._dfs_reversed(n, connected)
================================================
FILE: graphs/kosarajus-algorithm/main.py
================================================
from graph import Graph
g: Graph = Graph()
for i in range(9):
g.add_vertex(str(i))
g.add_edge('0', '1')
g.add_edge('1', '2')
g.add_edge('2', '3')
g.add_edge('3', '0')
g.add_edge('2', '4')
g.add_edge('4', '5')
g.add_edge('5', '6')
g.add_edge('6', '4')
g.add_edge('7', '6')
g.add_edge('8', '7')
print(g.kosaraju())
================================================
FILE: graphs/kosarajus-algorithm/stack.py
================================================
class Stack:
def __init__(self):
self._stack: list = []
def is_empty(self) -> bool:
return len(self._stack) == 0
def push(self, item):
self._stack.append(item)
def pop(self):
if self.is_empty():
raise Exception("Stack is empty")
return self._stack.pop()
def peek(self):
if self.is_empty():
raise Exception("Stack is empty")
# return self._stack[-1] # python way
return self._stack[len(self._stack) - 1]
def size(self) -> int:
return len(self._stack)
================================================
FILE: graphs/minimum-spanning-tree/breadth-first-search/graph.py
================================================
from queue import Queue
class Graph:
def __init__(self):
self.vertices: list = []
self.adjacency_list: dict = {}
self.prev: dict = {}
self.distance: dict = {}
self.colors: dict = {}
def add_vertex(self, label: str):
self.vertices.append(label)
self.adjacency_list[label]: list = []
self.prev[label] = None
self.distance[label] = 0
self.colors[label] = "white"
def add_edge(self, label1: str, label2: str):
self.adjacency_list[label1].append(label2)
self.adjacency_list[label2].append(label1)
def minimum_spanning_tree(self, label: str) -> list: # this is breadth first search
min_edges: list = []
q: Queue = Queue()
q.enqueue(label)
self.colors[label] = "gray"
while not q.is_empty():
tmp: str = q.dequeue()
for neighbour in self.adjacency_list[tmp]:
if self.colors[neighbour] == "white":
min_edges.append([tmp, neighbour])
self.prev[neighbour] = tmp
self.distance[neighbour] = self.distance[tmp] + 1
self.colors[neighbour] = "gray"
q.enqueue(neighbour)
self.colors[tmp] = "black"
return min_edges
def return_path(self, label: str) -> str:
if self.prev[label] is None:
return label
else:
return self.return_path(self.prev[label]) + " -> " + label
================================================
FILE: graphs/minimum-spanning-tree/breadth-first-search/main.py
================================================
from graph import Graph
graph = Graph()
my_vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
# add vertices
for i in range(len(my_vertices)):
graph.add_vertex(my_vertices[i])
graph.add_edge('A', 'B')
graph.add_edge('A', 'C')
graph.add_edge('A', 'D')
graph.add_edge('C', 'D')
graph.add_edge('C', 'G')
graph.add_edge('D', 'G')
graph.add_edge('D', 'H')
graph.add_edge('B', 'E')
graph.add_edge('B', 'F')
graph.add_edge('E', 'I')
edges: list = graph.minimum_spanning_tree("A")
print(edges)
print(graph.return_path("H"))
================================================
FILE: graphs/minimum-spanning-tree/breadth-first-search/queue.py
================================================
class Queue:
def __init__(self):
self.queue = []
def enqueue(self, item):
self.queue.insert(0, item)
def dequeue(self):
return self.queue.pop()
def size(self):
return len(self.queue)
def is_empty(self):
return self.queue == []
================================================
FILE: graphs/minimum-spanning-tree/kruskals-algorithm/graph.py
================================================
from typing import List, Set, Dict, Tuple
class Graph:
def __init__(self) -> None:
self.vertices:Set[str] = set()
self.roots:Dict[str, str] = dict()
self.sizes:Dict[str, int] = dict()
self.edges:List[Tuple[str, str, int]] = list()
self.mst:List[Tuple[str, str, int]] = list()
def add_vertex(self, label:str) -> None:
self.vertices.add(label)
self.roots[label] = label
self.sizes[label] = 1
def add_edge(self, label1:str, label2:str, weight:int) -> None:
if label1 not in self.vertices or label2 not in self.vertices:
raise Exception("Vertices must be added before connecting them")
self.edges.append((label1, label2, weight))
def kruskal(self) -> List[Tuple[str, str, int]]:
self.mst.clear()
self.edges.sort(key = lambda edge: edge[2])
for v1, v2, weight in self.edges:
root1:str = self._find_root(v1)
root2:str = self._find_root(v2)
if root1 != root2:
if self.sizes[root1] >= self.sizes[root2]:
self.roots[root2] = root1
self.sizes[root1] += self.sizes[root2]
else:
self.roots[root1] = root2
self.sizes[root2] += self.sizes[root1]
self.mst.append((v1, v2, weight))
return list(self.mst)
def _find_root(self, label:str) -> str:
if self.roots[label] != label:
self.roots[label] = self._find_root(self.roots[label])
return self.roots[label]
================================================
FILE: graphs/minimum-spanning-tree/kruskals-algorithm/main.py
================================================
from graph import Graph
g: Graph = Graph()
g.add_vertex('a')
g.add_vertex('b')
g.add_vertex('d')
g.add_vertex('c')
g.add_vertex('e')
g.add_vertex('f')
g.add_edge('a', 'f', 4)
g.add_edge('a', 'b', 23)
g.add_edge('b', 'd', 17)
g.add_edge('b', 'c', 3)
g.add_edge('c', 'd', 41)
g.add_edge('c', 'f', 2)
g.add_edge('f', 'e', 1)
print(g.kruskal())
================================================
FILE: graphs/minimum-spanning-tree/prims-algorithm/graph.py
================================================
from typing import Dict, List
from vertex import Vertex
from priorityqueue import PriorityQueue
class Graph:
def __init__(self) -> None:
self.vertices: Dict[str, Vertex] = dict()
self.adjacency_map: Dict[str, List[Vertex]] = dict()
self.prev:Dict[str, str] = dict()
def add_vertex(self, label:str, weight:int=float('inf')):
self.vertices[label] = Vertex(label)
self.adjacency_map[label] = []
self.prev[label] = None
def add_edge(self, label1:str, label2:str, weight:int):
self.adjacency_map[label1].append(Vertex(label2, weight))
self.adjacency_map[label2].append(Vertex(label1, weight))
def prims(self, label:str):
res:str = ''
v:Vertex = self.vertices[label]
v.weight = 0
pq:PriorityQueue = PriorityQueue()
for k in self.vertices:
vertex = self.vertices[k]
pq.insert(vertex)
while not pq.is_empty():
v = pq.delete_min()
print('Min is ', v.label)
if self.prev[v.label] is not None:
res += f'{self.prev[v.label]} -> {v.label}, '
for neighbour in self.adjacency_map[v.label]:
vertex:Vertex = self.vertices[neighbour.label]
if neighbour.weight < vertex.weight:
vertex.weight = neighbour.weight
self.prev[vertex.label] = v.label
pq.decrease_key(vertex.index)
print(res)
================================================
FILE: graphs/minimum-spanning-tree/prims-algorithm/main.py
================================================
from graph import Graph
graph: Graph = Graph()
graph.add_vertex("a")
graph.add_vertex("b")
graph.add_vertex("f")
graph.add_vertex("c")
graph.add_vertex("d")
graph.add_vertex("e")
graph.add_edge("a", "b", 4)
graph.add_edge("a", "f", 2)
graph.add_edge("b", "c", 6)
graph.add_edge("f", "b", 3)
graph.add_edge("f", "c", 1)
graph.add_edge("f", "e", 4)
graph.add_edge("c", "d", 3)
graph.add_edge("d", "e", 2)
graph.prims("a") # a -> f, f -> c, f -> b, c -> d, d -> e,
================================================
FILE: graphs/minimum-spanning-tree/prims-algorithm/priorityqueue.py
================================================
from typing import List
from vertex import Vertex
class PriorityQueue:
def __init__(self) -> None:
self.queue: List[Vertex] = [None]
self.pointer:int = 0
def is_empty(self) -> bool:
return self.pointer == 0
def insert(self, v:Vertex):
self.queue.append(v)
self.pointer += 1
v.index = self.pointer
self.perc_up(self.pointer)
def perc_up(self, index:int):
while index // 2 > 0:
if self.queue[index].weight < self.queue[index // 2].weight:
self.queue[index], self.queue[index // 2] = self.queue[index // 2], self.queue[index]
self.queue[index].index = index
self.queue[index // 2].index = index // 2
index = index // 2
def decrease_key(self, key:int):
self.perc_up(key)
def get_min(self) -> Vertex:
if self.is_empty():
raise Exception('Priority queue is empty')
return self.queue[1]
def delete_min(self) -> Vertex:
if self.is_empty():
raise Exception('Priority queue is empty')
v:Vertex = self.queue[1]
self.queue[1] = self.queue[self.pointer]
self.queue[1].index = 1
self.queue.pop()
self.pointer -= 1
self.perc_down(1)
return v
def perc_down(self, index:int):
while index * 2 <= self.pointer:
min_index:int = self.find_min_index(index)
if self.queue[index].weight > self.queue[min_index].weight:
self.queue[index], self.queue[min_index] = self.queue[min_index], self.queue[index]
self.queue[min_index].index = min_index
self.queue[index].index = index
index = min_index
def find_min_index(self, index:int) -> int:
if index * 2 + 1 > self.pointer:
return index * 2
else:
if self.queue[index * 2].weight <= self.queue[index * 2 + 1].weight:
return index * 2
else:
return index * 2 + 1
================================================
FILE: graphs/minimum-spanning-tree/prims-algorithm/vertex.py
================================================
class Vertex:
def __init__(self, label:str=None, weight:int=float('inf'), index:int=None) -> None:
self.label:str = label
self.weight:int = weight
self.index:int = index
================================================
FILE: graphs/topological-sorting/graph.py
================================================
class Graph:
def __init__(self):
self.vertices: list = []
self.adjacencyList: dict = {}
self.colors: dict = {}
self.previous: dict = {}
self.distance: dict = {}
self.time: int = 0
self.entry: dict = {}
self.exit: dict = {}
self.no_incoming_edges: dict = {} # to avoid looking through whole list
self.explored: list = []
def add_vertex(self, label: str):
self.vertices.append(label)
self.adjacencyList[label]: list = []
self.colors[label] = "white"
self.distance[label] = 0
self.previous[label] = None
self.no_incoming_edges[label] = label
def add_edge(self, label1: str, label2: str):
self.adjacencyList[label1].append(label2)
if label2 in self.no_incoming_edges:
del self.no_incoming_edges[label2] # remove vertex, it has incoming edge
def topsort(self):
# perform depth first search on vertices with no incoming edges
for label in self.no_incoming_edges:
self.dfs(label)
self.explored.reverse()
print(self.explored)
def dfs(self, start: str):
self.time += 1
self.entry[start] = self.time
self.colors[start] = "gray"
for neighbour in self.adjacencyList[start]:
if self.colors[neighbour] == "white":
self.previous[neighbour] = start
self.distance[neighbour] = self.distance[neighbour] + 1
self.dfs(neighbour)
self.time += 1
self.exit[start] = self.time
self.colors[start] = "black"
self.explored.append(start)
def show_path(self, label: str) -> str:
if self.previous[label] is None:
return label
else:
return self.show_path(self.previous[label]) + " -> " + label
================================================
FILE: graphs/topological-sorting/main.py
================================================
from graph import Graph
graph = Graph()
vertices = ["a", "b", "c", "d", "e", "f"]
for vertex in vertices:
graph.add_vertex(vertex)
graph.add_edge("a", "c")
graph.add_edge("c", "d")
graph.add_edge("c", "f")
graph.add_edge("b", "c")
graph.add_edge("b", "e")
graph.topsort()
================================================
FILE: graphs/union-find/number-of-connected-components/graph.py
================================================
from typing import List
def find_parent(i: int, components: List[int]) -> int:
while i != components[i]:
i = components[i]
return i
class Graph:
def number_of_connected_components(self, edges_matrix: List[List[int]]) -> int:
n: int = len(edges_matrix)
number_of_components: int = n
components: List[int] = [None] * n
for i in range(n):
components[i] = i
for i in range(n):
for j in range(n):
if edges_matrix[i][j] == 1:
parent_one: int = find_parent(i, components)
parent_two: int = find_parent(j, components)
if parent_one != parent_two:
components[parent_one] = parent_two
number_of_components -= 1
return number_of_components
================================================
FILE: graphs/union-find/union-find-path-compression/graph.py
================================================
from vertex import Vertex
class Graph:
def __init__(self):
self.vertices: dict = {}
self.edges: list = []
def add_vertex(self, label: str = None):
self.vertices[label] = Vertex(label)
def add_edge(self, label1: str, label2: str):
self.edges.append([label1, label2])
def union_find(self):
for edge in self.edges:
label_one: str = edge[0]
label_two: str = edge[1]
vertex_one = self.vertices[label_one]
vertex_two = self.vertices[label_two]
root_one: Vertex = self.find_root(vertex_one)
root_two: Vertex = self.find_root(vertex_two)
if root_one != root_two:
if root_one.rank > root_two.rank:
root_two.parent = root_one
root_one.rank = root_one.rank + 1
else:
root_one.parent = root_two
root_two.rank = root_two.rank + 1
def find_root(self, vertex: Vertex):
if vertex.parent != vertex:
vertex.parent = self.find_root(vertex.parent)
return vertex.parent
return vertex.parent
================================================
FILE: graphs/union-find/union-find-path-compression/main.py
================================================
from graph import Graph
from vertex import Vertex
g: Graph = Graph()
g.add_vertex('a')
g.add_vertex('b')
g.add_vertex('c')
g.add_vertex('d')
g.add_vertex('e')
g.add_vertex('f')
g.add_edge('a', 'b')
g.add_edge('c', 'd')
g.add_edge('d', 'e')
g.add_edge('c', 'f')
g.add_edge('f', 'b')
g.union_find()
for label in g.vertices:
vertex: Vertex = g.vertices[label]
print(f'{vertex.label} parent is {vertex.parent.label}, rank is {vertex.parent.rank}')
================================================
FILE: graphs/union-find/union-find-path-compression/vertex.py
================================================
class Vertex:
def __init__(self, label: str = None):
self.label = label
self.parent: 'Vertex' = self
self.rank: int = 0
================================================
FILE: hash-table/chaining.py
================================================
from typing import Any, List
class KeyValue:
def __init__(self, key: int, value: Any) -> None:
self.key: int = key
self.value: Any = value
class HashTable:
def __init__(self, capacity:int = 11) -> None:
self.capacity: int = capacity
self.length: int = 0
self.table: List[List[KeyValue]] = [None] * self.capacity
def put(self, key: int, value: Any) -> int:
index: int = self.hash(key)
if self.table[index] is None:
self.table[index] = [KeyValue(key, value)]
self.length += 1
else:
found: bool = False
i: int = 0
items: List[KeyValue] = self.table[index]
while i < len(items) and not found:
if items[i].key == key:
found = True
else:
i += 1
if found:
items[i].value = value
else:
items.append(KeyValue(key, value))
self.length += 1
def get(self, key: int) -> Any:
index: int = self.hash(key)
if self.table[index] is None:
return None
else:
found: bool = False
i: int = 0
items: List[KeyValue] = self.table[index]
while i < len(items) and not found:
if items[i].key == key:
found = True
else:
i += 1
if found:
return items[i].value
else:
return None
def contains(self, key: int) -> bool:
index: int = self.hash(key)
if self.table[index] is None:
return False
else:
found: bool = False
i: int = 0
items: List[KeyValue] = self.table[index]
while i < len(items) and not found:
if items[i].key == key:
found = True
else:
i += 1
if found:
return True
else:
return False
def delete(self, key: int) -> None:
index: int = self.hash(key)
if self.table[index] is None:
return None
else:
found: bool = False
i: int = 0
items: List[KeyValue] = self.table[index]
while i < len(items) and not found:
if items[i].key == key:
found = True
else:
i += 1
if not found:
return None
items.pop(i)
if len(items) == 0:
self.table[index] = None
return None
def hash(self, key: int) -> int:
return key % self.capacity
def size(self) -> int:
return self.length
ht: HashTable = HashTable()
ht.put(11, 'string 11')
ht.put(22, 'string 22')
ht.put(33, 'string 33')
ht.put(44, 'string 44')
ht.put(21, 'string 21')
ht.put(12, 'string 12')
print(ht.size())
print('Get 11', ht.get(11))
print('Get 33', ht.get(33))
print('Get 147', ht.get(147))
print('----------------------------------------')
print('Contains 22', ht.contains(22))
ht.delete(22)
print(ht.size())
print('Contains 22', ht.contains(22))
print('----------------------------------------')
print('Contains 77', ht.contains(77))
ht.put(44, 'string 144')
ht.put(77, 'string 77')
print(ht.size())
print('Contains 77', ht.contains(77))
================================================
FILE: hash-table/linear-probing.py
================================================
from typing import Any, List, Tuple
class HashTable:
def __init__(self, capacity:int = 11) -> None:
self.capacity:int = capacity
self.keys: List[int] = [None] * self.capacity
self.values: List[int] = [None] * self.capacity
self.length: int = 0
def put(self, key:int, value:Any):
index, contains = self.find(key)
if contains:
self.values[index] = value
return
hash:int = self.hash(key)
if self.keys[hash] == float('inf') or self.keys[hash] is None:
self.keys[hash] = key
self.values[hash] = value
self.length += 1
else:
new_hash:int = self.rehash(hash) % self.capacity
while self.keys[new_hash] is not None and self.keys[new_hash] != float('inf') and new_hash != hash:
new_hash = self.rehash(new_hash)
if self.keys[new_hash] == float('inf') or self.keys[new_hash] is None:
self.keys[new_hash] = key
self.values[new_hash] = value
self.length += 1
def contains(self, key:int) -> bool:
_, contains = self.find(key)
return contains
def get(self, key:int) -> Any:
index, contains = self.find(key)
if contains:
return self.values[index]
return None
def delete(self, key:int):
index, contains = self.find(key)
if not contains:
return
self.keys[index] = float('inf')
self.values[index] = None
self.length -= 1
def find(self, key:int) -> Tuple[int, bool]:
hash:int = self.hash(key)
if self.keys[hash] == key:
return (hash, True)
elif self.keys[hash] is None:
return (None, False)
else:
new_hash:int = self.rehash(hash) % self.capacity
while self.keys[new_hash] != key and self.keys[new_hash] is not None and new_hash != hash:
new_hash = self.rehash(new_hash)
if self.keys[new_hash] == key:
return (new_hash, True)
return (None, False)
def size(self) -> int:
return self.length
def hash(self, key:int) -> int:
return key % self.capacity
def rehash(self, old_hash:int) -> int:
return (old_hash + 1) % self.capacity
ht: HashTable = HashTable()
ht.put(11, 'string 11')
ht.put(22, 'string 22')
ht.put(33, 'string 33')
ht.put(44, 'string 44')
ht.put(21, 'string 21')
ht.put(12, 'string 12')
print(ht.keys)
print(ht.values)
print(ht.size())
print('Get 11', ht.get(11))
print('Get 22', ht.get(22))
print('Get 147', ht.get(147))
print('----------------------------------------')
print('Contains 22', ht.contains(22))
ht.delete(22)
print(ht.size())
print(ht.keys)
print(ht.values)
print('Contains 22', ht.contains(22))
print('----------------------------------------')
print('Contains 44', ht.contains(44))
print(ht.keys)
print(ht.values)
print('Contains 77', ht.contains(77))
ht.put(44, 'string 144')
ht.put(77, 'string 77')
print(ht.size())
print(ht.keys)
print(ht.values)
print('Contains 77', ht.contains(77))
print('Contains 44', ht.contains(44))
================================================
FILE: linked-lists/circular-doubly-linked-list/list.py
================================================
from node import Node
class List:
def __init__(self):
self.head: Node = None
self.tail: Node = None
def is_empty(self) -> bool:
return self.head is None
def print_all(self):
if self.is_empty():
return
tmp: Node = self.head
stopped: bool = False
while not stopped:
print(tmp.key, end=", ")
tmp = tmp.next
if tmp == self.head:
stopped = True
print("")
def number_of_elements(self) -> int:
if self.is_empty():
return 0
count: int = 0
tmp: Node = self.head
stopped: bool = False
while not stopped:
count += 1
tmp = tmp.next
if tmp == self.head:
stopped = True
return count
def add_to_head(self, key: int):
if self.is_empty():
self.head = self.tail = Node(key)
self.head.prev = self.tail
self.tail.next = self.head
else:
self.head = Node(key, self.tail, self.head)
self.head.next.prev = self.head
self.tail.next = self.head
def add_to_tail(self, key: int):
if self.is_empty():
self.head = self.tail = Node(key)
self.head.prev = self.tail
self.tail.next = self.head
else:
self.tail.next = Node(key, self.tail, self.head)
self.tail = self.tail.next
self.head.prev = self.tail
def delete_from_head(self) -> int:
if self.is_empty():
return None
else:
ret_node: Node = self.head
if self.head == self.tail:
self.head = self.tail = None
else:
self.head = self.head.next
self.head.prev = self.tail
self.tail.next = self.head
return ret_node.key
def delete_from_tail(self) -> int:
if self.is_empty():
return None
else:
ret_node: Node = self.tail
if self.head == self.tail:
self.head = self.tail = None
else:
self.tail = self.tail.prev
self.tail.next = self.head
self.head.prev = self.tail
return ret_node.key
def delete_nodes_with_value(self, key: int):
if self.is_empty():
return None
ret_value: int = None
tmp: Node = self.head
while tmp.next != self.head:
if tmp.next.key == key:
ret_value = tmp.next.key
tmp.next = tmp.next.next
tmp.next.prev = tmp
else:
tmp = tmp.next
self.tail = tmp
if self.head.key == key:
ret_value = self.delete_from_head()
return ret_value
def delete_on_index(self, index: int):
if self.is_empty():
return
end_index: int = self.number_of_elements() - 1
if index < 0 or index > end_index:
return
if index == 0:
self.delete_from_head()
elif index == end_index:
self.delete_from_tail()
else:
tmp: Node = self.head
count: int = 0
while count < index:
tmp = tmp.next
count += 1
tmp.prev.next = tmp.next
tmp.next.prev = tmp.prev
def insert_after(self, list_element: int, new_element: int):
if self.is_empty():
return
tmp: Node = self.head
stopped: bool = False
while not stopped:
if tmp.key == list_element:
if tmp == self.tail:
self.add_to_tail(new_element)
else:
new_node = Node(new_element, tmp, tmp.next)
tmp.next = new_node
new_node.next.prev = new_node
tmp = tmp.next
tmp = tmp.next
if tmp == self.head:
stopped = True
def insert_before(self, list_element: int, new_element: int):
if self.is_empty():
return
tmp: Node = self.head
stopped: bool = False
while not stopped:
if tmp.key == list_element:
if tmp == self.head:
self.add_to_head(new_element)
else:
new_node = Node(new_element, tmp.prev, tmp)
new_node.prev.next = new_node
tmp.prev = new_node
tmp = tmp.next
if tmp == self.head:
stopped = True
def sort(self):
swapped: bool = True
outer: Node = self.head
inner: Node = self.tail
while outer != self.tail:
inner = self.tail
while inner != outer:
if inner.key < inner.prev.key:
k = inner.key
inner.key = inner.prev.key
inner.prev.key = k
inner = inner.prev
outer = outer.next
================================================
FILE: linked-lists/circular-doubly-linked-list/node.py
================================================
class Node:
def __init__(self, key: int=None, prev=None, next=None):
self.key = key
self.prev = prev
self.next = next
================================================
FILE: linked-lists/circular-singly-linked-list/list.py
================================================
from node import Node
class List:
def __init__(self):
self.head: Node = None
self.tail: Node = None
def is_empty(self) -> bool:
return self.head is None
def print_all(self):
if self.is_empty():
return
tmp: Node = self.head
stopped: bool = False
while not stopped:
print(tmp.key, end=", ")
tmp = tmp.next
if tmp == self.head:
stopped = True
print("")
def number_of_elements(self) -> int:
if self.is_empty():
return 0
count: int = 0
tmp: Node = self.head
stopped: bool = False
while not stopped:
count += 1
tmp = tmp.next
if tmp == self.head:
stopped = True
return count
def add_to_head(self, key: int):
if self.is_empty():
self.head = self.tail = Node(key)
self.tail.next = self.head
else:
self.head = Node(key, self.head)
self.tail.next = self.head
def add_to_tail(self, key: int):
if self.is_empty():
self.head = self.tail = Node(key)
self.tail.next = self.head
else:
self.tail.next = Node(key, self.head)
self.tail = self.tail.next
def delete_from_head(self) -> int:
if self.is_empty():
return None
else:
ret_node: Node = self.head
if self.head == self.tail:
self.head = self.tail = None
else:
self.head = self.head.next
self.tail.next = self.head
return ret_node.key
def delete_from_tail(self) -> int:
if self.is_empty():
return None
else:
ret_node: Node = self.tail
if self.head == self.tail:
self.head = self.tail = None
else:
tmp: Node = self.head
while tmp.next != self.tail:
tmp = tmp.next
self.tail = tmp
tmp.next = self.head
return ret_node.key
def delete_nodes_with_value(self, key: int):
if self.is_empty():
return None
ret_value: int = None
tmp: Node = self.head
while tmp.next != self.head:
if tmp.next.key == key:
ret_value = tmp.next.key
tmp.next = tmp.next.next
else:
tmp = tmp.next
self.tail = tmp
if self.head.key == key:
ret_value = self.delete_from_head()
return ret_value
def delete_on_index(self, index: int):
if self.is_empty():
return
end_index: int = self.number_of_elements() - 1
if index < 0 or index > end_index:
return
if index == 0:
self.delete_from_head()
elif index == end_index:
self.delete_from_tail()
else:
prev: Node = None
tmp: Node = self.head
count: int = 0
while count < index:
prev = tmp
tmp = tmp.next
count += 1
prev.next = tmp.next
def insert_after(self, list_element: int, new_element: int):
if self.is_empty():
return
tmp: Node = self.head
stopped: bool = False
while not stopped:
if tmp.key == list_element:
if tmp == self.tail:
self.add_to_tail(new_element)
else:
tmp.next = Node(new_element, tmp.next)
tmp = tmp.next
tmp = tmp.next
if tmp == self.head:
stopped = True
def insert_before(self, list_element: int, new_element: int):
if self.is_empty():
return
prev: Node = None
tmp: Node = self.head
stopped: bool = False
while not stopped:
if tmp.key == list_element:
if tmp == self.head:
self.add_to_head(new_element)
else:
prev.next = Node(new_element, tmp)
prev = tmp
tmp = tmp.next
if tmp == self.head:
stopped = True
def sort(self):
swapped: bool = True
while swapped:
swapped = False
tmp: Node = self.head
while tmp != self.tail:
if tmp.key > tmp.next.key:
k = tmp.key
tmp.key = tmp.next.key
tmp.next.key = k
swapped = True
tmp = tmp.next
================================================
FILE: linked-lists/circular-singly-linked-list/node.py
================================================
class Node:
def __init__(self, key: int=None, next=None):
self.key = key
self.next = next
================================================
FILE: linked-lists/doubly-linked-list/list.py
================================================
from node import Node
class List:
def __init__(self):
self.head: Node = None
self.tail: Node = None
def is_empty(self) -> bool:
return self.head is None
def print_all(self):
tmp: Node = self.head
while tmp is not None:
print(tmp.key, end=", ")
tmp = tmp.next
print("")
def number_of_elements(self) -> int:
count: int = 0
tmp: Node = self.head
while tmp is not None:
count += 1
tmp = tmp.next
return count
def add_to_head(self, key: int):
if self.is_empty():
self.head = self.tail = Node(key)
else:
self.head = Node(key, None, self.head)
self.head.next.prev = self.head
def add_to_tail(self, key: int):
if self.is_empty():
self.head = self.tail = Node(key)
else:
self.tail.next = Node(key, self.tail)
self.tail = self.tail.next
def delete_from_head(self) -> int:
if self.is_empty():
return None
else:
ret_node: Node = self.head
if self.head == self.tail:
self.head = self.tail = None
else:
self.head = self.head.next
self.head.prev = None
return ret_node.key
def delete_from_tail(self) -> int:
if self.is_empty():
return None
else:
ret_node: Node = self.tail
if self.head == self.tail:
self.head = self.tail = None
else:
self.tail = self.tail.prev;
self.tail.next = None
return ret_node.key
def delete_nodes_with_value(self, key: int):
if self.is_empty():
return None
ret_value: int = None
tmp: Node = self.head
while tmp.next is not None:
if tmp.next.key == key:
ret_value = tmp.next.key
tmp.next = tmp.next.next
if tmp.next is not None:
tmp.next.prev = tmp
else:
tmp = tmp.next
self.tail = tmp
if self.head.key == key:
ret_value = self.delete_from_head()
return ret_value
def delete_on_index(self, index: int):
if self.is_empty():
return
end_index: int = self.number_of_elements() - 1
if index < 0 or index > end_index:
return
if index == 0:
self.delete_from_head()
elif index == end_index:
self.delete_from_tail()
else:
tmp: Node = self.head
count: int = 0
while count < index:
tmp = tmp.next
count += 1
tmp.prev.next = tmp.next
tmp.next.prev = tmp.prev
def insert_after(self, list_element: int, new_element: int):
tmp: Node = self.head
while tmp is not None:
if tmp.key == list_element:
if tmp == self.tail:
self.add_to_tail(new_element)
else:
new_node: Node = Node(new_element, tmp, tmp.next)
tmp.next = new_node
new_node.next.prev = new_node
tmp = tmp.next
tmp = tmp.next
def insert_before(self, list_element: int, new_element: int):
tmp: Node = self.head
while tmp is not None:
if tmp.key == list_element:
if tmp == self.head:
self.add_to_head(new_element)
else:
new_node: Node = Node(new_element, tmp.prev, tmp)
new_node.prev.next = new_node
tmp.prev = new_node
tmp = tmp.next
def sort(self):
swapped: bool = True
outer: Node = self.head
inner: Node = self.tail
while outer != self.tail:
inner = self.tail
while inner != outer:
if inner.key < inner.prev.key:
k = inner.key
inner.key = inner.prev.key
inner.prev.key = k
inner = inner.prev
outer = outer.next
================================================
FILE: linked-lists/doubly-linked-list/node.py
================================================
class Node:
def __init__(self, key: int=None, prev=None, next=None):
self.key = key
self.prev = prev
self.next = next
================================================
FILE: linked-lists/singly-linked-list/list.py
================================================
from node import Node
class List:
def __init__(self):
self.head: Node = None
self.tail: Node = None
def is_empty(self) -> bool:
return self.head is None
def print_all(self):
tmp: Node = self.head
while tmp is not None:
print(tmp.key, end=", ")
tmp = tmp.next
print("")
def number_of_elements(self) -> int:
count: int = 0
tmp: Node = self.head
while tmp is not None:
count += 1
tmp = tmp.next
return count
def add_to_head(self, key: int):
if self.is_empty():
self.head = self.tail = Node(key)
else:
self.head = Node(key, self.head)
def add_to_tail(self, key: int):
if self.is_empty():
self.head = self.tail = Node(key)
else:
self.tail.next = Node(key)
self.tail = self.tail.next
def delete_from_head(self) -> int:
if self.is_empty():
return None
else:
ret_node: Node = self.head
if self.head == self.tail:
self.head = self.tail = None
else:
self.head = self.head.next
return ret_node.key
def delete_from_tail(self) -> int:
if self.is_empty():
return None
else:
ret_node: Node = self.tail
if self.head == self.tail:
self.head = self.tail = None
else:
tmp: Node = self.head
while tmp.next != self.tail:
tmp = tmp.next
tmp.next = None
self.tail = tmp
return ret_node.key
def delete_nodes_with_value(self, key: int):
if self.is_empty():
return None
ret_value: int = None
tmp: Node = self.head
while tmp.next is not None:
if tmp.next.key == key:
ret_value = tmp.next.key
tmp.next = tmp.next.next
else:
tmp = tmp.next
self.tail = tmp
if self.head.key == key:
ret_value = self.delete_from_head()
return ret_value
def delete_on_index(self, index: int):
if self.is_empty():
return
end_index: int = self.number_of_elements() - 1
if index < 0 or index > end_index:
return
if index == 0:
self.delete_from_head()
elif index == end_index:
self.delete_from_tail()
else:
prev: Node = None
tmp: Node = self.head
count: int = 0
while count < index:
prev = tmp
tmp = tmp.next
count += 1
prev.next = tmp.next
def insert_after(self, list_element: int, new_element: int):
tmp: Node = self.head
while tmp is not None:
if tmp.key == list_element:
if tmp == self.tail:
self.add_to_tail(new_element)
else:
tmp.next = Node(new_element, tmp.next)
tmp = tmp.next
tmp = tmp.next
def insert_before(self, list_element: int, new_element: int):
prev: Node = None
tmp: Node = self.head
while tmp is not None:
if tmp.key == list_element:
if tmp == self.head:
self.add_to_head(new_element)
else:
prev.next = Node(new_element, tmp)
prev = tmp
tmp = tmp.next
def sort(self):
swapped: bool = True
while swapped:
swapped = False
tmp: Node = self.head
while tmp != self.tail:
if tmp.key > tmp.next.key:
k = tmp.key
tmp.key = tmp.next.key
tmp.next.key = k
swapped = True
tmp = tmp.next
================================================
FILE: linked-lists/singly-linked-list/node.py
================================================
class Node:
def __init__(self, key: int=None, next=None):
self.key = key
self.next = next
================================================
FILE: queue/circular-queue-fixed-size-array-impl.py
================================================
class Queue:
def __init__(self, length: int = 10):
self._length: int = length
self._queue: list = [None] * self._length
self._front = self._rear = -1
self._count: int = 0
def enqueue(self, item):
if self.is_full():
raise Exception("Queue is full")
self._rear = (self._rear + 1) % self._length
if self._front == -1:
self._front += 1
self._count += 1
self._queue[self._rear] = item
def dequeue(self):
if self.is_empty():
raise Exception("Queue is empty")
ret_value = self._queue[self._front]
if self._front == self._rear:
self._front = self._rear = -1
else:
self._front = (self._front + 1) % self._length
self._count -= 1
return ret_value
def peek(self):
if self.is_empty():
raise Exception("Queue is empty")
return self._queue[self._front]
def size(self) -> int:
return self._count
def is_empty(self) -> bool:
return self._front == -1
def is_full(self) -> bool:
return (self._rear + 1) % self._length == self._front
def hot_potato(namelist, number):
q = Queue(30)
for name in namelist:
q.enqueue(name)
while q.size() > 1:
for i in range(number):
q.enqueue(q.dequeue())
q.dequeue()
return q.dequeue()
print(hot_potato(["Bill", "David", "Susan", "Jane", "Kent", "Brad"], 7))
================================================
FILE: queue/queue-array-impl.py
================================================
class Queue:
def __init__(self):
self._queue = []
def enqueue(self, item):
self._queue.insert(0, item)
def dequeue(self):
if self.is_empty():
raise Exception('Queue is empty')
return self._queue.pop()
def peek(self):
if self.is_empty():
raise Exception('Queue is empty')
return self._queue[len(self._queue) - 1]
def size(self) -> int:
return len(self._queue)
def is_empty(self) -> bool:
return len(self._queue) == 0
def hot_potato(namelist, number):
q = Queue()
for name in namelist:
q.enqueue(name)
while q.size() > 1:
for i in range(number):
q.enqueue(q.dequeue())
q.dequeue()
return q.dequeue()
print(hot_potato(["Bill", "David", "Susan", "Jane", "Kent", "Brad"], 7))
================================================
FILE: queue/queue-fixed-size-array-impl.py
================================================
class Queue:
def __init__(self, length: int = 10):
self._length: int = length
self._queue: list = [None] * self._length
self._front = self._rear = -1
self._count: int = 0
def enqueue(self, item):
if self.is_full():
raise Exception("Queue is full")
self._rear += 1
if self._front == -1:
self._front += 1
self._count += 1
self._queue[self._rear] = item
def dequeue(self):
if self.is_empty():
raise Exception("Queue is empty")
ret_value = self._queue[self._front]
if self._front == self._rear:
self._front = self._rear = -1
else:
self._front += 1
self._count -= 1
return ret_value
def peek(self):
if self.is_empty():
raise Exception("Queue is empty")
return self._queue[self._front]
def size(self) -> int:
return self._count
def is_empty(self) -> bool:
return self._front == -1
def is_full(self) -> bool:
return self._rear == self._length - 1
def hot_potato(namelist, number):
q = Queue(300)
for name in namelist:
q.enqueue(name)
while q.size() > 1:
for i in range(number):
q.enqueue(q.dequeue())
q.dequeue()
return q.dequeue()
print(hot_potato(["Bill", "David", "Susan", "Jane", "Kent", "Brad"], 7))
================================================
FILE: queue/queue-linked-list-impl.py
================================================
class Node:
def __init__(self, key, next=None):
self.key = key
self.next = next
class Queue:
def __init__(self):
self._head = self._tail = None
self._count: int = 0
def enqueue(self, item):
if self.is_empty():
self._head = self._tail = Node(item)
else:
self._tail.next = Node(item)
self._tail = self._tail.next
self._count += 1
def dequeue(self):
if self.is_empty():
raise Exception("Queue is empty")
ret_value: Node = self._head
if self._head == self._tail:
self._head = self._tail = None
else:
self._head = self._head.next
self._count -= 1
return ret_value.key
def peek(self):
if self.is_empty():
raise Exception("Queue is empty")
return self._head.key
def size(self) -> int:
return self._count
def is_empty(self) -> bool:
return self._head is None
def hot_potato(namelist, number):
q: Queue = Queue()
for person in namelist:
q.enqueue(person)
while q.size() > 1:
for i in range(number):
q.enqueue(q.dequeue())
q.dequeue()
return q.dequeue()
print(hot_potato(["Bill", "David", "Susan", "Jane", "Kent", "Brad"], 7))
================================================
FILE: queue/queue-two-stacks-impl.py
================================================
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
class Queue:
def __init__(self):
self.input_stack: Stack = Stack()
self.output_stack: Stack = Stack()
def is_empty(self) -> bool:
return self.input_stack.is_empty()
def size(self) -> int:
return self.input_stack.size()
def enqueue(self, item):
self.input_stack.push(item)
def dequeue(self):
if self.is_empty():
raise Exception("Queue is empty")
while not self.input_stack.is_empty():
self.output_stack.push(self.input_stack.pop())
ret_value = self.output_stack.pop()
while not self.output_stack.is_empty():
self.input_stack.push(self.output_stack.pop())
return ret_value
def peek(self):
if self.is_empty():
raise Exception("Queue is empty")
while not self.input_stack.is_empty():
self.output_stack.push(self.input_stack.pop())
ret_value = self.input_stack.pop()
self.output_stack.push(ret_value)
while not self.output_stack.is_empty():
self.input_stack.push(self.output_stack.pop())
return ret_value
def hot_potato(people: list, num: int) -> str:
q: Queue = Queue()
for person in people:
q.enqueue(person)
while q.size() > 1:
for i in range(num):
q.enqueue(q.dequeue())
q.dequeue()
return q.dequeue()
print(hot_potato(["Bill", "David", "Susan", "Jane", "Kent", "Brad"], 7))
================================================
FILE: recursion/convert-number-iterative.py
================================================
from stack import Stack
def converter(num: int, base: int) -> str:
digits = "0123456789ABCDEF"
stack: Stack = Stack()
while num > 0:
stack.push(digits[num % base])
num = num // base
result: str = ""
while not stack.is_empty():
result += stack.pop()
return result
'''
digits = "0123456789ABCDEF"
def converter(num: int, base: int) -> str:
r:str = ''
while num > 0:
r = digits[num % base] + r
num = num // base
return r
'''
print(converter(1453, 16)) # 5AD
================================================
FILE: recursion/convert-number.py
================================================
def converter(num: int, base: int) -> str:
digits = "0123456789ABCDEF"
if num < base:
return digits[num]
else:
return converter(num // base, base) + digits[num % base]
print(converter(1453, 16)) # 5AD
================================================
FILE: recursion/factorial.py
================================================
def factorial_rec(n: int) -> int:
if n <= 1:
return 1
else:
return n * factorial_rec(n - 1)
def factorial_it(n: int) -> int:
if n <= 1:
return 1
result: int = 1
while n > 1:
result *= n
n -= 1
return result
================================================
FILE: recursion/fibonacci-iterative.py
================================================
def fibonacci(n: int) -> int:
if n <= 1:
return 0
elif n == 2:
return 1
prev: int = 0
curr: int = 1
for _ in range(n - 2):
prev, curr = curr, prev + curr
return curr
for i in range(6):
print(fibonacci(i))
================================================
FILE: recursion/fibonacci-memoization.py
================================================
nums: dict = {}
def fibonacci(n: int) -> int:
if n <= 1:
return 0
elif n == 2:
return 1
else:
if n in nums:
return nums[n]
nums[n] = fibonacci(n - 1) + fibonacci(n - 2)
return nums[n]
for i in range(6):
print(fibonacci(i))
================================================
FILE: recursion/fibonacci-recursive-worst-solution.py
================================================
def fibonacci(n: int) -> int:
if n <= 1:
return 0
elif n == 2:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
for i in range(6):
print(fibonacci(i))
================================================
FILE: recursion/fibonacci-recursive.py
================================================
def fibonacci(n: int) -> int:
def fibonacci_helper(num: int, prev: int = 0, curr: int = 1) -> int:
if num <= 1:
return prev
elif num == 2:
return curr
else:
return fibonacci_helper(num - 1, curr, prev + curr)
return fibonacci_helper(n)
for i in range(6):
print(fibonacci(i))
================================================
FILE: recursion/fibonacci-sum-iterative.py
================================================
def fibonaci(n: int):
if n == 1:
return 0
if n == 2:
return 1
prev: int = 0
curr: int = 1
acc: int = 1
for _ in range(n - 2):
prev,curr = curr, prev + curr
acc += curr
return acc
for i in range(6):
print(f'Fibonacci {i} is : {fibonacci(i)}')
================================================
FILE: recursion/fibonacci-sum-recursive.py
================================================
def fibonacci(n: int) -> int:
def fibonacci_helper(num: int, acc: int = 0, prev: int = 0, curr: int = 1):
if num <= 1:
return prev
elif num == 2:
return acc + curr
else:
return fibonacci_helper(num - 1, acc + curr, curr, prev + curr)
return fibonacci_helper(n)
for i in range(6):
print(fibonacci(i))
================================================
FILE: recursion/maze.py
================================================
from typing import List, Any
class Stack:
def __init__(self) -> None:
self.stack:List[Any] = list()
def is_empty(self) -> bool:
return len(self.stack) == 0
def size(self) -> int:
return len(self.stack)
def push(self, item:Any) -> None:
self.stack.append(item)
def peek(self) -> Any:
if self.is_empty():
raise Exception('Stack is empty')
return self.stack[len(self.stack) - 1]
def pop(self) -> Any:
if self.is_empty():
raise Exception('Stack is empty')
return self.stack.pop()
size: int = 5
matrix = [[0 for x in range(size)] for y in range(size)]
'''
0 - not visited
1 - visited
2 - obstacle
'''
# place maze obstacles
matrix[0][2] = 2
matrix[0][3] = 2
matrix[1][0] = 2
matrix[2][2] = 2
matrix[2][3] = 2
matrix[2][4] = 2
matrix[3][1] = 2
matrix[4][3] = 2
# starting position
matrix[0][0] = 1
stack = Stack()
stack.push([0, 0])
def path_finder(matrix:List[List[int]], stack:Stack) -> None:
_move(matrix, stack)
def _move(matrix:List[List[int]], stack:Stack) -> None:
if stack.is_empty():
print('Path not found')
else:
x, y = stack.peek()
if x == len(matrix) - 1 and y == len(matrix[x]) - 1:
print('Path found')
elif y < len(matrix[x]) - 1 and matrix[x][y + 1] == 0:
_add_coordinates_to_stack(matrix, stack, x, y + 1)
_move(matrix, stack)
elif y > 0 and matrix[x][y - 1] == 0:
_add_coordinates_to_stack(matrix, stack, x, y - 1)
_move(matrix, stack)
elif x > 0 and matrix[x - 1][y] == 0:
_add_coordinates_to_stack(matrix, stack, x - 1, y)
_move(matrix, stack)
elif x < len(matrix) - 1 and matrix[x + 1][y] == 0:
_add_coordinates_to_stack(matrix, stack, x + 1, y)
_move(matrix, stack)
else:
stack.pop()
_move(matrix, stack)
def _add_coordinates_to_stack(matrix:List[List[int]], stack:Stack, x:int, y:int) -> None:
matrix[x][y] = 1
stack.push([x, y])
if __name__ == "__main__":
path_finder(matrix, stack)
================================================
FILE: recursion/palindrome.py
================================================
def palindrome_checker(string: str) -> bool:
def palindrome_helper(s: str, start: int, end: int) -> bool:
if start >= end:
return True
else:
if s[start] == s[end]:
return palindrome_helper(s, start + 1, end - 1)
else:
return False
return palindrome_helper(string, 0, len(string) - 1)
str1: str = "kayak"
str2: str = "aibohphobia"
print(palindrome_checker(str1))
print(palindrome_checker(str2))
def palindrome_checker_iterative(string:str) -> bool:
is_palindrome: bool = True
start = 0
end = len(string) - 1
while start < end and is_palindrome:
if string[start] != string[end]:
is_palindrome = False
start += 1
end -= 1
return is_palindrome
print(palindrome_checker_iterative(str1))
print(palindrome_checker_iterative(str2))
def palindrome_checker_slicing(string: str) -> bool:
if len(string) <= 1:
return True
else:
if string[0] == string[-1]:
return palindrome_checker_slicing(string[1: -1])
else:
return False
print(palindrome_checker_slicing(str1))
print(palindrome_checker_slicing(str2))
================================================
FILE: recursion/reverse-linked-list-iterative-stack.py
================================================
from stack import Stack
class ListNode:
def __init__(self, payload = None, next: 'ListNode' = None) -> None:
self.payload = payload
self.next: 'ListNode' = next
def reverse_list(head: ListNode) -> ListNode:
if head is None or head.next is None:
return head
stack: Stack = Stack()
while head is not None:
stack.push(head)
head = head.next
dummy: ListNode = ListNode()
dummy_tmp = dummy
while not stack.is_empty():
dummy_tmp.next = stack.pop()
dummy_tmp = dummy_tmp.next
dummy_tmp.next = None
return dummy.next
================================================
FILE: recursion/reverse-linked-list-iterative.py
================================================
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reverse_list(head: ListNode) -> ListNode:
if head is None or head.next is None:
return head
stopped: bool = False
prev = head.next
head.next = None
while not stopped:
tmp: ListNode = prev.next
prev.next = head
head = prev
if tmp is not None:
prev = tmp
else:
stopped = True
return prev
================================================
FILE: recursion/reverse-linked-list.py
================================================
class ListNode:
def __init__(self, val: int = None, next = None):
self.val = val
self.next = next
def reverse_linked_list(node: ListNode) -> ListNode:
if node is None:
return None
elif node.next is None:
return node
else:
next_node: ListNode = node.next
node.next = None
rest: ListNode = reverse_linked_list(next_node)
next_node.next = node
return rest
================================================
FILE: recursion/reverse-list.py
================================================
nums: list = [1, 2, 3, 4, 5]
def reverse_rec(elements: list):
def reverse_list_helper(values: list, start: int, end: int):
if start < end:
values[start], values[end] = values[end], values[start]
reverse_list_helper(values, start + 1, end - 1)
reverse_list_helper(elements, 0, len(elements) - 1)
print(nums)
reverse_rec(nums)
print(nums)
def reverse_iterative(elements: list):
start: int = 0
end: int = len(elements) - 1
while start < end:
elements[start], elements[end] = elements[end], elements[start]
start += 1
end -= 1
reverse_iterative(nums)
print(nums)
================================================
FILE: recursion/reverse-string.py
================================================
string: str = "This string will be reversed"
def reverse_string(string: str) -> str:
def helper(s: str, end: int) -> str:
if end < 0:
return ""
else:
return s[end] + helper(s, end - 1)
return helper(string, len(string) - 1)
print(reverse_string(string))
def reverse_string_ex_one(string: str) -> str:
if len(string) == 0:
return ""
else:
return reverse_string_ex_one(string[1:]) + string[0]
print(reverse_string_ex_one(string))
def reverse_string_ex_two(string: str) -> str:
if len(string) == 0:
return ""
else:
return string[len(string) - 1] + reverse_string_ex_two(string[0: len(string) - 1])
print(reverse_string_ex_two(string))
================================================
FILE: recursion/stack.py
================================================
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
================================================
FILE: recursion/sum-numbers-binary-recursion.py
================================================
numbers: list = [1, 2, 3, 4, 5]
# O(n) time
def sum_numbers(nums: list) -> int:
def helper(elements: list, start: int, end: int) -> int:
if start > end:
return 0
else:
index: int = start + (end - start) // 2
return helper(elements, start, index - 1) + elements[index] + helper(elements, index + 1, end)
return helper(nums, 0, len(nums) - 1)
print(sum_numbers(numbers))
================================================
FILE: recursion/sum-numbers-pointer.py
================================================
numbers: list = [1, 2, 3, 4, 5]
# O(n) time
def sum_numbers(nums: list) -> int:
def helper(elements: list, end: int) -> int:
if end < 0:
return 0
else:
return elements[end] + helper(elements, end - 1)
return helper(nums, len(nums) - 1)
print(sum_numbers(numbers))
================================================
FILE: recursion/sum-numbers-slicing.py
================================================
numbers: list = [1, 2, 3, 4, 5]
# slicing is O(k), better is solution with pointer
def sum_numbers(nums: list) -> int:
if len(nums) == 0:
return 0
else:
return nums[0] + sum_numbers(nums[1:])
print(sum_numbers(numbers))
================================================
FILE: recursion/towers-of-hanoi.py
================================================
def print_move(start: str, end: str):
print("Moving from", start, "to", end)
def towers(number: int, start: str, spare: str, end: str):
if number == 1:
print_move(start, end)
else:
towers(number - 1, start, end, spare)
towers(1, start, spare, end)
towers(number - 1, spare, start, end)
towers(3, "start", "spare", "end")
================================================
FILE: searching/binary-search-iterative.py
================================================
def binary_search(nums: list, target: int) -> bool:
start: int = 0
end: int = len(nums) - 1
found: bool = False
while start <= end and not found:
midpoint: int = start + (end - start) // 2
if nums[midpoint] == target:
found = True
else:
if nums[midpoint] > target:
end = midpoint - 1
else:
start = midpoint + 1
return found
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42]
print(binary_search(testlist, 3))
print(binary_search(testlist, 13))
================================================
FILE: searching/binary-search-recursive-pointers.py
================================================
def binary_search(nums: list, target: int) -> bool:
def binary_search_helper(numbers: list, element, start: int, end: int) -> bool:
if start > end:
return False
else:
midpoint: int = start + (end - start) // 2
if nums[midpoint] == element:
return True
else:
if nums[midpoint] > element:
return binary_search_helper(numbers, element, start, midpoint - 1)
else:
return binary_search_helper(numbers, element, midpoint + 1, end)
return binary_search_helper(nums, target, 0, len(nums) - 1)
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42]
print(binary_search(testlist, 3))
print(binary_search(testlist, 13))
================================================
FILE: searching/binary-search-recursive.py
================================================
# slicing a list is O(k)
# better is recursive solution with pointers
def binary_search(nums: list, target: int) -> bool:
if len(nums) == 0:
return False
else:
midpoint: int = len(nums) // 2
if nums[midpoint] == target:
return True
else:
if nums[midpoint] > target:
return binary_search(nums[0: midpoint], target)
else:
return binary_search(nums[midpoint + 1:], target)
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42]
print(binary_search(testlist, 3))
print(binary_search(testlist, 13))
================================================
FILE: searching/sequential-search-ordered-list.py
================================================
def sequential_search(nums: list, target: int) -> bool:
found: bool = False
stopped: bool = False
i: int = 0
while i < len(nums) and not found and not stopped:
if nums[i] == target:
found = True
else:
if nums[i] > target:
stopped = True
else:
i += 1
return found
testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42]
print(sequential_search(testlist, 3))
print(sequential_search(testlist, 13))
================================================
FILE: searching/sequential-search-unordered-list.py
================================================
def sequential_search(nums: list, target: int) -> bool:
i: int = 0
found: bool = False
while i < len(nums) and not found:
if nums[i] == target:
found = True
else:
i += 1
return found
testlist = [1, 2, 32, 8, 17, 19, 42, 13, 0]
print(sequential_search(testlist, 3))
print(sequential_search(testlist, 13))
================================================
FILE: sorting/bubble-sort.py
================================================
array = [54, 26, 93, 17, 77, 31, 44, 55, 20]
def bubble_sort(nums: list):
for i in range(len(nums)):
for j in range(len(nums) - 1, i, -1):
if nums[j - 1] > nums[j]:
nums[j - 1], nums[j] = nums[j], nums[j - 1]
print(array)
bubble_sort(array)
print(array)
================================================
FILE: sorting/insertion-sort.py
================================================
array = [54, 26, 93, 17, 77, 31, 44, 55, 20]
def insertion_sort(nums: list):
for i in range(1, len(nums), +1):
curr: int = nums[i]
pos: int = i
while pos > 0 and nums[pos - 1] > curr:
nums[pos] = nums[pos - 1]
pos -= 1
nums[pos] = curr
print(array)
insertion_sort(array)
print(array)
================================================
FILE: sorting/merge-sort.py
================================================
array = [54, 26, 93, 17, 77, 31, 44, 55, 20]
def merge_sort(nums: list):
if len(nums) < 2:
return
midpoint: int = len(nums) // 2
left: list = nums[0:midpoint]
right: list = nums[midpoint:]
merge_sort(left)
merge_sort(right)
i = j = k = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
nums[k] = left[i]
i += 1
else:
nums[k] = right[j]
j += 1
k += 1
while i < len(left):
nums[k] = left[i]
i += 1
k += 1
while j < len(right):
nums[k] = right[j]
j += 1
k += 1
print(array)
merge_sort(array)
print(array)
================================================
FILE: sorting/quicksort-return-new-array.py
================================================
array = [54, 26, 93, 17, 77, 31, 44, 55, 20]
def quick_sort(nums: list) -> list:
if len(nums) < 2:
return nums
pivot_index: int = len(nums) // 2
pivot_value: int = nums[pivot_index]
left: list = []
right: list = []
for i in range(len(nums)):
if i != pivot_index:
if nums[i] < pivot_value:
left.append(nums[i])
else:
right.append(nums[i])
return quick_sort(left) + [pivot_value] + quick_sort(right)
print(array)
array_sorted: list = quick_sort(array)
print(array_sorted)
================================================
FILE: sorting/quicksort.py
================================================
array = [54, 26, 93, 17, 77, 31, 44, 55, 20]
def quick_sort(nums: list, i: int, j: int):
if i < j:
left: int = i
right: int = j
pointer: int = left
pivot_index: int = left + (right - left) // 2
pivot_value: int = nums[pivot_index]
while pointer <= right:
if nums[pointer] < pivot_value:
nums[left], nums[pointer] = nums[pointer], nums[left]
left += 1
pointer += 1
elif nums[pointer] > pivot_value:
nums[pointer], nums[right] = nums[right], nums[pointer]
right -= 1
else:
pointer += 1
quick_sort(nums, i, left)
if pointer > left:
quick_sort(nums, pointer, j)
else:
quick_sort(nums, pointer + 1, j)
print(array)
quick_sort(array, 0, len(array) - 1)
print(array)
================================================
FILE: sorting/selection-sort.py
================================================
array = [54, 26, 93, 17, 77, 31, 44, 55, 20]
def selection_sort(nums: list):
for i in range(0, len(nums), +1):
min_index: int = i
for j in range(i + 1, len(nums) - 1, +1):
if nums[j] < nums[min_index]:
min_index = j
if min_index != i:
nums[min_index], nums[i] = nums[i], nums[min_index]
print(array)
selection_sort(array)
print(array)
================================================
FILE: sorting/short-bubble.py
================================================
array = [54, 26, 93, 17, 77, 31, 44, 55, 20]
def short_bubble(nums: list):
swapped: bool = True
dec: int = 1
while swapped:
swapped = False
for i in range(len(nums) - dec):
if nums[i] > nums[i + 1]:
nums[i + 1], nums[i] = nums[i], nums[i + 1]
swapped = True
dec += 1
print(array)
short_bubble(array)
print(array)
================================================
FILE: stack/examples/balanced-brackets.py
================================================
from stack import Stack
def balanced_brackets(string: str) -> bool:
stack: Stack = Stack()
for character in string:
if character in "([{":
stack.push(character)
if character in ")]}":
if stack.is_empty():
return False
if "([{".index(stack.peek()) == ")]}".index(character):
stack.pop()
else:
return False
return stack.is_empty()
print(balanced_brackets('((()))')) # True
print(balanced_brackets('(()')) # False
print(balanced_brackets(']()')) # False
print(balanced_brackets('(])')) # False
================================================
FILE: stack/examples/number_converter.py
================================================
from stack import Stack
def base_converter(num, base) -> str:
digits = "0123456789ABCDEF"
stack: Stack = Stack()
while num > 0:
stack.push(digits[num % base])
num = num // base
result: str = ""
while not stack.is_empty():
result += stack.pop()
return result
print(base_converter(25, 8)) # 31
print(base_converter(256, 16)) # 100
print(base_converter(26, 26)) # 10
================================================
FILE: stack/examples/stack.py
================================================
class Stack:
def __init__(self):
self._stack: list = []
def is_empty(self) -> bool:
return len(self._stack) == 0
def push(self, item):
self._stack.append(item)
def pop(self):
if self.is_empty():
raise Exception("Stack is empty")
return self._stack.pop()
def peek(self):
if self.is_empty():
raise Exception("Stack is empty")
# return self._stack[-1] # python way
return self._stack[len(self._stack) - 1]
def size(self) -> int:
return len(self._stack)
================================================
FILE: stack/stack-array-impl-less-efficient.py
================================================
# this solution is less efficient because
# pop() from end of array is faster than pop(some_other_index)
# append(item) is faster than insert(some_other_index, item)
class Stack:
def __init__(self):
self._stack: list = []
def is_empty(self) -> bool:
return len(self._stack) == 0
def push(self, item):
self._stack.insert(0, item)
def pop(self):
if self.is_empty():
raise Exception("Stack is empty")
return self._stack.pop(0)
def peek(self):
if self.is_empty():
raise Exception("Stack is empty")
return self._stack[0]
def size(self) -> int:
return len(self._stack)
def reverse_string(s: str) -> str:
stack: Stack = Stack()
for character in s:
stack.push(character)
result: str = ""
while not stack.is_empty():
result += stack.pop()
return result
string: str = "This string will be reversed ..."
print(reverse_string(string)) # ... desrever eb lliw gnirts sihT
================================================
FILE: stack/stack-array-impl.py
================================================
class Stack:
def __init__(self):
self._stack: list = []
def is_empty(self) -> bool:
return len(self._stack) == 0
def push(self, item):
self._stack.append(item)
def pop(self):
if self.is_empty():
raise Exception("Stack is empty")
return self._stack.pop()
def peek(self):
if self.is_empty():
raise Exception("Stack is empty")
# return self._stack[-1] # python way
return self._stack[len(self._stack) - 1]
def size(self) -> int:
return len(self._stack)
def reverse_string(s: str) -> str:
stack: Stack = Stack()
for character in s:
stack.push(character)
result: str = ""
while not stack.is_empty():
result += stack.pop()
return result
string: str = "This string will be reversed ..."
print(reverse_string(string)) # ... desrever eb lliw gnirts sihT
================================================
FILE: stack/stack-fixed-size-array-impl.py
================================================
from typing import Any, List
class Stack:
def __init__(self, capacity: int = 1) -> None:
self.capacity: int = capacity
self.stack: List[Any] = [None] * self.capacity
self.pointer: int = -1
def size(self) -> int:
return self.pointer + 1
def is_empty(self) -> bool:
return self.pointer == -1
def is_full(self) -> bool:
return self.pointer == self.capacity - 1
def push(self, item:Any):
if self.is_full():
raise Exception('Stack is full')
self.pointer += 1
self.stack[self.pointer] = item
def pop(self) -> Any:
if self.is_empty():
raise Exception('Stack is empty')
item = self.stack[self.pointer]
self.pointer -= 1
return item
def peek(self) -> Any:
if self.is_empty():
raise Exception('Stack is empty')
return self.stack[self.pointer]
def reverse_string(s: str) -> str:
stack: Stack = Stack(len(s))
for character in s:
stack.push(character)
result: str = ""
while not stack.is_empty():
result += stack.pop()
return result
string: str = "This string will be reversed ..."
print(reverse_string(string)) # ... desrever eb lliw gnirts sihT
================================================
FILE: stack/stack-linked-list-impl.py
================================================
class Node:
def __init__(self, key=None, next=None):
self.key = key
self.next = next
class Stack:
def __init__(self):
self._head: Node = None
self._count: int = 0
def is_empty(self) -> bool:
return self._head is None
def push(self, item):
self._head = Node(item, self._head)
self._count += 1
def pop(self):
if self.is_empty():
raise Exception("Stack is empty")
ret_value = self._head.key
self._head = self._head.next
self._count -= 1
return ret_value
def peek(self):
if self.is_empty():
raise Exception("Stack is empty")
return self._head.key
def size(self) -> int:
return len(self._count)
def reverse_string(s: str) -> str:
stack: Stack = Stack()
for character in s:
stack.push(character)
result: str = ""
while not stack.is_empty():
result += stack.pop()
return result
string: str = "This string will be reversed ..."
print(reverse_string(string)) # ... desrever eb lliw gnirts sihT
================================================
FILE: stack/stack_two_queues.py
================================================
class Queue:
def __init__(self):
self._queue = []
def enqueue(self, item):
self._queue.insert(0, item)
def dequeue(self):
if self.is_empty():
raise Exception("Queue is empty")
return self._queue.pop()
def size(self) -> int:
return len(self._queue)
def is_empty(self) -> bool:
return len(self._queue) == 0
def peek(self) -> int:
if self.is_empty():
raise Exception("Queue is empty")
return self._queue[len(self._queue) - 1]
class MyStack:
def __init__(self):
self.input = Queue()
self.output = Queue()
def empty(self) -> bool:
return self.input.is_empty()
def push(self, item):
self.input.enqueue(item)
def pop(self):
if self.empty():
raise Exception("Stack is empty")
while self.input.size() > 1 :
self.output.enqueue(self.input.dequeue())
val = self.input.dequeue()
while not self.output.is_empty():
self.input.enqueue(self.output.dequeue())
return val
def top(self):
if self.empty():
raise Exception("Stack is empty")
while self.input.size() > 1 :
self.output.enqueue(self.input.dequeue())
val = self.input.peek()
self.output.enqueue(self.input.dequeue())
while not self.output.is_empty():
self.input.enqueue(self.output.dequeue())
return val
def size(self) -> int:
return self.input.size()
================================================
FILE: stack_two_queues.py
================================================
from typing import Any, List
class Queue:
def __init__(self) -> None:
self.queue:List[Any] = []
def size(self) -> int:
return len(self.queue)
def is_empty(self) -> bool:
return len(self.queue) == 0
def enqueue(self, item:Any) -> None:
self.queue.insert(0, item)
def dequeue(self) -> Any:
if self.is_empty():
raise Exception('Queue is empty')
return self.queue.pop()
class Stack:
def __init__(self):
self.input: Queue = Queue()
self.output:Queue = Queue()
def push(self, x: Any) -> None:
self.input.enqueue(x)
def pop(self) -> Any:
if self.input.is_empty():
raise Exception('Queue is empty')
while self.input.size() > 1:
self.output.enqueue(self.input.dequeue())
item:Any = self.input.dequeue()
while not self.output.is_empty():
self.input.enqueue(self.output.dequeue())
return item
def peek(self) -> Any:
if self.input.is_empty():
raise Exception('Queue is empty')
while self.input.size() > 1:
self.output.enqueue(self.input.dequeue())
item:Any = self.input.dequeue()
self.output.enqueue(item)
while not self.output.is_empty():
self.input.enqueue(self.output.dequeue())
return item
def is_empty(self) -> bool:
return self.input.is_empty()
================================================
FILE: substring-search/brute_force.py
================================================
# O(m * n)
# m - length of the text
# n - length of pattern
def search(text: str, pattern: str) -> int:
t:int = 0
last_index: int = len(text) - len(pattern) + 1
while t <= len(text) - len(pattern):
p:int = 0
while p < len(pattern):
if text[t + p] != pattern[p]:
break
else:
p += 1
if p == len(pattern):
return t
t += 1
return -1
================================================
FILE: trees/avl-tree.py
================================================
class TreeNode:
def __init__(self, key=None, value=None, parent=None, left=None, right=None,
left_subtree_height: int = 0, right_subtree_height: int = 0, balance_factor: int = 0):
self.key = key
self.value = value
self.parent = parent
self.left = left
self.right = right
self.left_subtree_height: int = left_subtree_height
self.right_subtree_height: int = right_subtree_height
self.balance_factor : int = balance_factor
def has_left_child(self) -> bool:
return self.left is not None
def has_right_child(self) -> bool:
return self.right is not None
def has_both_children(self) -> bool:
return self.has_left_child() and self.has_right_child()
def is_leaf(self) -> bool:
return not self.has_left_child() and not self.has_right_child()
def is_root(self) -> bool:
return self.parent is None
def has_parent(self) -> bool:
return self.parent is not None
def is_left_child(self) -> bool:
return self.parent.left == self
def is_right_child(self) -> bool:
return self.parent.right == self
def find_min(self):
if self is None:
return None
if self.has_left_child():
return self.left.find_min()
else:
return self
def find_max(self):
if self is None:
return None
node = self
while node.right is not None:
node = node.right
return node
class AVLTree:
def __init__(self):
self.root: TreeNode = None
self.elements: int = 0
def size(self) -> int:
return self.elements
def is_empty(self) -> bool:
return self.root is None
def put(self, key, value):
if self.is_empty():
self.root = TreeNode(key, value)
self.elements += 1
else:
self._put(self.root, key, value)
def _put(self, root: TreeNode, key, value):
if root.key == key:
root.value = value
elif key < root.key:
if root.has_left_child():
self._put(root.left, key, value)
else:
root.left = TreeNode(key, value, root)
self.elements += 1
self._update_balance_factor(root)
else:
if root.has_right_child():
self._put(root.right, key, value)
else:
root.right = TreeNode(key, value, root)
self.elements += 1
self._update_balance_factor(root)
def get(self, key) -> TreeNode:
if self.is_empty():
return None
else:
return self._get(self.root, key)
def _get(self, root: TreeNode, key) -> TreeNode:
if root.key == key:
return root
elif key < root.key:
if root.has_left_child():
return self._get(root.left, key)
else:
return None
else:
if root.has_right_child():
return self._get(root.right, key)
else:
return None
def contains(self, key) -> bool:
if self.is_empty():
return None
found: bool = False
node: TreeNode = self.root
while node is not None and not found:
if node.key == key:
found = True
elif key < node.key:
node = node.left
else:
node = node.right
return found
def delete(self, key):
node_to_delete: TreeNode = self.get(key)
if node_to_delete is None:
return
if node_to_delete.is_root():
if node_to_delete.is_leaf():
self.root = None
self.elements -= 1
elif node_to_delete.has_both_children():
max_node: TreeNode = node_to_delete.left.find_max()
tmp_key = max_node.key
tmp_value = max_node.value
self.delete(tmp_key)
# keep pointer to that node, not root, root might change
node_to_delete.key = tmp_key
node_to_delete.value = tmp_value
else:
if node_to_delete.has_left_child():
self.root = node_to_delete.left
else:
self.root = node_to_delete.right
self.root.parent = None
self.elements -= 1
else:
parent: TreeNode = None
if node_to_delete.is_leaf():
parent = node_to_delete.parent
if node_to_delete.is_left_child():
node_to_delete.parent.left = None
else:
node_to_delete.parent.right = None
self.elements -= 1
elif node_to_delete.has_both_children():
max_node: TreeNode = node_to_delete.left.find_max()
tmp_key = max_node.key
tmp_value = max_node.value
self.delete(tmp_key)
node_to_delete.key = tmp_key
node_to_delete.value = tmp_value
elif node_to_delete.has_left_child():
parent = node_to_delete.parent
self.elements -= 1
if node_to_delete.is_left_child():
node_to_delete.parent.left = node_to_delete.left
else:
node_to_delete.parent.right = node_to_delete.left
node_to_delete.left.parent = node_to_delete.parent
else:
parent = node_to_delete.parent
self.elements -= 1
if node_to_delete.is_left_child():
node_to_delete.parent.left = node_to_delete.right
else:
node_to_delete.parent.right = node_to_delete.right
node_to_delete.right.parent = node_to_delete.parent
if parent is not None:
self._update_balance_factor(parent)
def find_min(self) -> TreeNode:
if self.is_empty():
return None
node: TreeNode = self.root
while node.left is not None:
node = node.left
return node
def find_max(self) -> TreeNode:
if self.is_empty():
return None
node: TreeNode = self.root
while node.right is not None:
node = node.right
return node
def _update_balance_factor(self, root: TreeNode):
old_balance_factor: int = root.balance_factor
if root.has_left_child():
root.left_subtree_height = max(root.left.left_subtree_height, root.left.right_subtree_height) + 1
else:
root.left_subtree_height = 0
if root.has_right_child():
root.right_subtree_height = max(root.right.left_subtree_height, root.right.right_subtree_height) + 1
else:
root.right_subtree_height = 0
root.balance_factor = root.left_subtree_height - root.right_subtree_height
if root.balance_factor < -1 or root.balance_factor > 1:
self._rebalance(root)
return
if root.balance_factor != old_balance_factor and root.has_parent():
self._update(root.parent)
def _rebalance(self, root: TreeNode):
if root.balance_factor < 0:
if root.right.balance_factor > 0:
self._rotate_right(root.right)
else:
self._rotate_left(root)
else:
if root.left.balance_factor < 0:
self._rotate_left(root.left)
else:
self._rotate_right(root)
def _rotate_left(self, root: TreeNode):
old_root: TreeNode = root
new_root: TreeNode = old_root.right
old_root.right = new_root.left
if new_root.has_left_child():
new_root.left.parent = old_root
new_root.parent = old_root.parent
if old_root.has_parent():
if old_root.is_left_child():
old_root.parent.left = new_root
else:
old_root.parent.right = new_root
else:
self.root = new_root
old_root.parent = new_root
new_root.left = old_root
self._update_balance_factor(old_root)
def _rotate_right(self, root: TreeNode):
old_root: TreeNode = root
new_root: TreeNode = old_root.left
old_root.left = new_root.right
if new_root.has_right_child():
new_root.right.parent = old_root
new_root.parent = old_root.parent
if old_root.has_parent():
if old_root.is_left_child():
old_root.parent.left = new_root
else:
old_root.parent.right = new_root
else:
self.root = new_root
old_root.parent = new_root
new_root.right = old_root
self._update_balance_factor(old_root)
================================================
FILE: trees/binary-heap.py
================================================
# min heap
class BinaryHeap:
def __init__(self):
self.pointer: int = 0
self.heap: list = [None]
def is_empty(self) -> bool:
return self.pointer == 0
def insert(self, item):
self.heap.append(item)
self.pointer += 1
self.perc_up(self.pointer)
def perc_up(self, index: int):
while index // 2 > 0:
if self.heap[index] < self.heap[index // 2]:
self.heap[index], self.heap[index // 2] = self.heap[index // 2], self.heap[index]
index = index // 2
def get_min(self):
if self.is_empty():
raise Exception("Heap is empty")
return self.heap[1]
def delete_min(self):
if self.is_empty():
raise Exception("Heap is empty")
ret_value: int = self.heap[1]
self.heap[1] = self.heap[self.pointer]
self.heap.pop()
self.pointer -= 1
self.perc_down(1)
return ret_value
def perc_down(self, index: int):
while index * 2 <= self.pointer:
swap_index: int = self.find_swap_index(index)
if self.heap[swap_index] < self.heap[index]:
self.heap[swap_index], self.heap[index] = self.heap[index], self.heap[swap_index]
index = swap_index
def find_swap_index(self, index: int) -> int:
if index * 2 + 1 > self.pointer:
return index * 2
else:
if self.heap[index * 2] <= self.heap[index * 2 + 1]:
return index * 2
else:
return index * 2 + 1
def build_heap(self, nums: list):
for n in nums:
self.insert(n)
h: BinaryHeap = BinaryHeap()
h.insert(10)
h.insert(1)
h.insert(3)
print(h.heap) # [None, 1, 10, 3]
print(h.get_min()) # 1
while not h.is_empty():
print(h.delete_min())
================================================
FILE: trees/binary-search-tree.py
================================================
class TreeNode:
def __init__(self, key=None, value=None, parent=None, left=None, right=None):
self.key = key
self.value = value
self.parent = parent
self.left = left
self.right = right
def has_left_child(self) -> bool:
return self.left is not None
def has_right_child(self) -> bool:
return self.right is not None
def has_both_children(self) -> bool:
return self.has_left_child() and self.has_right_child()
def is_leaf(self) -> bool:
return not self.has_left_child() and not self.has_right_child()
def is_root(self) -> bool:
return self.parent is None
def has_parent(self) -> bool:
return self.parent is not None
def is_left_child(self) -> bool:
if self.parent is None:
return False
return self.parent.left == self
def is_right_child(self) -> bool:
if self.parent is None:
return False
return self.parent.right == self
def find_min(self):
if self is None:
return None
if self.has_left_child():
return self.left.find_min()
else:
return self
def find_max(self):
if self is None:
return None
node = self
while node.right is not None:
node = node.right
return node
class BinarySearchTree:
def __init__(self):
self.root: TreeNode = None
self.elements: int = 0
def size(self) -> int:
return self.elements
def is_empty(self) -> bool:
return self.root is None
def put(self, key, value):
if self.is_empty():
self.root = TreeNode(key, value)
self.elements += 1
else:
self._put(self.root, key, value)
def _put(self, root: TreeNode, key, value):
if root.key == key:
root.value = value
elif key < root.key:
if root.has_left_child():
self._put(root.left, key, value)
else:
root.left = TreeNode(key, value, root)
self.elements += 1
else:
if root.has_right_child():
self._put(root.right, key, value)
else:
root.right = TreeNode(key, value, root)
self.elements += 1
def get(self, key) -> TreeNode:
if self.is_empty():
return None
else:
return self._get(self.root, key)
def _get(self, root: TreeNode, key) -> TreeNode:
if root.key == key:
return root
elif key < root.key:
if root.has_left_child():
return self._get(root.left, key)
else:
return None
else:
if root.has_right_child():
return self._get(root.right, key)
else:
return None
def contains(self, key) -> bool:
if self.is_empty():
return False
found: bool = False
node: TreeNode = self.root
while node is not None and not found:
if node.key == key:
found = True
elif key < node.key:
node = node.left
else:
node = node.right
return found
def delete(self, key):
node_to_delete: TreeNode = self.get(key)
if node_to_delete is None:
return
if node_to_delete.is_root():
if node_to_delete.is_leaf():
self.root = None
self.elements -= 1
elif node_to_delete.has_both_children():
max_node: TreeNode = node_to_delete.left.find_max()
tmp_key = max_node.key
tmp_value = max_node.value
self.delete(tmp_key)
node_to_delete.key = tmp_key
node_to_delete.value = tmp_value
else:
if node_to_delete.has_left_child():
self.root = node_to_delete.left
else:
self.root = node_to_delete.right
self.root.parent = None
self.elements -= 1
else:
if node_to_delete.is_leaf():
if node_to_delete.is_left_child():
node_to_delete.parent.left = None
else:
node_to_delete.parent.right = None
self.elements -= 1
elif node_to_delete.has_both_children():
max_node: TreeNode = node_to_delete.left.find_max()
tmp_key = max_node.key
tmp_value = max_node.value
self.delete(tmp_key)
node_to_delete.key = tmp_key
node_to_delete.value = tmp_value
elif node_to_delete.has_left_child():
self.elements -= 1
if node_to_delete.is_left_child():
node_to_delete.parent.left = node_to_delete.left
else:
node_to_delete.parent.right = node_to_delete.left
node_to_delete.left.parent = node_to_delete.parent
else:
self.elements -= 1
if node_to_delete.is_left_child():
node_to_delete.parent.left = node_to_delete.right
else:
node_to_delete.parent.right = node_to_delete.right
node_to_delete.right.parent = node_to_delete.parent
def find_min(self) -> TreeNode:
if self.is_empty():
return None
node: TreeNode = self.root
while node.left is not None:
node = node.left
return node
def find_max(self) -> TreeNode:
if self.is_empty():
return None
node: TreeNode = self.root
while node.right is not None:
node = node.right
return node
================================================
FILE: trees/class-representation.py
================================================
class TreeNode:
def __init__(self, key=None, left=None, right=None):
self.key = key
self.left = left
self.right = right
def insert_root_value(self, key=None):
self.key = key
def insert_left(self, key=None):
self.left = TreeNode(key, self.left)
def insert_right(self, key=None):
self.right = TreeNode(key, None, self.right)
def get_root_value(self):
return self.key
def get_left_child(self):
return self.left
def get_right_child(self):
return self.right
# Write a function build_tree that returns a tree
# using the list of lists functions that look like this :
# a
# / \
# b c
# \ / \
# d e f
def build_tree() -> TreeNode:
tree: TreeNode = TreeNode('a')
tree.insert_right('f')
tree.insert_right('c')
tree.get_right_child().insert_left('e')
tree.insert_left('b')
tree.get_left_child().insert_right('d')
return tree
binary_tree: TreeNode = build_tree()
def print_tree(tree: TreeNode):
if tree is not None:
print_tree(tree.get_left_child())
print(tree.key, end=", ")
print_tree(tree.get_right_child())
print_tree(binary_tree)
# ['a',
# ['b',
# [],
# ['d', [], []]],
# ['c',
# ['e', [], []],
# ['f', [], []]
# ]
# ]
================================================
FILE: trees/list-representation.py
================================================
def create_tree(root=None) -> list:
return [None, [], []]
def insert_root(tree: list, root=None):
tree[0] = root
def insert_left(tree: list, root=None):
left_child: list = tree.pop(1)
tree.insert(1, [root, left_child, []])
def insert_right(tree: list, root=None):
right_child: list = tree.pop(2)
tree.insert(2, [root, [], right_child])
def get_root(tree: list):
return tree[0]
def get_left_child(tree: list) -> list:
return tree[1]
def get_right_child(tree: list) -> list:
return tree[2]
# Write a function build_tree that returns a tree
# using the list of lists functions that look like this :
# a
# / \
# b c
# \ / \
# d e f
def build_tree() -> list:
tree: list = create_tree()
insert_root(tree, 'a')
insert_right(tree, 'f')
insert_right(tree, 'c')
insert_left(get_right_child(tree), 'e')
insert_left(tree, 'b')
insert_right(get_left_child(tree), 'd')
return tree
binary_tree: list = build_tree()
print(binary_tree)
# ['a',
# ['b',
# [],
# ['d', [], []]],
# ['c',
# ['e', [], []],
# ['f', [], []]
# ]
# ]
================================================
FILE: trees/parse-tree.py
================================================
from stack import Stack
import operator
import re
class TreeNode:
def __init__(self, key=None, left=None, right=None):
self.key = key
self.left = left
self.right = right
def insert_root_value(self, key=None):
self.key = key
def insert_left(self, key=None):
self.left = TreeNode(key, self.left)
def insert_right(self, key=None):
self.right = TreeNode(key, None, self.right)
def get_root_value(self):
return self.key
def get_left_child(self):
return self.left
def get_right_child(self):
return self.right
opers = {'+':operator.add, '-':operator.sub, '*':operator.mul, '/':operator.truediv}
pattern = re.compile("[0-9]")
string = "( ( 10 + 5 ) * 3 )"
def tree_parser(s: str) -> TreeNode:
arr: list = s.split()
stack: Stack = Stack()
node: TreeNode = TreeNode()
current_node: TreeNode = node
stack.push(node)
for e in arr:
if e == "(":
current_node.insert_left()
stack.push(current_node)
current_node = current_node.get_left_child()
elif e in "+-*/":
current_node.insert_root_value(e)
current_node.insert_right()
stack.push(current_node)
current_node = current_node.get_right_child()
elif pattern.match(e):
current_node.insert_root_value(int(e))
current_node = stack.pop()
elif e == ")":
current_node = stack.pop()
else:
raise Exception()
return node
tree_node: TreeNode = tree_parser(string)
def evaluate(node: TreeNode) -> int:
if node.get_left_child() is not None and node.get_right_child() is not None:
f = opers[node.get_root_value()]
return f(evaluate(node.get_left_child()), evaluate(node.get_right_child()))
else:
return node.get_root_value()
print(evaluate(tree_node)) # 45
================================================
FILE: trees/stack.py
================================================
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
================================================
FILE: trees/tree-traversal/functions.py
================================================
from treenode import TreeNode
node: TreeNode = TreeNode('a')
node.insert_left('b')
node.insert_left('c')
node.get_left_child().insert_left('f')
node.insert_right('k')
node.insert_right('j')
print("\nInorder")
node.inorder()
print("\nPreorder")
node.preorder()
print("\nPostorder")
node.postorder()
# functions for tree traversal
def inorder(tree: TreeNode):
if tree is not None:
inorder(tree.left)
print(tree.key, end=", ")
inorder(tree.right)
def preorder(tree: TreeNode):
if tree is not None:
print(tree.key, end=", ")
preorder(tree.left)
preorder(tree.right)
def postorder(tree: TreeNode):
if tree is not None:
postorder(tree.left)
postorder(tree.right)
print(tree.key, end=", ")
print("\nInorder")
inorder(node)
print("\nPreorder")
preorder(node)
print("\nPostorder")
postorder(node)
================================================
FILE: trees/tree-traversal/inorder-traversal-example.py
================================================
from stack import Stack
import operator
import re
from treenode import TreeNode
opers = {'+':operator.add, '-':operator.sub, '*':operator.mul, '/':operator.truediv}
pattern = re.compile("[0-9]")
string = "( ( 10 + 5 ) * 3 )"
def tree_parser(s: str) -> TreeNode:
arr: list = s.split()
stack: Stack = Stack()
node: TreeNode = TreeNode()
current_node: TreeNode = node
stack.push(node)
for e in arr:
if e == "(":
current_node.insert_left()
stack.push(current_node)
current_node = current_node.get_left_child()
elif e in "+-*/":
current_node.insert_root_value(e)
current_node.insert_right()
stack.push(current_node)
current_node = current_node.get_right_child()
elif pattern.match(e):
current_node.insert_root_value(int(e))
current_node = stack.pop()
elif e == ")":
current_node = stack.pop()
else:
raise Exception()
return node
tree_node: TreeNode = tree_parser(string)
def inorder(node: TreeNode) -> str:
ret_value: str = ""
if node.get_left_child() is not None:
ret_value += "(" + inorder(node.get_left_child())
ret_value += str(node.get_root_value())
if node.get_right_child() is not None:
ret_value += inorder(node.get_right_child()) + ")"
return ret_value
print(inorder(tree_node)) # ((10+5)*3)
================================================
FILE: trees/tree-traversal/postorder-traversal-example.py
================================================
from stack import Stack
import operator
import re
from treenode import TreeNode
opers = {'+':operator.add, '-':operator.sub, '*':operator.mul, '/':operator.truediv}
pattern = re.compile("[0-9]")
string = "( ( 10 + 5 ) * 3 )"
def tree_parser(s: str) -> TreeNode:
arr: list = s.split()
stack: Stack = Stack()
node: TreeNode = TreeNode()
current_node: TreeNode = node
stack.push(node)
for e in arr:
if e == "(":
current_node.insert_left()
stack.push(current_node)
current_node = current_node.get_left_child()
elif e in "+-*/":
current_node.insert_root_value(e)
current_node.insert_right()
stack.push(current_node)
current_node = current_node.get_right_child()
elif pattern.match(e):
current_node.insert_root_value(int(e))
current_node = stack.pop()
elif e == ")":
current_node = stack.pop()
else:
raise Exception()
return node
tree_node: TreeNode = tree_parser(string)
def postorder(node: TreeNode) -> str:
if node is None:
return None
left = postorder(node.get_left_child())
right = postorder(node.get_right_child())
if left is not None and right is not None:
f = opers[node.get_root_value()]
return f(left, right)
else:
return node.get_root_value()
print(postorder(tree_node)) # 45
================================================
FILE: trees/tree-traversal/preorder-traversal-example.py
================================================
from stack import Stack
import operator
import re
from treenode import TreeNode
opers = {'+':operator.add, '-':operator.sub, '*':operator.mul, '/':operator.truediv}
pattern = re.compile("[0-9]")
string = "( ( 10 + 5 ) * 3 )"
def tree_parser(s: str) -> TreeNode:
arr: list = s.split()
stack: Stack = Stack()
node: TreeNode = TreeNode()
current_node: TreeNode = node
stack.push(node)
for e in arr:
if e == "(":
current_node.insert_left()
stack.push(current_node)
current_node = current_node.get_left_child()
elif e in "+-*/":
current_node.insert_root_value(e)
current_node.insert_right()
stack.push(current_node)
current_node = current_node.get_right_child()
elif pattern.match(e):
current_node.insert_root_value(int(e))
current_node = stack.pop()
elif e == ")":
current_node = stack.pop()
else:
raise Exception()
return node
tree_node: TreeNode = tree_parser(string)
def preorder(node: TreeNode, space: int = 0):
if node is not None:
print(" " * space, node.key)
preorder(node.get_left_child(), space + 2)
preorder(node.get_right_child(), space + 2)
preorder(tree_node)
================================================
FILE: trees/tree-traversal/stack.py
================================================
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
================================================
FILE: trees/tree-traversal/treenode.py
================================================
class TreeNode:
def __init__(self, key=None, left=None, right=None):
self.key = key
self.left = left
self.right = right
def insert_root_value(self, key=None):
self.key = key
def insert_left(self, key=None):
self.left = TreeNode(key, self.left)
def insert_right(self, key=None):
self.right = TreeNode(key, None, self.right)
def get_root_value(self):
return self.key
def get_left_child(self):
return self.left
def get_right_child(self):
return self.right
def inorder(self):
if self.get_left_child() is not None:
self.get_left_child().inorder()
print(self.key, end=", ")
if self.get_right_child() is not None:
self.get_right_child().inorder()
def preorder(self):
print(self.key, end=", ")
if self.get_left_child() is not None:
self.get_left_child().preorder()
if self.get_right_child() is not None:
self.get_right_child().preorder()
def postorder(self):
if self.get_left_child() is not None:
self.get_left_child().postorder()
if self.get_right_child() is not None:
self.get_right_child().postorder()
print(self.key, end=", ")
================================================
FILE: trie/trie.py
================================================
class TrieNode:
def __init__(self, key, parent = None, children: dict = {}):
self.key = key
self.parent = parent
self.children:dict = {}
self.endchar: bool = False
class Trie:
def __init__(self):
self.root: TrieNode = TrieNode(None)
def insert(self, string: str):
current: TrieNode = self.root
for character in string:
if character not in current.children:
current.children[character] = TrieNode(character, current)
current = current.children[character]
current.endchar = True
def contains(self, string: str)->bool:
current: TrieNode = self.root
for character in string:
if character not in current.children:
current = None
break
current = current.children[character]
if current is None:
return False
return current.endchar
def delete(self, string: str):
current: TrieNode = self.root
for character in string:
if character not in current.children:
current = None
break
current = current.children[character]
if current is None:
return
current.endchar = False
parent: TrieNode = current.parent
while parent is not None and not current.endchar and len(current.children) == 0:
del(parent.children[current.key])
current = parent
parent = current.parent
def prefix(self, prefix: str)->list:
current: TrieNode = self.root
for character in prefix:
if character not in current.children:
current = None
break
current = current.children[character]
if current is None:
return
words: list = []
self.helper(current, words, prefix)
return words
def helper(self, node: TrieNode, words: list, currentWord: str):
if node is None:
return
if node.endchar:
words.append(currentWord)
for key in node.children:
self.helper(node.children[key], words, currentWord + key)
def allWords(self)->list:
words: list = []
self.helper(self.root, words, "")
return words
def count(self)->int:
return self.countHelper(self.root)
def countHelper(self, node: TrieNode)->int:
if node is None:
return 0
sum: int = 0
if node.endchar:
sum += 1
for character in node.children:
sum += self.countHelper(node.children[character])
return sum
trie = Trie()
trie.insert("javascript")
trie.insert("java")
trie.insert("scala")
trie.insert("scale")
trie.insert("scalable")
trie.insert("perl")
print("Contains 'javascript' : ", trie.contains("javascript"))
print("Contains 'java' : ", trie.contains("java"))
print("Contains 'ruby' : ", trie.contains("ruby"))
#trie.delete("java")
trie.delete("javascript")
print("Contains 'javascript' : ", trie.contains("javascript"))
print("Contains 'java' : ", trie.contains("java"))
print("Contains 'ruby' : ", trie.contains("ruby"))
print(trie.prefix("scal")) # ['scala', 'scalable', 'scale']
print(trie.prefix("java")) # ['java']
print("All words", trie.allWords()) # All words ['java', 'scala', 'scalable', 'scale', 'perl']
print("Count : ", trie.count())
gitextract_x7v3a_w5/
├── .gitignore
├── LICENSE
├── README.md
├── analysis/
│ ├── anagrams-linear-solution.py
│ ├── anagrams-loglinear-solution.py
│ ├── anagrams-quadratic-solution.py
│ ├── time-iterative-approach.py
│ └── time-noniterative-approach.py
├── deque/
│ ├── circular-deque.py
│ ├── deque.py
│ └── deque_linked_list_impl.py
├── graphs/
│ ├── bellman-ford/
│ │ └── graph.py
│ ├── bellman-ford-negative-weight-cycle/
│ │ └── graph.py
│ ├── breadth-first-search/
│ │ ├── graph.py
│ │ ├── main.py
│ │ └── queue.py
│ ├── cycle-detection/
│ │ ├── Cycle.md
│ │ ├── cycle-directed-graph/
│ │ │ ├── graph.py
│ │ │ └── main.py
│ │ └── cycle-undirected-graph/
│ │ ├── graph.py
│ │ └── main.py
│ ├── depth-first-search/
│ │ ├── depth-first-search/
│ │ │ ├── graph.py
│ │ │ ├── main.py
│ │ │ └── stack.py
│ │ └── depth-first-search-recursive/
│ │ ├── graph.py
│ │ └── main.py
│ ├── dijkstra/
│ │ ├── adjacency-list-impl/
│ │ │ ├── main.py
│ │ │ └── vertex.py
│ │ ├── matrix-impl/
│ │ │ ├── graph.py
│ │ │ ├── main.py
│ │ │ └── vertex.py
│ │ └── priority-queue-impl-adjacency-map/
│ │ ├── graph.py
│ │ ├── main.py
│ │ ├── priorityqueue.py
│ │ └── vertex.py
│ ├── is-graph-bipartite/
│ │ ├── graph.py
│ │ ├── main.py
│ │ └── queue.py
│ ├── kosarajus-algorithm/
│ │ ├── graph.py
│ │ ├── main.py
│ │ └── stack.py
│ ├── minimum-spanning-tree/
│ │ ├── breadth-first-search/
│ │ │ ├── graph.py
│ │ │ ├── main.py
│ │ │ └── queue.py
│ │ ├── kruskals-algorithm/
│ │ │ ├── graph.py
│ │ │ └── main.py
│ │ └── prims-algorithm/
│ │ ├── graph.py
│ │ ├── main.py
│ │ ├── priorityqueue.py
│ │ └── vertex.py
│ ├── topological-sorting/
│ │ ├── graph.py
│ │ └── main.py
│ └── union-find/
│ ├── number-of-connected-components/
│ │ └── graph.py
│ └── union-find-path-compression/
│ ├── graph.py
│ ├── main.py
│ └── vertex.py
├── hash-table/
│ ├── chaining.py
│ └── linear-probing.py
├── linked-lists/
│ ├── circular-doubly-linked-list/
│ │ ├── list.py
│ │ └── node.py
│ ├── circular-singly-linked-list/
│ │ ├── list.py
│ │ └── node.py
│ ├── doubly-linked-list/
│ │ ├── list.py
│ │ └── node.py
│ └── singly-linked-list/
│ ├── list.py
│ └── node.py
├── queue/
│ ├── circular-queue-fixed-size-array-impl.py
│ ├── queue-array-impl.py
│ ├── queue-fixed-size-array-impl.py
│ ├── queue-linked-list-impl.py
│ └── queue-two-stacks-impl.py
├── recursion/
│ ├── convert-number-iterative.py
│ ├── convert-number.py
│ ├── factorial.py
│ ├── fibonacci-iterative.py
│ ├── fibonacci-memoization.py
│ ├── fibonacci-recursive-worst-solution.py
│ ├── fibonacci-recursive.py
│ ├── fibonacci-sum-iterative.py
│ ├── fibonacci-sum-recursive.py
│ ├── maze.py
│ ├── palindrome.py
│ ├── reverse-linked-list-iterative-stack.py
│ ├── reverse-linked-list-iterative.py
│ ├── reverse-linked-list.py
│ ├── reverse-list.py
│ ├── reverse-string.py
│ ├── stack.py
│ ├── sum-numbers-binary-recursion.py
│ ├── sum-numbers-pointer.py
│ ├── sum-numbers-slicing.py
│ └── towers-of-hanoi.py
├── searching/
│ ├── binary-search-iterative.py
│ ├── binary-search-recursive-pointers.py
│ ├── binary-search-recursive.py
│ ├── sequential-search-ordered-list.py
│ └── sequential-search-unordered-list.py
├── sorting/
│ ├── bubble-sort.py
│ ├── insertion-sort.py
│ ├── merge-sort.py
│ ├── quicksort-return-new-array.py
│ ├── quicksort.py
│ ├── selection-sort.py
│ └── short-bubble.py
├── stack/
│ ├── examples/
│ │ ├── balanced-brackets.py
│ │ ├── number_converter.py
│ │ └── stack.py
│ ├── stack-array-impl-less-efficient.py
│ ├── stack-array-impl.py
│ ├── stack-fixed-size-array-impl.py
│ ├── stack-linked-list-impl.py
│ └── stack_two_queues.py
├── stack_two_queues.py
├── substring-search/
│ └── brute_force.py
├── trees/
│ ├── avl-tree.py
│ ├── binary-heap.py
│ ├── binary-search-tree.py
│ ├── class-representation.py
│ ├── list-representation.py
│ ├── parse-tree.py
│ ├── stack.py
│ └── tree-traversal/
│ ├── functions.py
│ ├── inorder-traversal-example.py
│ ├── postorder-traversal-example.py
│ ├── preorder-traversal-example.py
│ ├── stack.py
│ └── treenode.py
└── trie/
└── trie.py
SYMBOL INDEX (611 symbols across 110 files)
FILE: analysis/anagrams-linear-solution.py
function anagrams (line 3) | def anagrams(string1: str, string2: str) -> bool:
function count_characters (line 23) | def count_characters(string: str, arr: list):
FILE: analysis/anagrams-loglinear-solution.py
function anagrams (line 3) | def anagrams(string1: str, string2: str) -> bool:
FILE: analysis/anagrams-quadratic-solution.py
function anagrams (line 3) | def anagrams(string1: str, string2: str) -> bool:
FILE: analysis/time-iterative-approach.py
function sum_nums (line 4) | def sum_nums(n: int) -> int:
FILE: analysis/time-noniterative-approach.py
function sum_nums (line 4) | def sum_nums(n: int) -> int:
FILE: deque/circular-deque.py
class Deque (line 5) | class Deque:
method __init__ (line 7) | def __init__(self, capacity: int = 10) -> None:
method is_empty (line 14) | def is_empty(self) -> bool:
method is_full (line 17) | def is_full(self) -> bool:
method size (line 20) | def size(self) -> int:
method add_front (line 23) | def add_front(self, item: Any):
method add_rear (line 35) | def add_rear(self, item: Any):
method remove_front (line 45) | def remove_front(self) -> Any:
method remove_rear (line 56) | def remove_rear(self) -> Any:
method get_front (line 69) | def get_front(self) -> Any:
method get_rear (line 74) | def get_rear(self) -> Any:
function is_palindrome (line 80) | def is_palindrome(string:str='') -> bool:
FILE: deque/deque.py
class Deque (line 5) | class Deque:
method __init__ (line 7) | def __init__(self) -> None:
method is_empty (line 10) | def is_empty(self) -> bool:
method size (line 13) | def size(self) -> int:
method add_front (line 16) | def add_front(self, item: Any):
method add_rear (line 19) | def add_rear(self, item: Any):
method remove_front (line 22) | def remove_front(self) -> Any:
method remove_rear (line 27) | def remove_rear(self) -> Any:
function is_palindrome (line 34) | def is_palindrome(string:str='') -> bool:
FILE: deque/deque_linked_list_impl.py
class ListNode (line 6) | class ListNode:
method __init__ (line 8) | def __init__(self, key:Any = None, prev:'ListNode' = None, next:'ListN...
class Deque (line 14) | class Deque:
method __init__ (line 16) | def __init__(self):
method size (line 22) | def size(self) -> int:
method is_empty (line 26) | def is_empty(self) -> bool:
method add_front (line 30) | def add_front(self, e:Any) -> None:
method add_rear (line 39) | def add_rear(self, e:Any) -> None:
method remove_front (line 48) | def remove_front(self) -> Any:
method remove_rear (line 61) | def remove_rear(self) -> Any:
method get_front (line 74) | def get_front(self) -> Any:
method remove_rear (line 80) | def remove_rear(self) -> Any:
FILE: graphs/bellman-ford-negative-weight-cycle/graph.py
class Graph (line 10) | class Graph:
method __init__ (line 11) | def __init__(self):
method add_vertex (line 17) | def add_vertex(self, label: str):
method add_edge (line 22) | def add_edge(self, label1: str, label2: str, weight: int):
method bellman_ford (line 25) | def bellman_ford(self, source: str):
method print_distances (line 58) | def print_distances(self, source: str):
FILE: graphs/bellman-ford/graph.py
class Graph (line 10) | class Graph:
method __init__ (line 13) | def __init__(self) -> None:
method add_vertex (line 20) | def add_vertex(self, label:str) -> None:
method add_edge (line 26) | def add_edge(self, v1:str, v2:str, distance:int) -> None:
method bellman_ford (line 30) | def bellman_ford(self, label:str) -> None:
method _print_paths (line 50) | def _print_paths(self, label:str) -> None:
method _return_path (line 60) | def _return_path(self, label:str) -> str:
FILE: graphs/breadth-first-search/graph.py
class Graph (line 4) | class Graph:
method __init__ (line 5) | def __init__(self):
method add_vertex (line 12) | def add_vertex(self, label: str):
method add_edge (line 19) | def add_edge(self, label1: str, label2: str):
method bfs (line 23) | def bfs(self, label: str):
method return_path (line 37) | def return_path(self, label: str) -> str:
FILE: graphs/breadth-first-search/queue.py
class Queue (line 1) | class Queue:
method __init__ (line 2) | def __init__(self):
method enqueue (line 5) | def enqueue(self, item):
method dequeue (line 8) | def dequeue(self):
method size (line 11) | def size(self):
method is_empty (line 14) | def is_empty(self):
FILE: graphs/cycle-detection/cycle-directed-graph/graph.py
class Graph (line 2) | class Graph:
method __init__ (line 3) | def __init__(self):
method add_vertex (line 13) | def add_vertex(self, label: str):
method add_edge (line 20) | def add_edge(self, label1: str, label2: str):
method dfs (line 23) | def dfs(self, label: str):
method return_path (line 38) | def return_path(self, label: str) -> str:
FILE: graphs/cycle-detection/cycle-undirected-graph/graph.py
class Graph (line 2) | class Graph:
method __init__ (line 3) | def __init__(self):
method add_vertex (line 13) | def add_vertex(self, label: str):
method add_edge (line 20) | def add_edge(self, label1: str, label2: str):
method dfs (line 24) | def dfs(self, label: str):
method return_path (line 39) | def return_path(self, label: str) -> str:
FILE: graphs/depth-first-search/depth-first-search-recursive/graph.py
class Graph (line 2) | class Graph:
method __init__ (line 3) | def __init__(self):
method add_vertex (line 13) | def add_vertex(self, label: str):
method add_edge (line 20) | def add_edge(self, label1: str, label2: str):
method dfs (line 24) | def dfs(self, label: str):
method return_path (line 37) | def return_path(self, label: str) -> str:
FILE: graphs/depth-first-search/depth-first-search/graph.py
class Graph (line 4) | class Graph:
method __init__ (line 5) | def __init__(self):
method add_vertex (line 15) | def add_vertex(self, label: str):
method add_edge (line 22) | def add_edge(self, label1: str, label2: str):
method dfs (line 26) | def dfs(self, label: str):
method return_path (line 48) | def return_path(self, label: str) -> str:
method find_unvisited_neighbour (line 54) | def find_unvisited_neighbour(self, tmp) -> str:
FILE: graphs/depth-first-search/depth-first-search/stack.py
class Stack (line 1) | class Stack:
method __init__ (line 2) | def __init__(self):
method is_empty (line 5) | def is_empty(self):
method push (line 8) | def push(self, item):
method pop (line 11) | def pop(self):
method peek (line 14) | def peek(self):
method size (line 17) | def size(self):
FILE: graphs/dijkstra/adjacency-list-impl/main.py
class Graph (line 7) | class Graph:
method __init__ (line 9) | def __init__(self, capacity :int =10):
method add_vertex (line 18) | def add_vertex(self, label :str, weight :int = float('inf')) -> None:
method add_edge (line 25) | def add_edge(self, label1 :str, label2 :str, weight :int) -> None:
method dijkstra (line 30) | def dijkstra(self, label :str) -> None:
method show_path (line 44) | def show_path(self, label :str) -> str:
method _find_cheapest_vertex (line 50) | def _find_cheapest_vertex(self) -> Vertex:
FILE: graphs/dijkstra/adjacency-list-impl/vertex.py
class Vertex (line 3) | class Vertex:
method __init__ (line 5) | def __init__(self, label :str, weight :int = float('inf')):
FILE: graphs/dijkstra/matrix-impl/graph.py
class Graph (line 4) | class Graph:
method __init__ (line 5) | def __init__(self, size: int = 10):
method add_vertex (line 14) | def add_vertex(self, label: str):
method add_edge (line 24) | def add_edge(self, label1: str, label2: str, weight: int):
method dijkstra (line 29) | def dijkstra(self, label: str):
method return_path (line 43) | def return_path(self, label: str) -> str:
method find_minimum_weight_vertex (line 49) | def find_minimum_weight_vertex(self):
FILE: graphs/dijkstra/matrix-impl/vertex.py
class Vertex (line 1) | class Vertex:
method __init__ (line 2) | def __init__(self, label: str = None, weight: int = float("inf"), ind...
FILE: graphs/dijkstra/priority-queue-impl-adjacency-map/graph.py
class Graph (line 5) | class Graph:
method __init__ (line 6) | def __init__(self):
method add_vertex (line 11) | def add_vertex(self, label: str):
method add_edge (line 17) | def add_edge(self, label1: str, label2: str, weight: int):
method dijkstra (line 20) | def dijkstra(self, label: str):
method show_path (line 34) | def show_path(self, label: str) -> str:
FILE: graphs/dijkstra/priority-queue-impl-adjacency-map/priorityqueue.py
class PriorityQueue (line 4) | class PriorityQueue:
method __init__ (line 5) | def __init__(self):
method is_empty (line 9) | def is_empty(self) -> bool:
method insert (line 12) | def insert(self, vertex: Vertex):
method _perc_up (line 18) | def _perc_up(self, pointer: int):
method decrease_key (line 26) | def decrease_key(self, pointer: int):
method delete_min (line 29) | def delete_min(self) -> Vertex:
method _perc_down (line 40) | def _perc_down(self, pointer: int):
method _find_swap_index (line 49) | def _find_swap_index(self, pointer: int) -> int:
FILE: graphs/dijkstra/priority-queue-impl-adjacency-map/vertex.py
class Vertex (line 1) | class Vertex:
method __init__ (line 2) | def __init__(self, label: str = None, weight: int = float("inf"), key:...
FILE: graphs/is-graph-bipartite/graph.py
class Graph (line 4) | class Graph:
method __init__ (line 5) | def __init__(self):
method add_vertex (line 10) | def add_vertex(self, label: str = None):
method add_edge (line 15) | def add_edge(self, label1: str = None, label2: str = None):
method bipartite_check (line 19) | def bipartite_check(self) -> bool:
FILE: graphs/is-graph-bipartite/queue.py
class Queue (line 1) | class Queue:
method __init__ (line 2) | def __init__(self):
method is_empty (line 5) | def is_empty(self) -> bool:
method enqueue (line 8) | def enqueue(self, vertex: str):
method dequeue (line 11) | def dequeue(self):
FILE: graphs/kosarajus-algorithm/graph.py
class Graph (line 7) | class Graph:
method __init__ (line 10) | def __init__(self) -> None:
method add_vertex (line 18) | def add_vertex(self, label:str) -> None:
method add_edge (line 24) | def add_edge(self, label1:str, label2:str) -> None:
method kosaraju (line 31) | def kosaraju(self) -> List[List[str]]:
method _dfs (line 53) | def _dfs(self, label:str) -> None:
method _dfs_reversed (line 63) | def _dfs_reversed(self, v:str, connected:List[str]) -> None:
FILE: graphs/kosarajus-algorithm/stack.py
class Stack (line 1) | class Stack:
method __init__ (line 2) | def __init__(self):
method is_empty (line 5) | def is_empty(self) -> bool:
method push (line 8) | def push(self, item):
method pop (line 11) | def pop(self):
method peek (line 16) | def peek(self):
method size (line 22) | def size(self) -> int:
FILE: graphs/minimum-spanning-tree/breadth-first-search/graph.py
class Graph (line 4) | class Graph:
method __init__ (line 5) | def __init__(self):
method add_vertex (line 12) | def add_vertex(self, label: str):
method add_edge (line 19) | def add_edge(self, label1: str, label2: str):
method minimum_spanning_tree (line 23) | def minimum_spanning_tree(self, label: str) -> list: # this is breadt...
method return_path (line 40) | def return_path(self, label: str) -> str:
FILE: graphs/minimum-spanning-tree/breadth-first-search/queue.py
class Queue (line 1) | class Queue:
method __init__ (line 2) | def __init__(self):
method enqueue (line 5) | def enqueue(self, item):
method dequeue (line 8) | def dequeue(self):
method size (line 11) | def size(self):
method is_empty (line 14) | def is_empty(self):
FILE: graphs/minimum-spanning-tree/kruskals-algorithm/graph.py
class Graph (line 4) | class Graph:
method __init__ (line 7) | def __init__(self) -> None:
method add_vertex (line 15) | def add_vertex(self, label:str) -> None:
method add_edge (line 21) | def add_edge(self, label1:str, label2:str, weight:int) -> None:
method kruskal (line 27) | def kruskal(self) -> List[Tuple[str, str, int]]:
method _find_root (line 47) | def _find_root(self, label:str) -> str:
FILE: graphs/minimum-spanning-tree/prims-algorithm/graph.py
class Graph (line 7) | class Graph:
method __init__ (line 9) | def __init__(self) -> None:
method add_vertex (line 15) | def add_vertex(self, label:str, weight:int=float('inf')):
method add_edge (line 21) | def add_edge(self, label1:str, label2:str, weight:int):
method prims (line 26) | def prims(self, label:str):
FILE: graphs/minimum-spanning-tree/prims-algorithm/priorityqueue.py
class PriorityQueue (line 6) | class PriorityQueue:
method __init__ (line 9) | def __init__(self) -> None:
method is_empty (line 14) | def is_empty(self) -> bool:
method insert (line 18) | def insert(self, v:Vertex):
method perc_up (line 25) | def perc_up(self, index:int):
method decrease_key (line 34) | def decrease_key(self, key:int):
method get_min (line 38) | def get_min(self) -> Vertex:
method delete_min (line 44) | def delete_min(self) -> Vertex:
method perc_down (line 56) | def perc_down(self, index:int):
method find_min_index (line 67) | def find_min_index(self, index:int) -> int:
FILE: graphs/minimum-spanning-tree/prims-algorithm/vertex.py
class Vertex (line 1) | class Vertex:
method __init__ (line 3) | def __init__(self, label:str=None, weight:int=float('inf'), index:int=...
FILE: graphs/topological-sorting/graph.py
class Graph (line 1) | class Graph:
method __init__ (line 2) | def __init__(self):
method add_vertex (line 14) | def add_vertex(self, label: str):
method add_edge (line 22) | def add_edge(self, label1: str, label2: str):
method topsort (line 27) | def topsort(self):
method dfs (line 34) | def dfs(self, start: str):
method show_path (line 48) | def show_path(self, label: str) -> str:
FILE: graphs/union-find/number-of-connected-components/graph.py
function find_parent (line 3) | def find_parent(i: int, components: List[int]) -> int:
class Graph (line 10) | class Graph:
method number_of_connected_components (line 11) | def number_of_connected_components(self, edges_matrix: List[List[int]]...
FILE: graphs/union-find/union-find-path-compression/graph.py
class Graph (line 4) | class Graph:
method __init__ (line 6) | def __init__(self):
method add_vertex (line 10) | def add_vertex(self, label: str = None):
method add_edge (line 13) | def add_edge(self, label1: str, label2: str):
method union_find (line 16) | def union_find(self):
method find_root (line 35) | def find_root(self, vertex: Vertex):
FILE: graphs/union-find/union-find-path-compression/vertex.py
class Vertex (line 1) | class Vertex:
method __init__ (line 3) | def __init__(self, label: str = None):
FILE: hash-table/chaining.py
class KeyValue (line 5) | class KeyValue:
method __init__ (line 7) | def __init__(self, key: int, value: Any) -> None:
class HashTable (line 12) | class HashTable:
method __init__ (line 15) | def __init__(self, capacity:int = 11) -> None:
method put (line 21) | def put(self, key: int, value: Any) -> int:
method get (line 42) | def get(self, key: int) -> Any:
method contains (line 61) | def contains(self, key: int) -> bool:
method delete (line 80) | def delete(self, key: int) -> None:
method hash (line 102) | def hash(self, key: int) -> int:
method size (line 106) | def size(self) -> int:
FILE: hash-table/linear-probing.py
class HashTable (line 6) | class HashTable:
method __init__ (line 8) | def __init__(self, capacity:int = 11) -> None:
method put (line 15) | def put(self, key:int, value:Any):
method contains (line 35) | def contains(self, key:int) -> bool:
method get (line 40) | def get(self, key:int) -> Any:
method delete (line 47) | def delete(self, key:int):
method find (line 56) | def find(self, key:int) -> Tuple[int, bool]:
method size (line 72) | def size(self) -> int:
method hash (line 75) | def hash(self, key:int) -> int:
method rehash (line 79) | def rehash(self, old_hash:int) -> int:
FILE: linked-lists/circular-doubly-linked-list/list.py
class List (line 4) | class List:
method __init__ (line 5) | def __init__(self):
method is_empty (line 9) | def is_empty(self) -> bool:
method print_all (line 12) | def print_all(self):
method number_of_elements (line 24) | def number_of_elements(self) -> int:
method add_to_head (line 37) | def add_to_head(self, key: int):
method add_to_tail (line 47) | def add_to_tail(self, key: int):
method delete_from_head (line 57) | def delete_from_head(self) -> int:
method delete_from_tail (line 70) | def delete_from_tail(self) -> int:
method delete_nodes_with_value (line 83) | def delete_nodes_with_value(self, key: int):
method delete_on_index (line 100) | def delete_on_index(self, index: int):
method insert_after (line 119) | def insert_after(self, list_element: int, new_element: int):
method insert_before (line 137) | def insert_before(self, list_element: int, new_element: int):
method sort (line 154) | def sort(self):
FILE: linked-lists/circular-doubly-linked-list/node.py
class Node (line 1) | class Node:
method __init__ (line 2) | def __init__(self, key: int=None, prev=None, next=None):
FILE: linked-lists/circular-singly-linked-list/list.py
class List (line 4) | class List:
method __init__ (line 5) | def __init__(self):
method is_empty (line 9) | def is_empty(self) -> bool:
method print_all (line 12) | def print_all(self):
method number_of_elements (line 24) | def number_of_elements(self) -> int:
method add_to_head (line 37) | def add_to_head(self, key: int):
method add_to_tail (line 45) | def add_to_tail(self, key: int):
method delete_from_head (line 53) | def delete_from_head(self) -> int:
method delete_from_tail (line 65) | def delete_from_tail(self) -> int:
method delete_nodes_with_value (line 80) | def delete_nodes_with_value(self, key: int):
method delete_on_index (line 96) | def delete_on_index(self, index: int):
method insert_after (line 116) | def insert_after(self, list_element: int, new_element: int):
method insert_before (line 132) | def insert_before(self, list_element: int, new_element: int):
method sort (line 149) | def sort(self):
FILE: linked-lists/circular-singly-linked-list/node.py
class Node (line 1) | class Node:
method __init__ (line 2) | def __init__(self, key: int=None, next=None):
FILE: linked-lists/doubly-linked-list/list.py
class List (line 4) | class List:
method __init__ (line 5) | def __init__(self):
method is_empty (line 9) | def is_empty(self) -> bool:
method print_all (line 12) | def print_all(self):
method number_of_elements (line 19) | def number_of_elements(self) -> int:
method add_to_head (line 27) | def add_to_head(self, key: int):
method add_to_tail (line 34) | def add_to_tail(self, key: int):
method delete_from_head (line 41) | def delete_from_head(self) -> int:
method delete_from_tail (line 53) | def delete_from_tail(self) -> int:
method delete_nodes_with_value (line 65) | def delete_nodes_with_value(self, key: int):
method delete_on_index (line 83) | def delete_on_index(self, index: int):
method insert_after (line 102) | def insert_after(self, list_element: int, new_element: int):
method insert_before (line 115) | def insert_before(self, list_element: int, new_element: int):
method sort (line 127) | def sort(self):
FILE: linked-lists/doubly-linked-list/node.py
class Node (line 1) | class Node:
method __init__ (line 2) | def __init__(self, key: int=None, prev=None, next=None):
FILE: linked-lists/singly-linked-list/list.py
class List (line 4) | class List:
method __init__ (line 5) | def __init__(self):
method is_empty (line 9) | def is_empty(self) -> bool:
method print_all (line 12) | def print_all(self):
method number_of_elements (line 19) | def number_of_elements(self) -> int:
method add_to_head (line 27) | def add_to_head(self, key: int):
method add_to_tail (line 33) | def add_to_tail(self, key: int):
method delete_from_head (line 40) | def delete_from_head(self) -> int:
method delete_from_tail (line 51) | def delete_from_tail(self) -> int:
method delete_nodes_with_value (line 66) | def delete_nodes_with_value(self, key: int):
method delete_on_index (line 82) | def delete_on_index(self, index: int):
method insert_after (line 102) | def insert_after(self, list_element: int, new_element: int):
method insert_before (line 113) | def insert_before(self, list_element: int, new_element: int):
method sort (line 125) | def sort(self):
FILE: linked-lists/singly-linked-list/node.py
class Node (line 1) | class Node:
method __init__ (line 2) | def __init__(self, key: int=None, next=None):
FILE: queue/circular-queue-fixed-size-array-impl.py
class Queue (line 1) | class Queue:
method __init__ (line 2) | def __init__(self, length: int = 10):
method enqueue (line 8) | def enqueue(self, item):
method dequeue (line 17) | def dequeue(self):
method peek (line 28) | def peek(self):
method size (line 33) | def size(self) -> int:
method is_empty (line 36) | def is_empty(self) -> bool:
method is_full (line 39) | def is_full(self) -> bool:
function hot_potato (line 43) | def hot_potato(namelist, number):
FILE: queue/queue-array-impl.py
class Queue (line 1) | class Queue:
method __init__ (line 2) | def __init__(self):
method enqueue (line 5) | def enqueue(self, item):
method dequeue (line 8) | def dequeue(self):
method peek (line 13) | def peek(self):
method size (line 18) | def size(self) -> int:
method is_empty (line 21) | def is_empty(self) -> bool:
function hot_potato (line 25) | def hot_potato(namelist, number):
FILE: queue/queue-fixed-size-array-impl.py
class Queue (line 1) | class Queue:
method __init__ (line 2) | def __init__(self, length: int = 10):
method enqueue (line 8) | def enqueue(self, item):
method dequeue (line 17) | def dequeue(self):
method peek (line 28) | def peek(self):
method size (line 33) | def size(self) -> int:
method is_empty (line 36) | def is_empty(self) -> bool:
method is_full (line 39) | def is_full(self) -> bool:
function hot_potato (line 43) | def hot_potato(namelist, number):
FILE: queue/queue-linked-list-impl.py
class Node (line 2) | class Node:
method __init__ (line 3) | def __init__(self, key, next=None):
class Queue (line 8) | class Queue:
method __init__ (line 9) | def __init__(self):
method enqueue (line 13) | def enqueue(self, item):
method dequeue (line 21) | def dequeue(self):
method peek (line 32) | def peek(self):
method size (line 37) | def size(self) -> int:
method is_empty (line 40) | def is_empty(self) -> bool:
function hot_potato (line 44) | def hot_potato(namelist, number):
FILE: queue/queue-two-stacks-impl.py
class Stack (line 1) | class Stack:
method __init__ (line 2) | def __init__(self):
method is_empty (line 5) | def is_empty(self):
method push (line 8) | def push(self, item):
method pop (line 11) | def pop(self):
method peek (line 14) | def peek(self):
method size (line 17) | def size(self):
class Queue (line 21) | class Queue:
method __init__ (line 22) | def __init__(self):
method is_empty (line 26) | def is_empty(self) -> bool:
method size (line 29) | def size(self) -> int:
method enqueue (line 32) | def enqueue(self, item):
method dequeue (line 35) | def dequeue(self):
method peek (line 45) | def peek(self):
function hot_potato (line 57) | def hot_potato(people: list, num: int) -> str:
FILE: recursion/convert-number-iterative.py
function converter (line 4) | def converter(num: int, base: int) -> str:
FILE: recursion/convert-number.py
function converter (line 1) | def converter(num: int, base: int) -> str:
FILE: recursion/factorial.py
function factorial_rec (line 1) | def factorial_rec(n: int) -> int:
function factorial_it (line 8) | def factorial_it(n: int) -> int:
FILE: recursion/fibonacci-iterative.py
function fibonacci (line 1) | def fibonacci(n: int) -> int:
FILE: recursion/fibonacci-memoization.py
function fibonacci (line 5) | def fibonacci(n: int) -> int:
FILE: recursion/fibonacci-recursive-worst-solution.py
function fibonacci (line 1) | def fibonacci(n: int) -> int:
FILE: recursion/fibonacci-recursive.py
function fibonacci (line 1) | def fibonacci(n: int) -> int:
FILE: recursion/fibonacci-sum-iterative.py
function fibonaci (line 1) | def fibonaci(n: int):
FILE: recursion/fibonacci-sum-recursive.py
function fibonacci (line 1) | def fibonacci(n: int) -> int:
FILE: recursion/maze.py
class Stack (line 4) | class Stack:
method __init__ (line 6) | def __init__(self) -> None:
method is_empty (line 10) | def is_empty(self) -> bool:
method size (line 14) | def size(self) -> int:
method push (line 18) | def push(self, item:Any) -> None:
method peek (line 22) | def peek(self) -> Any:
method pop (line 28) | def pop(self) -> Any:
function path_finder (line 57) | def path_finder(matrix:List[List[int]], stack:Stack) -> None:
function _move (line 61) | def _move(matrix:List[List[int]], stack:Stack) -> None:
function _add_coordinates_to_stack (line 86) | def _add_coordinates_to_stack(matrix:List[List[int]], stack:Stack, x:int...
FILE: recursion/palindrome.py
function palindrome_checker (line 1) | def palindrome_checker(string: str) -> bool:
function palindrome_checker_iterative (line 22) | def palindrome_checker_iterative(string:str) -> bool:
function palindrome_checker_slicing (line 40) | def palindrome_checker_slicing(string: str) -> bool:
FILE: recursion/reverse-linked-list-iterative-stack.py
class ListNode (line 3) | class ListNode:
method __init__ (line 4) | def __init__(self, payload = None, next: 'ListNode' = None) -> None:
function reverse_list (line 10) | def reverse_list(head: ListNode) -> ListNode:
FILE: recursion/reverse-linked-list-iterative.py
class ListNode (line 1) | class ListNode:
method __init__ (line 2) | def __init__(self, val=0, next=None):
function reverse_list (line 7) | def reverse_list(head: ListNode) -> ListNode:
FILE: recursion/reverse-linked-list.py
class ListNode (line 1) | class ListNode:
method __init__ (line 2) | def __init__(self, val: int = None, next = None):
function reverse_linked_list (line 7) | def reverse_linked_list(node: ListNode) -> ListNode:
FILE: recursion/reverse-list.py
function reverse_rec (line 4) | def reverse_rec(elements: list):
function reverse_iterative (line 19) | def reverse_iterative(elements: list):
FILE: recursion/reverse-string.py
function reverse_string (line 5) | def reverse_string(string: str) -> str:
function reverse_string_ex_one (line 19) | def reverse_string_ex_one(string: str) -> str:
function reverse_string_ex_two (line 29) | def reverse_string_ex_two(string: str) -> str:
FILE: recursion/stack.py
class Stack (line 1) | class Stack:
method __init__ (line 3) | def __init__(self):
method is_empty (line 6) | def is_empty(self):
method push (line 9) | def push(self, item):
method pop (line 12) | def pop(self):
method peek (line 15) | def peek(self):
method size (line 18) | def size(self):
FILE: recursion/sum-numbers-binary-recursion.py
function sum_numbers (line 5) | def sum_numbers(nums: list) -> int:
FILE: recursion/sum-numbers-pointer.py
function sum_numbers (line 5) | def sum_numbers(nums: list) -> int:
FILE: recursion/sum-numbers-slicing.py
function sum_numbers (line 5) | def sum_numbers(nums: list) -> int:
FILE: recursion/towers-of-hanoi.py
function print_move (line 1) | def print_move(start: str, end: str):
function towers (line 5) | def towers(number: int, start: str, spare: str, end: str):
FILE: searching/binary-search-iterative.py
function binary_search (line 2) | def binary_search(nums: list, target: int) -> bool:
FILE: searching/binary-search-recursive-pointers.py
function binary_search (line 2) | def binary_search(nums: list, target: int) -> bool:
FILE: searching/binary-search-recursive.py
function binary_search (line 3) | def binary_search(nums: list, target: int) -> bool:
FILE: searching/sequential-search-ordered-list.py
function sequential_search (line 2) | def sequential_search(nums: list, target: int) -> bool:
FILE: searching/sequential-search-unordered-list.py
function sequential_search (line 2) | def sequential_search(nums: list, target: int) -> bool:
FILE: sorting/bubble-sort.py
function bubble_sort (line 5) | def bubble_sort(nums: list):
FILE: sorting/insertion-sort.py
function insertion_sort (line 5) | def insertion_sort(nums: list):
FILE: sorting/merge-sort.py
function merge_sort (line 5) | def merge_sort(nums: list):
FILE: sorting/quicksort-return-new-array.py
function quick_sort (line 4) | def quick_sort(nums: list) -> list:
FILE: sorting/quicksort.py
function quick_sort (line 4) | def quick_sort(nums: list, i: int, j: int):
FILE: sorting/selection-sort.py
function selection_sort (line 5) | def selection_sort(nums: list):
FILE: sorting/short-bubble.py
function short_bubble (line 5) | def short_bubble(nums: list):
FILE: stack/examples/balanced-brackets.py
function balanced_brackets (line 4) | def balanced_brackets(string: str) -> bool:
FILE: stack/examples/number_converter.py
function base_converter (line 4) | def base_converter(num, base) -> str:
FILE: stack/examples/stack.py
class Stack (line 1) | class Stack:
method __init__ (line 2) | def __init__(self):
method is_empty (line 5) | def is_empty(self) -> bool:
method push (line 8) | def push(self, item):
method pop (line 11) | def pop(self):
method peek (line 16) | def peek(self):
method size (line 22) | def size(self) -> int:
FILE: stack/stack-array-impl-less-efficient.py
class Stack (line 4) | class Stack:
method __init__ (line 5) | def __init__(self):
method is_empty (line 8) | def is_empty(self) -> bool:
method push (line 11) | def push(self, item):
method pop (line 14) | def pop(self):
method peek (line 19) | def peek(self):
method size (line 24) | def size(self) -> int:
function reverse_string (line 28) | def reverse_string(s: str) -> str:
FILE: stack/stack-array-impl.py
class Stack (line 1) | class Stack:
method __init__ (line 2) | def __init__(self):
method is_empty (line 5) | def is_empty(self) -> bool:
method push (line 8) | def push(self, item):
method pop (line 11) | def pop(self):
method peek (line 16) | def peek(self):
method size (line 22) | def size(self) -> int:
function reverse_string (line 26) | def reverse_string(s: str) -> str:
FILE: stack/stack-fixed-size-array-impl.py
class Stack (line 4) | class Stack:
method __init__ (line 6) | def __init__(self, capacity: int = 1) -> None:
method size (line 11) | def size(self) -> int:
method is_empty (line 14) | def is_empty(self) -> bool:
method is_full (line 17) | def is_full(self) -> bool:
method push (line 20) | def push(self, item:Any):
method pop (line 26) | def pop(self) -> Any:
method peek (line 33) | def peek(self) -> Any:
function reverse_string (line 39) | def reverse_string(s: str) -> str:
FILE: stack/stack-linked-list-impl.py
class Node (line 1) | class Node:
method __init__ (line 2) | def __init__(self, key=None, next=None):
class Stack (line 7) | class Stack:
method __init__ (line 8) | def __init__(self):
method is_empty (line 12) | def is_empty(self) -> bool:
method push (line 15) | def push(self, item):
method pop (line 19) | def pop(self):
method peek (line 27) | def peek(self):
method size (line 32) | def size(self) -> int:
function reverse_string (line 36) | def reverse_string(s: str) -> str:
FILE: stack/stack_two_queues.py
class Queue (line 1) | class Queue:
method __init__ (line 2) | def __init__(self):
method enqueue (line 5) | def enqueue(self, item):
method dequeue (line 8) | def dequeue(self):
method size (line 13) | def size(self) -> int:
method is_empty (line 16) | def is_empty(self) -> bool:
method peek (line 19) | def peek(self) -> int:
class MyStack (line 24) | class MyStack:
method __init__ (line 26) | def __init__(self):
method empty (line 30) | def empty(self) -> bool:
method push (line 33) | def push(self, item):
method pop (line 36) | def pop(self):
method top (line 48) | def top(self):
method size (line 61) | def size(self) -> int:
FILE: stack_two_queues.py
class Queue (line 4) | class Queue:
method __init__ (line 6) | def __init__(self) -> None:
method size (line 9) | def size(self) -> int:
method is_empty (line 12) | def is_empty(self) -> bool:
method enqueue (line 15) | def enqueue(self, item:Any) -> None:
method dequeue (line 18) | def dequeue(self) -> Any:
class Stack (line 25) | class Stack:
method __init__ (line 27) | def __init__(self):
method push (line 32) | def push(self, x: Any) -> None:
method pop (line 36) | def pop(self) -> Any:
method peek (line 51) | def peek(self) -> Any:
method is_empty (line 66) | def is_empty(self) -> bool:
FILE: substring-search/brute_force.py
function search (line 6) | def search(text: str, pattern: str) -> int:
FILE: trees/avl-tree.py
class TreeNode (line 1) | class TreeNode:
method __init__ (line 2) | def __init__(self, key=None, value=None, parent=None, left=None, right...
method has_left_child (line 13) | def has_left_child(self) -> bool:
method has_right_child (line 16) | def has_right_child(self) -> bool:
method has_both_children (line 19) | def has_both_children(self) -> bool:
method is_leaf (line 22) | def is_leaf(self) -> bool:
method is_root (line 25) | def is_root(self) -> bool:
method has_parent (line 28) | def has_parent(self) -> bool:
method is_left_child (line 31) | def is_left_child(self) -> bool:
method is_right_child (line 34) | def is_right_child(self) -> bool:
method find_min (line 37) | def find_min(self):
method find_max (line 45) | def find_max(self):
class AVLTree (line 54) | class AVLTree:
method __init__ (line 55) | def __init__(self):
method size (line 59) | def size(self) -> int:
method is_empty (line 62) | def is_empty(self) -> bool:
method put (line 65) | def put(self, key, value):
method _put (line 72) | def _put(self, root: TreeNode, key, value):
method get (line 90) | def get(self, key) -> TreeNode:
method _get (line 96) | def _get(self, root: TreeNode, key) -> TreeNode:
method contains (line 110) | def contains(self, key) -> bool:
method delete (line 124) | def delete(self, key):
method find_min (line 182) | def find_min(self) -> TreeNode:
method find_max (line 190) | def find_max(self) -> TreeNode:
method _update_balance_factor (line 198) | def _update_balance_factor(self, root: TreeNode):
method _rebalance (line 215) | def _rebalance(self, root: TreeNode):
method _rotate_left (line 227) | def _rotate_left(self, root: TreeNode):
method _rotate_right (line 245) | def _rotate_right(self, root: TreeNode):
FILE: trees/binary-heap.py
class BinaryHeap (line 3) | class BinaryHeap:
method __init__ (line 4) | def __init__(self):
method is_empty (line 8) | def is_empty(self) -> bool:
method insert (line 11) | def insert(self, item):
method perc_up (line 16) | def perc_up(self, index: int):
method get_min (line 22) | def get_min(self):
method delete_min (line 27) | def delete_min(self):
method perc_down (line 37) | def perc_down(self, index: int):
method find_swap_index (line 44) | def find_swap_index(self, index: int) -> int:
method build_heap (line 53) | def build_heap(self, nums: list):
FILE: trees/binary-search-tree.py
class TreeNode (line 1) | class TreeNode:
method __init__ (line 2) | def __init__(self, key=None, value=None, parent=None, left=None, right...
method has_left_child (line 9) | def has_left_child(self) -> bool:
method has_right_child (line 12) | def has_right_child(self) -> bool:
method has_both_children (line 15) | def has_both_children(self) -> bool:
method is_leaf (line 18) | def is_leaf(self) -> bool:
method is_root (line 21) | def is_root(self) -> bool:
method has_parent (line 24) | def has_parent(self) -> bool:
method is_left_child (line 27) | def is_left_child(self) -> bool:
method is_right_child (line 32) | def is_right_child(self) -> bool:
method find_min (line 37) | def find_min(self):
method find_max (line 45) | def find_max(self):
class BinarySearchTree (line 54) | class BinarySearchTree:
method __init__ (line 55) | def __init__(self):
method size (line 59) | def size(self) -> int:
method is_empty (line 62) | def is_empty(self) -> bool:
method put (line 65) | def put(self, key, value):
method _put (line 72) | def _put(self, root: TreeNode, key, value):
method get (line 88) | def get(self, key) -> TreeNode:
method _get (line 94) | def _get(self, root: TreeNode, key) -> TreeNode:
method contains (line 108) | def contains(self, key) -> bool:
method delete (line 122) | def delete(self, key):
method find_min (line 173) | def find_min(self) -> TreeNode:
method find_max (line 181) | def find_max(self) -> TreeNode:
FILE: trees/class-representation.py
class TreeNode (line 1) | class TreeNode:
method __init__ (line 2) | def __init__(self, key=None, left=None, right=None):
method insert_root_value (line 7) | def insert_root_value(self, key=None):
method insert_left (line 10) | def insert_left(self, key=None):
method insert_right (line 13) | def insert_right(self, key=None):
method get_root_value (line 16) | def get_root_value(self):
method get_left_child (line 19) | def get_left_child(self):
method get_right_child (line 22) | def get_right_child(self):
function build_tree (line 35) | def build_tree() -> TreeNode:
function print_tree (line 50) | def print_tree(tree: TreeNode):
FILE: trees/list-representation.py
function create_tree (line 2) | def create_tree(root=None) -> list:
function insert_root (line 6) | def insert_root(tree: list, root=None):
function insert_left (line 10) | def insert_left(tree: list, root=None):
function insert_right (line 15) | def insert_right(tree: list, root=None):
function get_root (line 20) | def get_root(tree: list):
function get_left_child (line 24) | def get_left_child(tree: list) -> list:
function get_right_child (line 28) | def get_right_child(tree: list) -> list:
function build_tree (line 41) | def build_tree() -> list:
FILE: trees/parse-tree.py
class TreeNode (line 7) | class TreeNode:
method __init__ (line 8) | def __init__(self, key=None, left=None, right=None):
method insert_root_value (line 13) | def insert_root_value(self, key=None):
method insert_left (line 16) | def insert_left(self, key=None):
method insert_right (line 19) | def insert_right(self, key=None):
method get_root_value (line 22) | def get_root_value(self):
method get_left_child (line 25) | def get_left_child(self):
method get_right_child (line 28) | def get_right_child(self):
function tree_parser (line 39) | def tree_parser(s: str) -> TreeNode:
function evaluate (line 68) | def evaluate(node: TreeNode) -> int:
FILE: trees/stack.py
class Stack (line 1) | class Stack:
method __init__ (line 2) | def __init__(self):
method is_empty (line 5) | def is_empty(self):
method push (line 8) | def push(self, item):
method pop (line 11) | def pop(self):
method peek (line 14) | def peek(self):
method size (line 17) | def size(self):
FILE: trees/tree-traversal/functions.py
function inorder (line 21) | def inorder(tree: TreeNode):
function preorder (line 28) | def preorder(tree: TreeNode):
function postorder (line 35) | def postorder(tree: TreeNode):
FILE: trees/tree-traversal/inorder-traversal-example.py
function tree_parser (line 14) | def tree_parser(s: str) -> TreeNode:
function inorder (line 43) | def inorder(node: TreeNode) -> str:
FILE: trees/tree-traversal/postorder-traversal-example.py
function tree_parser (line 14) | def tree_parser(s: str) -> TreeNode:
function postorder (line 43) | def postorder(node: TreeNode) -> str:
FILE: trees/tree-traversal/preorder-traversal-example.py
function tree_parser (line 14) | def tree_parser(s: str) -> TreeNode:
function preorder (line 43) | def preorder(node: TreeNode, space: int = 0):
FILE: trees/tree-traversal/stack.py
class Stack (line 1) | class Stack:
method __init__ (line 2) | def __init__(self):
method is_empty (line 5) | def is_empty(self):
method push (line 8) | def push(self, item):
method pop (line 11) | def pop(self):
method peek (line 14) | def peek(self):
method size (line 17) | def size(self):
FILE: trees/tree-traversal/treenode.py
class TreeNode (line 1) | class TreeNode:
method __init__ (line 2) | def __init__(self, key=None, left=None, right=None):
method insert_root_value (line 7) | def insert_root_value(self, key=None):
method insert_left (line 10) | def insert_left(self, key=None):
method insert_right (line 13) | def insert_right(self, key=None):
method get_root_value (line 16) | def get_root_value(self):
method get_left_child (line 19) | def get_left_child(self):
method get_right_child (line 22) | def get_right_child(self):
method inorder (line 25) | def inorder(self):
method preorder (line 32) | def preorder(self):
method postorder (line 39) | def postorder(self):
FILE: trie/trie.py
class TrieNode (line 2) | class TrieNode:
method __init__ (line 3) | def __init__(self, key, parent = None, children: dict = {}):
class Trie (line 9) | class Trie:
method __init__ (line 10) | def __init__(self):
method insert (line 13) | def insert(self, string: str):
method contains (line 21) | def contains(self, string: str)->bool:
method delete (line 32) | def delete(self, string: str):
method prefix (line 48) | def prefix(self, prefix: str)->list:
method helper (line 61) | def helper(self, node: TrieNode, words: list, currentWord: str):
method allWords (line 69) | def allWords(self)->list:
method count (line 74) | def count(self)->int:
method countHelper (line 77) | def countHelper(self, node: TrieNode)->int:
[
{
"path": ".gitignore",
"chars": 28,
"preview": "/__pycache__/\n/venv/\n/.idea/"
},
{
"path": "LICENSE",
"chars": 1070,
"preview": "MIT License\n\nCopyright (c) 2018 Ivan Markovic\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
},
{
"path": "README.md",
"chars": 19186,
"preview": "# Problem-Solving-with-Algorithms-and-Data-Structures-using-Python\n\nI started the project by learning data structures an"
},
{
"path": "analysis/anagrams-linear-solution.py",
"chars": 726,
"preview": "\n# O(n)\ndef anagrams(string1: str, string2: str) -> bool:\n if len(string1) != len(string2):\n return False\n\n "
},
{
"path": "analysis/anagrams-loglinear-solution.py",
"chars": 600,
"preview": "\n# O(nlogn)\ndef anagrams(string1: str, string2: str) -> bool:\n\n if len(string1) != len(string2):\n return False"
},
{
"path": "analysis/anagrams-quadratic-solution.py",
"chars": 778,
"preview": "\n# O(n2)\ndef anagrams(string1: str, string2: str) -> bool:\n if len(string1) != len(string2):\n return False\n\n "
},
{
"path": "analysis/time-iterative-approach.py",
"chars": 309,
"preview": "import time\n\n\ndef sum_nums(n: int) -> int:\n start = time.time()\n total: int = 0\n for i in range(n + 1):\n "
},
{
"path": "analysis/time-noniterative-approach.py",
"chars": 277,
"preview": "import time\n\n\ndef sum_nums(n: int) -> int:\n start = time.time()\n total: int = n * (n + 1) / 2\n end = time.time("
},
{
"path": "deque/circular-deque.py",
"chars": 2624,
"preview": "\nfrom typing import Any, List\n\n\nclass Deque:\n\n def __init__(self, capacity: int = 10) -> None:\n self.capacity:"
},
{
"path": "deque/deque.py",
"chars": 1085,
"preview": "\nfrom typing import Any, List\n\n\nclass Deque:\n\n def __init__(self) -> None:\n self._deque: List[Any] = []\n\n d"
},
{
"path": "deque/deque_linked_list_impl.py",
"chars": 2028,
"preview": "\n\nfrom typing import List, Any\n\n\nclass ListNode:\n\n def __init__(self, key:Any = None, prev:'ListNode' = None, next:'L"
},
{
"path": "graphs/bellman-ford/graph.py",
"chars": 2186,
"preview": "\n# Bellman-Ford algorithm\n# Find shortest paths from one vertex,\n# to all other vertices in weighted graph.\n# Runtim"
},
{
"path": "graphs/bellman-ford-negative-weight-cycle/graph.py",
"chars": 2123,
"preview": "\n# Bellman-Ford algorithm\n# Find shortest paths from one vertex,\n# to all other vertices in weighted graph.\n# Runtim"
},
{
"path": "graphs/breadth-first-search/graph.py",
"chars": 1343,
"preview": "from queue import Queue\n\n\nclass Graph:\n def __init__(self):\n self.vertices: list = []\n self.adjacency_l"
},
{
"path": "graphs/breadth-first-search/main.py",
"chars": 485,
"preview": "from graph import Graph\n\ngraph = Graph()\n\nmy_vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']\n# add vertices\nfor"
},
{
"path": "graphs/breadth-first-search/queue.py",
"chars": 290,
"preview": "class Queue:\n def __init__(self):\n self.queue = []\n\n def enqueue(self, item):\n self.queue.insert(0, "
},
{
"path": "graphs/cycle-detection/Cycle.md",
"chars": 277,
"preview": "\n\n#Cycle - vertex is reachable from itself. \n\n\n##Undirected graph\n\n'''\nedge(u, v)\n'''\n\n- v is in the stack, visited but "
},
{
"path": "graphs/cycle-detection/cycle-directed-graph/graph.py",
"chars": 1391,
"preview": "\nclass Graph:\n def __init__(self):\n self.vertices: list = []\n self.adjacency_list: dict = {}\n se"
},
{
"path": "graphs/cycle-detection/cycle-directed-graph/main.py",
"chars": 253,
"preview": "from graph import Graph\n\ngraph: Graph = Graph()\n\n\nvertices = [\"a\", \"b\", \"c\", \"d\"]\nfor vertex in vertices:\n graph.add_"
},
{
"path": "graphs/cycle-detection/cycle-undirected-graph/graph.py",
"chars": 1476,
"preview": "\nclass Graph:\n def __init__(self):\n self.vertices: list = []\n self.adjacency_list: dict = {}\n se"
},
{
"path": "graphs/cycle-detection/cycle-undirected-graph/main.py",
"chars": 255,
"preview": "from graph import Graph\n\ngraph: Graph = Graph()\n\n\nvertices = [\"a\", \"b\", \"c\", \"d\"]\nfor vertex in vertices:\n graph.add_"
},
{
"path": "graphs/depth-first-search/depth-first-search/graph.py",
"chars": 1842,
"preview": "from stack import Stack\n\n\nclass Graph:\n def __init__(self):\n self.vertices: list = []\n self.adjacency_l"
},
{
"path": "graphs/depth-first-search/depth-first-search/main.py",
"chars": 485,
"preview": "from graph import Graph\n\ngraph = Graph()\n\nmy_vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']\n# add vertices\nfor"
},
{
"path": "graphs/depth-first-search/depth-first-search/stack.py",
"chars": 348,
"preview": "class Stack:\n def __init__(self):\n self.items = []\n\n def is_empty(self):\n return self.items == []\n\n "
},
{
"path": "graphs/depth-first-search/depth-first-search-recursive/graph.py",
"chars": 1337,
"preview": "\nclass Graph:\n def __init__(self):\n self.vertices: list = []\n self.adjacency_list: dict = {}\n se"
},
{
"path": "graphs/depth-first-search/depth-first-search-recursive/main.py",
"chars": 485,
"preview": "from graph import Graph\n\ngraph = Graph()\n\nmy_vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']\n# add vertices\nfor"
},
{
"path": "graphs/dijkstra/adjacency-list-impl/main.py",
"chars": 2190,
"preview": "\nfrom typing import List, Dict, Set\n\nfrom vertex import Vertex\n\n\nclass Graph:\n\n def __init__(self, capacity :int =10)"
},
{
"path": "graphs/dijkstra/adjacency-list-impl/vertex.py",
"chars": 146,
"preview": "\n\nclass Vertex:\n\n def __init__(self, label :str, weight :int = float('inf')):\n self.label :str = label\n "
},
{
"path": "graphs/dijkstra/matrix-impl/graph.py",
"chars": 2346,
"preview": "from vertex import Vertex\n\n\nclass Graph:\n def __init__(self, size: int = 10):\n self.size: int = size\n s"
},
{
"path": "graphs/dijkstra/matrix-impl/main.py",
"chars": 488,
"preview": "from graph import Graph\n\n\ngraph: Graph = Graph()\n\ngraph.add_vertex(\"START\")\ngraph.add_vertex(\"A\")\ngraph.add_vertex(\"C\")\n"
},
{
"path": "graphs/dijkstra/matrix-impl/vertex.py",
"chars": 204,
"preview": "class Vertex:\n def __init__(self, label: str = None, weight: int = float(\"inf\"), index: int = None):\n self.la"
},
{
"path": "graphs/dijkstra/priority-queue-impl-adjacency-map/graph.py",
"chars": 1362,
"preview": "from vertex import Vertex\nfrom priorityqueue import PriorityQueue\n\n\nclass Graph:\n def __init__(self):\n self._v"
},
{
"path": "graphs/dijkstra/priority-queue-impl-adjacency-map/main.py",
"chars": 487,
"preview": "from graph import Graph\n\n\ngraph: Graph = Graph()\n\ngraph.add_vertex(\"START\")\ngraph.add_vertex(\"A\")\ngraph.add_vertex(\"C\")\n"
},
{
"path": "graphs/dijkstra/priority-queue-impl-adjacency-map/priorityqueue.py",
"chars": 1888,
"preview": "from vertex import Vertex\n\n\nclass PriorityQueue:\n def __init__(self):\n self.pq: list = [None]\n self._po"
},
{
"path": "graphs/dijkstra/priority-queue-impl-adjacency-map/vertex.py",
"chars": 196,
"preview": "class Vertex:\n def __init__(self, label: str = None, weight: int = float(\"inf\"), key: int = None):\n self.label"
},
{
"path": "graphs/is-graph-bipartite/graph.py",
"chars": 1303,
"preview": "from queue import Queue\n\n\nclass Graph:\n def __init__(self):\n self.vertices: list = []\n self.adjacency_l"
},
{
"path": "graphs/is-graph-bipartite/main.py",
"chars": 278,
"preview": "from graph import Graph\n\n\ng: Graph = Graph()\ng.add_vertex(\"a\")\ng.add_vertex(\"b\")\ng.add_vertex(\"c\")\ng.add_vertex(\"d\")\n\n# "
},
{
"path": "graphs/is-graph-bipartite/queue.py",
"chars": 342,
"preview": "class Queue:\n def __init__(self):\n self._queue: list = []\n\n def is_empty(self) -> bool:\n return len("
},
{
"path": "graphs/kosarajus-algorithm/graph.py",
"chars": 1873,
"preview": "\n\nfrom typing import Dict, List, Set\n\nfrom stack import Stack\n\nclass Graph:\n\n\n def __init__(self) -> None:\n se"
},
{
"path": "graphs/kosarajus-algorithm/main.py",
"chars": 320,
"preview": "from graph import Graph\n\ng: Graph = Graph()\nfor i in range(9):\n g.add_vertex(str(i))\n\ng.add_edge('0', '1')\ng.add_edge"
},
{
"path": "graphs/kosarajus-algorithm/stack.py",
"chars": 574,
"preview": "class Stack:\n def __init__(self):\n self._stack: list = []\n\n def is_empty(self) -> bool:\n return len("
},
{
"path": "graphs/minimum-spanning-tree/breadth-first-search/graph.py",
"chars": 1510,
"preview": "from queue import Queue\n\n\nclass Graph:\n def __init__(self):\n self.vertices: list = []\n self.adjacency_l"
},
{
"path": "graphs/minimum-spanning-tree/breadth-first-search/main.py",
"chars": 530,
"preview": "from graph import Graph\n\ngraph = Graph()\n\nmy_vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']\n# add vertices\nfor"
},
{
"path": "graphs/minimum-spanning-tree/breadth-first-search/queue.py",
"chars": 290,
"preview": "class Queue:\n def __init__(self):\n self.queue = []\n\n def enqueue(self, item):\n self.queue.insert(0, "
},
{
"path": "graphs/minimum-spanning-tree/kruskals-algorithm/graph.py",
"chars": 1601,
"preview": "\nfrom typing import List, Set, Dict, Tuple\n\nclass Graph:\n\n\n def __init__(self) -> None:\n self.vertices:Set[str"
},
{
"path": "graphs/minimum-spanning-tree/kruskals-algorithm/main.py",
"chars": 347,
"preview": "from graph import Graph\n\ng: Graph = Graph()\n\ng.add_vertex('a')\ng.add_vertex('b')\ng.add_vertex('d')\ng.add_vertex('c')\ng.a"
},
{
"path": "graphs/minimum-spanning-tree/prims-algorithm/graph.py",
"chars": 1500,
"preview": "\nfrom typing import Dict, List\n\nfrom vertex import Vertex\nfrom priorityqueue import PriorityQueue\n\nclass Graph:\n\n def"
},
{
"path": "graphs/minimum-spanning-tree/prims-algorithm/main.py",
"chars": 467,
"preview": "from graph import Graph\n\n\ngraph: Graph = Graph()\n\ngraph.add_vertex(\"a\")\ngraph.add_vertex(\"b\")\ngraph.add_vertex(\"f\")\ngrap"
},
{
"path": "graphs/minimum-spanning-tree/prims-algorithm/priorityqueue.py",
"chars": 2067,
"preview": "from typing import List\n\nfrom vertex import Vertex\n\n\nclass PriorityQueue:\n\n\n def __init__(self) -> None:\n self"
},
{
"path": "graphs/minimum-spanning-tree/prims-algorithm/vertex.py",
"chars": 200,
"preview": "class Vertex:\n\n def __init__(self, label:str=None, weight:int=float('inf'), index:int=None) -> None:\n self.lab"
},
{
"path": "graphs/topological-sorting/graph.py",
"chars": 1858,
"preview": "class Graph:\n def __init__(self):\n self.vertices: list = []\n self.adjacencyList: dict = {}\n self"
},
{
"path": "graphs/topological-sorting/main.py",
"chars": 282,
"preview": "from graph import Graph\n\ngraph = Graph()\n\nvertices = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]\nfor vertex in vertices:\n graph.ad"
},
{
"path": "graphs/union-find/number-of-connected-components/graph.py",
"chars": 1014,
"preview": "from typing import List\n\ndef find_parent(i: int, components: List[int]) -> int:\n \n while i != components[i]:\n "
},
{
"path": "graphs/union-find/union-find-path-compression/graph.py",
"chars": 1176,
"preview": "from vertex import Vertex\n\n\nclass Graph:\n\n def __init__(self):\n self.vertices: dict = {}\n self.edges: l"
},
{
"path": "graphs/union-find/union-find-path-compression/main.py",
"chars": 460,
"preview": "from graph import Graph\nfrom vertex import Vertex\n\ng: Graph = Graph()\ng.add_vertex('a')\ng.add_vertex('b')\ng.add_vertex('"
},
{
"path": "graphs/union-find/union-find-path-compression/vertex.py",
"chars": 150,
"preview": "class Vertex:\n\n def __init__(self, label: str = None):\n self.label = label\n self.parent: 'Vertex' = sel"
},
{
"path": "hash-table/chaining.py",
"chars": 3488,
"preview": "\n\nfrom typing import Any, List\n\nclass KeyValue:\n\n def __init__(self, key: int, value: Any) -> None:\n self.key:"
},
{
"path": "hash-table/linear-probing.py",
"chars": 3204,
"preview": "\n\nfrom typing import Any, List, Tuple\n\n\nclass HashTable:\n\n def __init__(self, capacity:int = 11) -> None:\n sel"
},
{
"path": "linked-lists/circular-doubly-linked-list/list.py",
"chars": 5107,
"preview": "from node import Node\n\n\nclass List:\n def __init__(self):\n self.head: Node = None\n self.tail: Node = Non"
},
{
"path": "linked-lists/circular-doubly-linked-list/node.py",
"chars": 147,
"preview": "class Node:\n def __init__(self, key: int=None, prev=None, next=None):\n self.key = key\n self.prev = prev"
},
{
"path": "linked-lists/circular-singly-linked-list/list.py",
"chars": 4721,
"preview": "from node import Node\n\n\nclass List:\n def __init__(self):\n self.head: Node = None\n self.tail: Node = Non"
},
{
"path": "linked-lists/circular-singly-linked-list/node.py",
"chars": 111,
"preview": "class Node:\n def __init__(self, key: int=None, next=None):\n self.key = key\n self.next = next\n\n"
},
{
"path": "linked-lists/doubly-linked-list/list.py",
"chars": 4268,
"preview": "from node import Node\n\n\nclass List:\n def __init__(self):\n self.head: Node = None\n self.tail: Node = Non"
},
{
"path": "linked-lists/doubly-linked-list/node.py",
"chars": 147,
"preview": "class Node:\n def __init__(self, key: int=None, prev=None, next=None):\n self.key = key\n self.prev = prev"
},
{
"path": "linked-lists/singly-linked-list/list.py",
"chars": 3993,
"preview": "from node import Node\n\n\nclass List:\n def __init__(self):\n self.head: Node = None\n self.tail: Node = Non"
},
{
"path": "linked-lists/singly-linked-list/node.py",
"chars": 111,
"preview": "class Node:\n def __init__(self, key: int=None, next=None):\n self.key = key\n self.next = next\n\n"
},
{
"path": "queue/circular-queue-fixed-size-array-impl.py",
"chars": 1498,
"preview": "class Queue:\n def __init__(self, length: int = 10):\n self._length: int = length\n self._queue: list = [N"
},
{
"path": "queue/queue-array-impl.py",
"chars": 847,
"preview": "class Queue:\n def __init__(self):\n self._queue = []\n\n def enqueue(self, item):\n self._queue.insert(0"
},
{
"path": "queue/queue-fixed-size-array-impl.py",
"chars": 1424,
"preview": "class Queue:\n def __init__(self, length: int = 10):\n self._length: int = length\n self._queue: list = [N"
},
{
"path": "queue/queue-linked-list-impl.py",
"chars": 1330,
"preview": "\nclass Node:\n def __init__(self, key, next=None):\n self.key = key\n self.next = next\n\n\nclass Queue:\n "
},
{
"path": "queue/queue-two-stacks-impl.py",
"chars": 1812,
"preview": "class Stack:\n def __init__(self):\n self.items = []\n\n def is_empty(self):\n return self.items == []\n\n "
},
{
"path": "recursion/convert-number-iterative.py",
"chars": 550,
"preview": "from stack import Stack\n\n\ndef converter(num: int, base: int) -> str:\n digits = \"0123456789ABCDEF\"\n stack: Stack = "
},
{
"path": "recursion/convert-number.py",
"chars": 230,
"preview": "def converter(num: int, base: int) -> str:\n digits = \"0123456789ABCDEF\"\n if num < base:\n return digits[num]"
},
{
"path": "recursion/factorial.py",
"chars": 273,
"preview": "def factorial_rec(n: int) -> int:\n if n <= 1:\n return 1\n else:\n return n * factorial_rec(n - 1)\n\n\nde"
},
{
"path": "recursion/fibonacci-iterative.py",
"chars": 259,
"preview": "def fibonacci(n: int) -> int:\n if n <= 1:\n return 0\n elif n == 2:\n return 1\n prev: int = 0\n cu"
},
{
"path": "recursion/fibonacci-memoization.py",
"chars": 296,
"preview": "\nnums: dict = {}\n\n\ndef fibonacci(n: int) -> int:\n if n <= 1:\n return 0\n elif n == 2:\n return 1\n e"
},
{
"path": "recursion/fibonacci-recursive-worst-solution.py",
"chars": 202,
"preview": "def fibonacci(n: int) -> int:\n if n <= 1:\n return 0\n elif n == 2:\n return 1\n else:\n return"
},
{
"path": "recursion/fibonacci-recursive.py",
"chars": 351,
"preview": "def fibonacci(n: int) -> int:\n\n def fibonacci_helper(num: int, prev: int = 0, curr: int = 1) -> int:\n if num <"
},
{
"path": "recursion/fibonacci-sum-iterative.py",
"chars": 317,
"preview": "def fibonaci(n: int):\n \n if n == 1:\n return 0\n if n == 2:\n return 1\n\n prev: int = 0\n curr: "
},
{
"path": "recursion/fibonacci-sum-recursive.py",
"chars": 376,
"preview": "def fibonacci(n: int) -> int:\n\n def fibonacci_helper(num: int, acc: int = 0, prev: int = 0, curr: int = 1):\n i"
},
{
"path": "recursion/maze.py",
"chars": 2188,
"preview": "\nfrom typing import List, Any\n\nclass Stack:\n\n def __init__(self) -> None:\n self.stack:List[Any] = list()\n\n\n "
},
{
"path": "recursion/palindrome.py",
"chars": 1215,
"preview": "def palindrome_checker(string: str) -> bool:\n\n def palindrome_helper(s: str, start: int, end: int) -> bool:\n i"
},
{
"path": "recursion/reverse-linked-list-iterative-stack.py",
"chars": 617,
"preview": "from stack import Stack\n\nclass ListNode:\n def __init__(self, payload = None, next: 'ListNode' = None) -> None:\n "
},
{
"path": "recursion/reverse-linked-list-iterative.py",
"chars": 496,
"preview": "class ListNode:\n def __init__(self, val=0, next=None):\n self.val = val\n self.next = next\n\n\ndef reverse_"
},
{
"path": "recursion/reverse-linked-list.py",
"chars": 444,
"preview": "class ListNode:\n def __init__(self, val: int = None, next = None):\n self.val = val\n self.next = next\n\n\n"
},
{
"path": "recursion/reverse-list.py",
"chars": 645,
"preview": "nums: list = [1, 2, 3, 4, 5]\n\n\ndef reverse_rec(elements: list):\n\n def reverse_list_helper(values: list, start: int, e"
},
{
"path": "recursion/reverse-string.py",
"chars": 743,
"preview": "\nstring: str = \"This string will be reversed\"\n\n\ndef reverse_string(string: str) -> str:\n\n def helper(s: str, end: int"
},
{
"path": "recursion/stack.py",
"chars": 349,
"preview": "class Stack:\n\n def __init__(self):\n self.items = []\n\n def is_empty(self):\n return self.items == []\n\n"
},
{
"path": "recursion/sum-numbers-binary-recursion.py",
"chars": 435,
"preview": "numbers: list = [1, 2, 3, 4, 5]\n\n\n# O(n) time\ndef sum_numbers(nums: list) -> int:\n\n def helper(elements: list, start:"
},
{
"path": "recursion/sum-numbers-pointer.py",
"chars": 318,
"preview": "numbers: list = [1, 2, 3, 4, 5]\n\n\n# O(n) time\ndef sum_numbers(nums: list) -> int:\n\n def helper(elements: list, end: i"
},
{
"path": "recursion/sum-numbers-slicing.py",
"chars": 248,
"preview": "numbers: list = [1, 2, 3, 4, 5]\n\n\n# slicing is O(k), better is solution with pointer\ndef sum_numbers(nums: list) -> int:"
},
{
"path": "recursion/towers-of-hanoi.py",
"chars": 369,
"preview": "def print_move(start: str, end: str):\n print(\"Moving from\", start, \"to\", end)\n\n\ndef towers(number: int, start: str, s"
},
{
"path": "searching/binary-search-iterative.py",
"chars": 552,
"preview": "\ndef binary_search(nums: list, target: int) -> bool:\n start: int = 0\n end: int = len(nums) - 1\n found: bool = F"
},
{
"path": "searching/binary-search-recursive-pointers.py",
"chars": 763,
"preview": "\ndef binary_search(nums: list, target: int) -> bool:\n\n def binary_search_helper(numbers: list, element, start: int, e"
},
{
"path": "searching/binary-search-recursive.py",
"chars": 593,
"preview": "# slicing a list is O(k)\n# better is recursive solution with pointers\ndef binary_search(nums: list, target: int) -> bool"
},
{
"path": "searching/sequential-search-ordered-list.py",
"chars": 491,
"preview": "\ndef sequential_search(nums: list, target: int) -> bool:\n found: bool = False\n stopped: bool = False\n i: int = "
},
{
"path": "searching/sequential-search-unordered-list.py",
"chars": 363,
"preview": "\ndef sequential_search(nums: list, target: int) -> bool:\n i: int = 0\n found: bool = False\n while i < len(nums) "
},
{
"path": "sorting/bubble-sort.py",
"chars": 299,
"preview": "\narray = [54, 26, 93, 17, 77, 31, 44, 55, 20]\n\n\ndef bubble_sort(nums: list):\n for i in range(len(nums)):\n for "
},
{
"path": "sorting/insertion-sort.py",
"chars": 349,
"preview": "\narray = [54, 26, 93, 17, 77, 31, 44, 55, 20]\n\n\ndef insertion_sort(nums: list):\n for i in range(1, len(nums), +1):\n "
},
{
"path": "sorting/merge-sort.py",
"chars": 689,
"preview": "\narray = [54, 26, 93, 17, 77, 31, 44, 55, 20]\n\n\ndef merge_sort(nums: list):\n if len(nums) < 2:\n return\n mid"
},
{
"path": "sorting/quicksort-return-new-array.py",
"chars": 575,
"preview": "array = [54, 26, 93, 17, 77, 31, 44, 55, 20]\n\n\ndef quick_sort(nums: list) -> list:\n if len(nums) < 2:\n return "
},
{
"path": "sorting/quicksort.py",
"chars": 898,
"preview": "array = [54, 26, 93, 17, 77, 31, 44, 55, 20]\n\n\ndef quick_sort(nums: list, i: int, j: int):\n if i < j:\n left: i"
},
{
"path": "sorting/selection-sort.py",
"chars": 408,
"preview": "\narray = [54, 26, 93, 17, 77, 31, 44, 55, 20]\n\n\ndef selection_sort(nums: list):\n for i in range(0, len(nums), +1):\n "
},
{
"path": "sorting/short-bubble.py",
"chars": 398,
"preview": "\narray = [54, 26, 93, 17, 77, 31, 44, 55, 20]\n\n\ndef short_bubble(nums: list):\n swapped: bool = True\n dec: int = 1\n"
},
{
"path": "stack/examples/balanced-brackets.py",
"chars": 628,
"preview": "from stack import Stack\n\n\ndef balanced_brackets(string: str) -> bool:\n stack: Stack = Stack()\n for character in st"
},
{
"path": "stack/examples/number_converter.py",
"chars": 421,
"preview": "from stack import Stack\n\n\ndef base_converter(num, base) -> str:\n digits = \"0123456789ABCDEF\"\n stack: Stack = Stack"
},
{
"path": "stack/examples/stack.py",
"chars": 575,
"preview": "class Stack:\n def __init__(self):\n self._stack: list = []\n\n def is_empty(self) -> bool:\n return len("
},
{
"path": "stack/stack-array-impl-less-efficient.py",
"chars": 1019,
"preview": "# this solution is less efficient because\n# pop() from end of array is faster than pop(some_other_index)\n# append(item) "
},
{
"path": "stack/stack-array-impl.py",
"chars": 914,
"preview": "class Stack:\n def __init__(self):\n self._stack: list = []\n\n def is_empty(self) -> bool:\n return len("
},
{
"path": "stack/stack-fixed-size-array-impl.py",
"chars": 1271,
"preview": "from typing import Any, List\n\n\nclass Stack:\n\n def __init__(self, capacity: int = 1) -> None:\n self.capacity: i"
},
{
"path": "stack/stack-linked-list-impl.py",
"chars": 1108,
"preview": "class Node:\n def __init__(self, key=None, next=None):\n self.key = key\n self.next = next\n\n\nclass Stack:\n"
},
{
"path": "stack/stack_two_queues.py",
"chars": 1590,
"preview": "class Queue:\n def __init__(self):\n self._queue = []\n\n def enqueue(self, item):\n self._queue.insert(0"
},
{
"path": "stack_two_queues.py",
"chars": 1545,
"preview": "from typing import Any, List\n\n\nclass Queue:\n\n def __init__(self) -> None:\n self.queue:List[Any] = []\n\n def "
},
{
"path": "substring-search/brute_force.py",
"chars": 472,
"preview": "\n\n# O(m * n)\n# m - length of the text\n# n - length of pattern\ndef search(text: str, pattern: str) -> int:\n \n t:int"
},
{
"path": "trees/avl-tree.py",
"chars": 9015,
"preview": "class TreeNode:\n def __init__(self, key=None, value=None, parent=None, left=None, right=None,\n left_s"
},
{
"path": "trees/binary-heap.py",
"chars": 1844,
"preview": "\n# min heap\nclass BinaryHeap:\n def __init__(self):\n self.pointer: int = 0\n self.heap: list = [None]\n\n "
},
{
"path": "trees/binary-search-tree.py",
"chars": 5927,
"preview": "class TreeNode:\n def __init__(self, key=None, value=None, parent=None, left=None, right=None):\n self.key = key"
},
{
"path": "trees/class-representation.py",
"chars": 1359,
"preview": "class TreeNode:\n def __init__(self, key=None, left=None, right=None):\n self.key = key\n self.left = left"
},
{
"path": "trees/list-representation.py",
"chars": 1171,
"preview": "\ndef create_tree(root=None) -> list:\n return [None, [], []]\n\n\ndef insert_root(tree: list, root=None):\n tree[0] = r"
},
{
"path": "trees/parse-tree.py",
"chars": 1933,
"preview": "\nfrom stack import Stack\nimport operator\nimport re\n\n\nclass TreeNode:\n def __init__(self, key=None, left=None, right=N"
},
{
"path": "trees/stack.py",
"chars": 349,
"preview": "class Stack:\n def __init__(self):\n self.items = []\n\n def is_empty(self):\n return self.items == []\n\n "
},
{
"path": "trees/tree-traversal/functions.py",
"chars": 884,
"preview": "from treenode import TreeNode\n\nnode: TreeNode = TreeNode('a')\nnode.insert_left('b')\nnode.insert_left('c')\nnode.get_left_"
},
{
"path": "trees/tree-traversal/inorder-traversal-example.py",
"chars": 1447,
"preview": "\nfrom stack import Stack\nimport operator\nimport re\nfrom treenode import TreeNode\n\nopers = {'+':operator.add, '-':operato"
},
{
"path": "trees/tree-traversal/postorder-traversal-example.py",
"chars": 1447,
"preview": "\nfrom stack import Stack\nimport operator\nimport re\nfrom treenode import TreeNode\n\nopers = {'+':operator.add, '-':operato"
},
{
"path": "trees/tree-traversal/preorder-traversal-example.py",
"chars": 1310,
"preview": "\nfrom stack import Stack\nimport operator\nimport re\nfrom treenode import TreeNode\n\nopers = {'+':operator.add, '-':operato"
},
{
"path": "trees/tree-traversal/stack.py",
"chars": 349,
"preview": "class Stack:\n def __init__(self):\n self.items = []\n\n def is_empty(self):\n return self.items == []\n\n "
},
{
"path": "trees/tree-traversal/treenode.py",
"chars": 1288,
"preview": "class TreeNode:\n def __init__(self, key=None, left=None, right=None):\n self.key = key\n self.left = left"
},
{
"path": "trie/trie.py",
"chars": 3549,
"preview": "\r\nclass TrieNode:\r\n def __init__(self, key, parent = None, children: dict = {}):\r\n self.key = key\r\n sel"
}
]
About this extraction
This page contains the full source code of the ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 128 files (157.9 KB), approximately 43.4k tokens, and a symbol index with 611 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.