├── Examples ├── c++ │ ├── BinarySearchTree │ │ └── BST.cpp │ ├── Graph Algorithms │ │ ├── directed-unweighted-topological-sort.cpp │ │ ├── directed-weighted-BellmanFord.cpp │ │ ├── directed-weighted-Dijkstra.cpp │ │ ├── undirected-unweighted-DFS.cpp │ │ ├── undirected-weighted-Kruskal-using-disjoint-set.cpp │ │ ├── undirected-weighted-Kruskal-using-vector.cpp │ │ └── undirected-weighted-Prim.cpp │ ├── Graph │ │ ├── directed-unweighted-graph-using-list.cpp │ │ ├── directed-weighted-graph-using-list.cpp │ │ ├── directed-weighted-graph-using-matrix.cpp │ │ └── undirected-unweighted-graph-using-list.cpp │ ├── Hashtable │ │ ├── hashtable-using-balanced-tree.cpp │ │ └── hashtable-using-lists.cpp │ ├── Heap │ │ └── heap.cpp │ ├── KDTree │ │ └── kd-tree.cpp │ ├── Linked List │ │ └── singly-linked-list.cpp │ ├── Queue │ │ ├── queue-using-links.cpp │ │ └── queue-using-list.cpp │ ├── Searching │ │ ├── binary-search-answer.cpp │ │ ├── binary-search-recursive.cpp │ │ ├── binary-search.cpp │ │ ├── exponential-search.cpp │ │ ├── interpolation-search.cpp │ │ ├── jump-search.cpp │ │ ├── linear-search.cpp │ │ ├── ternary-search-max.cpp │ │ └── ternary-search.cpp │ ├── Sorting │ │ ├── bubble-sort-adaptive.cpp │ │ ├── bubble-sort-cleancode.cpp │ │ ├── bubble-sort-short.cpp │ │ ├── bubble-sort-simple.cpp │ │ ├── bucket-sort.cpp │ │ ├── counting-sort.cpp │ │ ├── insertion-sort-cleancode.cpp │ │ ├── insertion-sort-short.cpp │ │ ├── insertion-sort-simple.cpp │ │ ├── merge-sort-cleancode.cpp │ │ ├── merge-sort-short.cpp │ │ ├── quick-sort-hoare-short.cpp │ │ ├── quick-sort-hoare-using-while-loops.cpp │ │ ├── quick-sort-lomuto-cleancode.cpp │ │ ├── quick-sort-lomuto-random-pivot.cpp │ │ ├── quick-sort-lomuto-short.cpp │ │ ├── quick-sort-lomuto-shuffle.cpp │ │ ├── radix-sort.cpp │ │ ├── selection-sort-cleancode.cpp │ │ ├── selection-sort-short.cpp │ │ └── selection-sort-simple.cpp │ ├── Stack │ │ ├── stack-using-array.cpp │ │ ├── stack-using-links.cpp │ │ ├── stack-using-list.cpp │ │ └── stack-using-vector.cpp │ └── stl-cheatsheet.cpp └── java │ ├── 02-Searching │ ├── Search.java │ └── SearchTest.java │ ├── 03-Sorting │ ├── Sort.java │ └── SortTest.java │ ├── 04-LinkedList │ ├── DoublyLinkedList.java │ ├── DoublyLinkedListTest.java │ ├── LinkedList.java │ └── LinkedListTest.java │ ├── 05-Queue │ ├── MinQueue.java │ ├── Queue.java │ └── QueueTest.java │ ├── 06-Stack │ ├── MinStack.java │ ├── Stack.java │ └── StackTest.java │ ├── 09-Heap │ ├── Heap.java │ └── HeapTest.java │ ├── 11-Hashmap │ ├── HashTable.java │ └── HashTableTest.java │ └── 13-14-15-Graphs │ ├── 01-DFS.java │ ├── 02-BFS.java │ ├── 03-TopologicalSort.java │ ├── 04-Cycles.java │ ├── 05-NumberOfPathsOfFixedLength.java │ ├── 06-Bridges.java │ ├── 07-ArticulationPoints.java │ ├── 08-BellmanFord.java │ ├── 09-Dijkstra.java │ ├── 10-Floyd.java │ ├── 11-Prim.java │ ├── 12-Kruskal.java │ ├── 13-EdmondsKarp.java │ ├── DirectedGraph.java │ ├── Graph.java │ └── GraphsTest.java ├── Exercises └── 01-ComplexityOfAlgorithms.md ├── Homeworks 2019-2020 ├── Homework1 │ ├── cloning-socks.cpp │ ├── darts.cpp │ └── mission-sda.cpp ├── Homework2 │ ├── electrical-energy.cpp │ ├── permutations.cpp │ └── schedule.cpp ├── Homework3 │ ├── balloons-and-candy.cpp │ ├── cows.cpp │ ├── monster-trucks.cpp │ └── strawberries.cpp ├── Homework4 │ └── truck-ordering.cpp ├── Homework5 │ ├── los-binares.cpp │ └── student-queue.cpp └── Homework7 │ └── file-systems.cpp ├── Homeworks 2020-2021 ├── Homework 1 │ ├── Another_arrays_interview_problem.cpp │ ├── Stripe_interview_problem.cpp │ ├── Unique_with_recursion.cpp │ ├── duner_kebab.py │ ├── enterpreneur.py │ └── unique_using_combinatorics.py ├── Homework 2 │ ├── memories.cpp │ ├── merge_intervals.py │ └── walkingMedian.cpp └── Homework 3 │ ├── 01-grades.cpp │ ├── 02-the-perfect-printer.cpp │ ├── 03-genetic-engineering.cpp │ ├── 04-weird-queries.cpp │ └── 05-between-us-bonus.cpp ├── Lectures ├── 00-Prerequisites │ └── readme.md ├── 01-ComplexityOfAlgorithms │ └── readme.md ├── 02-Sorting │ └── readme.md ├── 03-Searching │ └── readme.md ├── 04-LinkedList │ └── readme.md ├── 05-Queue │ └── readme.md ├── 06-Stack │ └── readme.md ├── 07-Trees,BinarySearchTree │ └── readme.md ├── 08-BalancedTrees │ └── readme.md ├── 09-Heap │ └── readme.md ├── 10-GeometricSearch, KDTree │ └── readme.md ├── 11-Hashmap │ └── readme.md ├── 12-DynamicProgramming │ └── readme.md ├── 13-Graph. Representation and definitions │ └── readme.md ├── 14-Grapht.Shortest Path, Dijkstra │ └── readme.md ├── 15-MinimumSpanningTree │ └── readme.md └── 16-Euler and Hamiltonian Sycle. P,NP,NP Complete tasks │ └── readme.md ├── README.md └── Tests ├── Test 5 └── wave_game.cpp ├── Test1 └── solution.cpp ├── Test2 └── solution.cpp └── Test3 ├── penultimate-descendants.cpp └── print-specific-level.cpp /Examples/c++/BinarySearchTree/BST.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct Node 5 | { 6 | Node *left; 7 | Node *right; 8 | int value; 9 | Node(int value) 10 | { 11 | this->value = value; 12 | this->left = NULL; 13 | this->right = NULL; 14 | } 15 | }; 16 | 17 | class BST 18 | { 19 | private: 20 | Node* root; 21 | 22 | Node* find(Node* curNode, int value) 23 | { 24 | if(curNode == NULL) 25 | return NULL; 26 | if(curNode->value == value) 27 | return curNode; 28 | if(curNode->value < value) 29 | return find(curNode->right, value); 30 | return find(curNode->left, value); 31 | } 32 | 33 | Node* insert(Node *curNode, int value) 34 | { 35 | if(curNode == NULL) 36 | { 37 | return new Node(value); 38 | } 39 | if(curNode->value < value) 40 | { 41 | curNode->right = insert(curNode->right, value); 42 | } 43 | else 44 | { 45 | curNode->left = insert(curNode->left, value); 46 | } 47 | return curNode; 48 | } 49 | 50 | Node* remove(Node* curNode, int value) 51 | { 52 | if(curNode == NULL) 53 | { 54 | return NULL; 55 | } 56 | if(curNode->value < value) 57 | { 58 | curNode->right = remove(curNode->right, value); 59 | } 60 | else if(curNode->value > value) 61 | { 62 | curNode->left = remove(curNode->left, value); 63 | } 64 | else 65 | { 66 | if(curNode->left == NULL) 67 | { 68 | Node* tmp = curNode->right; 69 | delete curNode; 70 | return tmp; 71 | } 72 | Node* maxInLeftSubTree = findMax(curNode->left); 73 | curNode->value = maxInLeftSubTree->value; 74 | curNode->left = remove(curNode->left, curNode->value); 75 | } 76 | return curNode; 77 | } 78 | 79 | void printSorted(Node *root) 80 | { 81 | if(root == NULL) 82 | { 83 | return; 84 | } 85 | printSorted(root->left); 86 | cout<value<<" "; 87 | printSorted(root->right); 88 | } 89 | 90 | Node* findMax(Node *root) 91 | { 92 | if(root->right != NULL) 93 | { 94 | return findMax(root->right); 95 | } 96 | return root; 97 | } 98 | 99 | Node* findMin(Node *root) 100 | { 101 | if(root->left != NULL) 102 | { 103 | return findMin(root->left); 104 | } 105 | return root; 106 | } 107 | 108 | Node* lowerBound(Node* root, int value) 109 | { 110 | if(root == NULL) 111 | { 112 | return NULL; 113 | } 114 | else if(root->value == value) 115 | { 116 | return root; 117 | } 118 | else if(root->value < value) 119 | { 120 | return lowerBound(root->right, value); 121 | } 122 | else 123 | { 124 | Node* tmp = lowerBound(root->left, value); 125 | if(tmp != NULL) 126 | return tmp; 127 | else 128 | return root; 129 | } 130 | } 131 | 132 | public: 133 | BST() 134 | { 135 | root = NULL; 136 | } 137 | void insert(int value) 138 | { 139 | if(root == NULL) 140 | { 141 | root = new Node(value); 142 | } 143 | else 144 | { 145 | insert(root, value); 146 | } 147 | } 148 | void remove(int value) 149 | { 150 | root = remove(root, value); 151 | } 152 | bool exists(int value) 153 | { 154 | return find(root, value) != NULL; 155 | } 156 | int findMin() 157 | { 158 | if(root == NULL) 159 | return -1; 160 | return findMin(root)->value; 161 | } 162 | int findMax() 163 | { 164 | if(root == NULL) 165 | return -1; 166 | return findMax(root)->value; 167 | } 168 | int lowerBound(int value) 169 | { 170 | Node* lb = lowerBound(root, value); 171 | if(lb == NULL) 172 | return -1; 173 | else return lb->value; 174 | } 175 | void printSorted() 176 | { 177 | printSorted(root); 178 | } 179 | 180 | }; 181 | 182 | int main() 183 | { 184 | 185 | } 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /Examples/c++/Graph Algorithms/directed-unweighted-topological-sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct Node { 7 | list neighbours; 8 | 9 | bool hasNeighbour(int index) { 10 | for (auto i : neighbours) { 11 | if (i == index) { 12 | return true; 13 | } 14 | } 15 | return false; 16 | } 17 | 18 | void addNeighbour(int index) { 19 | neighbours.push_back(index); 20 | } 21 | }; 22 | 23 | struct Edge { 24 | int from; 25 | int to; 26 | }; 27 | 28 | class Graph { 29 | private: 30 | vector nodes; 31 | 32 | void _topologicalSort(list& sorted, vector& visited, int start) const { 33 | visited[start] = 'o'; 34 | for (auto neighbour : nodes[start].neighbours) { 35 | if (visited[neighbour] == 'u') { 36 | _topologicalSort(sorted, visited, neighbour); 37 | } else if (visited[neighbour] == 'o') { 38 | cout << "Found cycle going through nodes " << start << " and " << neighbour << "\n"; 39 | } 40 | } 41 | visited[start] = 'c'; 42 | sorted.push_front(start); 43 | } 44 | 45 | public: 46 | Graph(int nodeCount = 0) { 47 | nodes.resize(nodeCount); 48 | } 49 | 50 | void print() const { 51 | for (int node = 0; node < nodes.size(); node++) { 52 | cout << node << ": "; 53 | for (auto neighbour : nodes[node].neighbours) { 54 | cout << neighbour << ", "; 55 | } 56 | cout << "\n"; 57 | } 58 | } 59 | 60 | void connect(int from, int to) { 61 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 62 | nodes[from].addNeighbour(to); 63 | } 64 | } 65 | 66 | list topologicalSort() const { 67 | list sorted; 68 | // 'o' for open, 'c' for closed, 'u' for unvisited 69 | // open = the node is in the stack of DFS 70 | // closed = the node is not in the stack of DFS 71 | // unvisited = we have never gone to that node 72 | vector visited(nodes.size(), 'u'); 73 | 74 | for (int i = 0; i < nodes.size(); i++) { 75 | if (visited[i] == 'u') { 76 | _topologicalSort(sorted, visited, i); 77 | } 78 | } 79 | 80 | return sorted; 81 | } 82 | }; 83 | 84 | int main() { 85 | Graph g(5); 86 | g.connect(4, 3); 87 | g.connect(4, 2); 88 | g.connect(1, 3); 89 | g.connect(2, 0); 90 | // g.connect(0, 4); // Adds a cycle 91 | 92 | list sorted = g.topologicalSort(); 93 | for (auto i : sorted) { 94 | cout << i << " "; 95 | } 96 | cout << "\n"; 97 | } -------------------------------------------------------------------------------- /Examples/c++/Graph Algorithms/directed-weighted-BellmanFord.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | struct Pair { 9 | int index; 10 | int distance; 11 | 12 | bool operator<(const Pair & rhs) const { 13 | return distance > rhs.distance; 14 | } 15 | }; 16 | 17 | struct Edge { 18 | int from; 19 | int to; 20 | int distance; 21 | }; 22 | 23 | struct Node { 24 | list neighbours; 25 | 26 | bool hasNeighbour(int index) { 27 | for (auto neighbour : neighbours) { 28 | if (neighbour.index == index) { 29 | return true; 30 | } 31 | } 32 | return false; 33 | } 34 | 35 | void addNeighbour(int index, int distance) { 36 | neighbours.push_back(Pair{ index, distance }); 37 | } 38 | }; 39 | 40 | class Graph { 41 | private: 42 | vector nodes; 43 | 44 | public: 45 | Graph(int nodeCount = 0) { 46 | nodes.resize(nodeCount); 47 | } 48 | 49 | void print() const { 50 | for (int node = 0; node < nodes.size(); node++) { 51 | cout << node << ": "; 52 | for (auto neighbour : nodes[node].neighbours) { 53 | cout << neighbour.index << "(" << neighbour.distance << "), "; 54 | } 55 | cout << "\n"; 56 | } 57 | } 58 | 59 | void connect(int from, int to, int distance) { 60 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 61 | nodes[from].addNeighbour(to, distance); 62 | } 63 | } 64 | 65 | vector getAllEdges() const { 66 | vector edges; 67 | 68 | for (int from = 0; from < nodes.size(); from++) { 69 | for (auto neighbour : nodes[from].neighbours) { 70 | int to = neighbour.index; 71 | int distance = neighbour.distance; 72 | edges.push_back(Edge{ from, to, distance }); 73 | } 74 | } 75 | 76 | return edges; 77 | } 78 | 79 | list bellmanFord(int start) const { 80 | vector allEdges = getAllEdges(); 81 | list tree; 82 | 83 | vector distance(nodes.size(), INT_MAX); 84 | vector parent(nodes.size(), -1); 85 | 86 | distance[start] = 0; 87 | for (int i = 0; i < nodes.size() - 1; i++) { 88 | for (auto edge : allEdges) { 89 | int alternativeDistance = distance[edge.from] + edge.distance; 90 | if (alternativeDistance < distance[edge.to]) { 91 | distance[edge.to] = alternativeDistance; 92 | parent[edge.to] = edge.from; 93 | } 94 | } 95 | } 96 | 97 | // Check for negative cycles (do 1 more relaxation round) 98 | for (auto edge : allEdges) { 99 | int alternativeDistance = distance[edge.from] + edge.distance; 100 | if (alternativeDistance < distance[edge.to]) { 101 | cout << "Negative cycle found\n"; 102 | break; 103 | } 104 | } 105 | 106 | for (int i = 0; i < parent.size() ; i++) { 107 | if (parent[i] != -1) { 108 | int directDistance = distance[i] - distance[parent[i]]; 109 | tree.push_back({parent[i], i, directDistance}); 110 | } 111 | } 112 | 113 | return tree; 114 | } 115 | }; 116 | 117 | int main() { 118 | Graph g(4); 119 | g.connect(0, 1, 5); 120 | g.connect(1, 0, 3); 121 | g.connect(1, 2, 2); 122 | g.connect(1, 3, 10); 123 | g.connect(2, 1, 21); 124 | g.connect(3, 1, 9); 125 | g.connect(3, 2, 1); 126 | g.connect(0, 3, 2); 127 | 128 | list tree = g.bellmanFord(0); 129 | cout << "Bellman-Ford tree:\n"; 130 | for (Edge edge : tree) { 131 | cout << edge.from << "-" << edge.to << "(" << edge.distance << ")\n"; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /Examples/c++/Graph Algorithms/directed-weighted-Dijkstra.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | struct Pair { 9 | int index; 10 | int distance; 11 | 12 | bool operator<(const Pair & rhs) const { 13 | return distance > rhs.distance; 14 | } 15 | }; 16 | 17 | struct Edge { 18 | int from; 19 | int to; 20 | int weight; 21 | }; 22 | 23 | struct Node { 24 | list neighbours; 25 | 26 | bool hasNeighbour(int index) { 27 | for (auto neighbour : neighbours) { 28 | if (neighbour.index == index) { 29 | return true; 30 | } 31 | } 32 | return false; 33 | } 34 | 35 | void addNeighbour(int index, int distance) { 36 | neighbours.push_back(Pair{ index, distance }); 37 | } 38 | }; 39 | 40 | class Graph { 41 | private: 42 | vector nodes; 43 | 44 | public: 45 | Graph(int nodeCount = 0) { 46 | nodes.resize(nodeCount); 47 | } 48 | 49 | void print() const { 50 | for (int node = 0; node < nodes.size(); node++) { 51 | cout << node << ": "; 52 | for (auto neighbour : nodes[node].neighbours) { 53 | cout << neighbour.index << "(" << neighbour.distance << "), "; 54 | } 55 | cout << "\n"; 56 | } 57 | } 58 | 59 | void connect(int from, int to, int distance) { 60 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 61 | nodes[from].addNeighbour(to, distance); 62 | } 63 | } 64 | 65 | list dijkstra(int start) const { 66 | if (nodes.size() < 1) { 67 | return list(); 68 | } 69 | 70 | // parent[i] will hold the index of the parent node 71 | vector parent(nodes.size(), -1); 72 | // distance[i] will hold the total distance to the i-th node 73 | vector distance(nodes.size(), INT_MAX); 74 | // visited[i] will be a marker if we've been to this node before 75 | vector visited(nodes.size(), false); 76 | 77 | distance[start] = 0; 78 | // Holds the next node to process with the distance required to reach it 79 | priority_queue nextToProcess; 80 | nextToProcess.push({start, 0}); 81 | while (!nextToProcess.empty()) { 82 | Pair currentPair = nextToProcess.top(); 83 | nextToProcess.pop(); 84 | int currentNode = currentPair.index; 85 | 86 | // If we've been in this node before skip it 87 | if (visited[currentNode]) { 88 | continue; 89 | } 90 | visited[currentNode] = true; 91 | 92 | // For each neighbour check if we have a better potential route from the current node 93 | for (auto neighbour : nodes[currentNode].neighbours) { 94 | int neighbourNode = neighbour.index; 95 | int alternativeDistance = distance[currentNode] + neighbour.distance; 96 | if (alternativeDistance < distance[neighbourNode]) { 97 | distance[neighbourNode] = alternativeDistance; 98 | parent[neighbourNode] = currentNode; 99 | nextToProcess.push({neighbourNode, alternativeDistance}); 100 | } 101 | } 102 | } 103 | 104 | // cout << "Distances: \n"; 105 | // for (auto i : distance) { 106 | // cout << i << " "; 107 | // } 108 | // cout << "\n"; 109 | 110 | // cout << "Parents: \n"; 111 | // for (auto i : parent) { 112 | // cout << i << " "; 113 | // } 114 | // cout << "\n"; 115 | 116 | // Construct tree from the edges participating in the Dijkstra traversal 117 | list tree; 118 | for (int i = 0; i < parent.size() ; i++) { 119 | if (parent[i] != -1) { 120 | int directDistance = distance[i] - distance[parent[i]]; 121 | tree.push_back({parent[i], i, directDistance}); 122 | } 123 | } 124 | 125 | return tree; 126 | } 127 | }; 128 | 129 | int main() { 130 | Graph g(4); 131 | g.connect(0, 1, 5); 132 | g.connect(1, 0, 3); 133 | g.connect(1, 2, 2); 134 | g.connect(1, 3, 10); 135 | g.connect(2, 1, 21); 136 | g.connect(3, 1, 9); 137 | g.connect(3, 2, 1); 138 | g.connect(0, 3, 2); 139 | 140 | list tree = g.dijkstra(0); 141 | cout << "Dijkstra tree:\n"; 142 | for (Edge edge : tree) { 143 | cout << edge.from << "-" << edge.to << "(" << edge.weight << ")\n"; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /Examples/c++/Graph Algorithms/undirected-unweighted-DFS.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct Node { 7 | list neighbours; 8 | 9 | bool hasNeighbour(int index) { 10 | for (auto i : neighbours) { 11 | if (i == index) { 12 | return true; 13 | } 14 | } 15 | return false; 16 | } 17 | 18 | void addNeighbour(int index) { 19 | neighbours.push_back(index); 20 | } 21 | }; 22 | 23 | class Graph { 24 | private: 25 | vector nodes; 26 | 27 | void _DFS(int current, vector & visited) { 28 | cout << current << ", "; 29 | visited[current] = true; 30 | 31 | for (auto neighbour : nodes[current].neighbours) { 32 | if (!visited[neighbour]) { 33 | _DFS(neighbour, visited); 34 | } 35 | } 36 | } 37 | 38 | public: 39 | Graph(int nodeCount = 0) { 40 | nodes.resize(nodeCount); 41 | } 42 | 43 | void print() const { 44 | for (int node = 0; node < nodes.size(); node++) { 45 | cout << node << ": "; 46 | for (auto neighbour : nodes[node].neighbours) { 47 | cout << neighbour << ", "; 48 | } 49 | cout << "\n"; 50 | } 51 | } 52 | 53 | void connect(int from, int to) { 54 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 55 | nodes[from].addNeighbour(to); 56 | nodes[to].addNeighbour(from); // remove this to make the graph directed 57 | } 58 | } 59 | 60 | void DFSAll() { // For disjoint union of graphs 61 | vector visited; 62 | visited.resize(nodes.size(), false); 63 | 64 | for (int start = 0; start < nodes.size(); start++) { 65 | if (!visited[start]) { 66 | _DFS(start, visited); 67 | } 68 | } 69 | } 70 | 71 | void DFS(int start) { // Traverse the component this node belongs to 72 | vector visited; 73 | visited.resize(nodes.size(), false); 74 | 75 | _DFS(start, visited); 76 | } 77 | }; 78 | 79 | int main() { 80 | Graph g(4); 81 | g.connect(0, 1); 82 | g.connect(1, 0); 83 | g.connect(1, 2); 84 | g.connect(1, 3); 85 | g.connect(2, 1); 86 | g.connect(3, 1); 87 | g.connect(3, 2); 88 | 89 | g.DFS(3); 90 | } -------------------------------------------------------------------------------- /Examples/c++/Graph Algorithms/undirected-weighted-Kruskal-using-disjoint-set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | class DisjointSet { 9 | private: 10 | unordered_map parent; 11 | // currentLastTree starts from 0 because our nodes start from 0 12 | int currentLastTree = 0; 13 | public: 14 | void add(int child) { 15 | parent[child] = currentLastTree; 16 | currentLastTree++; 17 | } 18 | 19 | int find(int child) { // Returns root of the tree the node belongs to 20 | if (parent[child] == child) { 21 | return child; 22 | } 23 | // Make the parent of each node be the root of the tree to reduce height 24 | int root = find(parent[child]); 25 | parent[child] = root; 26 | return root; 27 | } 28 | 29 | void unite(int a, int b) { // Combines two trees by making the root of one be the root for the other as well 30 | int aRoot = find(a); 31 | int bRoot = find(b); 32 | parent[aRoot] = bRoot; 33 | } 34 | 35 | void initialize(int nodeCount) { 36 | for (int i = 0; i < nodeCount; i++) { 37 | add(i); 38 | } 39 | } 40 | }; 41 | 42 | struct Pair { 43 | int index; 44 | int weight; 45 | }; 46 | 47 | struct Node { 48 | list neighbours; 49 | 50 | bool hasNeighbour(int index) { 51 | for (auto neighbour : neighbours) { 52 | if (neighbour.index == index) { 53 | return true; 54 | } 55 | } 56 | return false; 57 | } 58 | 59 | void addNeighbour(int index, int weight) { 60 | neighbours.push_back(Pair{ index, weight }); 61 | } 62 | }; 63 | 64 | struct Edge { 65 | int from; 66 | int to; 67 | int weight; 68 | 69 | bool operator<(const Edge& rhs) const { 70 | return weight < rhs.weight; 71 | } 72 | }; 73 | 74 | class Graph { 75 | private: 76 | vector nodes; 77 | 78 | public: 79 | Graph(int nodeCount = 0) { 80 | nodes.resize(nodeCount); 81 | } 82 | 83 | void print() const { 84 | for (int node = 0; node < nodes.size(); node++) { 85 | cout << node << ": "; 86 | for (auto neighbour : nodes[node].neighbours) { 87 | cout << neighbour.index << "(" << neighbour.weight << "), "; 88 | } 89 | cout << "\n"; 90 | } 91 | } 92 | 93 | void connect(int from, int to, int weight) { 94 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 95 | nodes[from].addNeighbour(to, weight); 96 | nodes[to].addNeighbour(from, weight); 97 | } 98 | } 99 | 100 | vector getAllEdges() const { 101 | vector edges; 102 | 103 | for (int from = 0; from < nodes.size(); from++) { 104 | for (auto neighbour : nodes[from].neighbours) { 105 | int to = neighbour.index; 106 | int weight = neighbour.weight; 107 | if (from < to) { 108 | edges.push_back(Edge{ from, to, weight }); 109 | } 110 | } 111 | } 112 | 113 | return edges; 114 | } 115 | 116 | list kruskal() const { 117 | vector allEdges = getAllEdges(); 118 | sort(allEdges.begin(), allEdges.end()); 119 | 120 | list tree; 121 | 122 | DisjointSet components; 123 | components.initialize(nodes.size()); 124 | 125 | for (Edge edge : allEdges) { 126 | if (components.find(edge.from) != components.find(edge.to)) { 127 | tree.push_back(edge); 128 | components.unite(edge.from, edge.to); 129 | } 130 | } 131 | 132 | return tree; 133 | } 134 | }; 135 | 136 | int main() { 137 | Graph g(4); 138 | g.connect(0, 1, 5); 139 | g.connect(1, 2, 2); 140 | g.connect(1, 3, 8); 141 | g.connect(2, 0, 4); 142 | g.connect(2, 3, 3); 143 | g.connect(3, 0, 10); 144 | 145 | list spanningTree = g.kruskal(); 146 | for (Edge edge : spanningTree) { 147 | cout << edge.from << "-" << edge.to << "(" << edge.weight << ")\n"; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Examples/c++/Graph Algorithms/undirected-weighted-Kruskal-using-vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct Pair { 8 | int index; 9 | int weight; 10 | }; 11 | 12 | struct Node { 13 | list neighbours; 14 | 15 | bool hasNeighbour(int index) { 16 | for (auto neighbour : neighbours) { 17 | if (neighbour.index == index) { 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | 24 | void addNeighbour(int index, int weight) { 25 | neighbours.push_back(Pair{ index, weight }); 26 | } 27 | }; 28 | 29 | struct Edge { 30 | int from; 31 | int to; 32 | int weight; 33 | 34 | bool operator<(const Edge& rhs) const { 35 | return weight < rhs.weight; 36 | } 37 | }; 38 | 39 | class Graph { 40 | private: 41 | vector nodes; 42 | 43 | public: 44 | Graph(int nodeCount = 0) { 45 | nodes.resize(nodeCount); 46 | } 47 | 48 | void print() const { 49 | for (int node = 0; node < nodes.size(); node++) { 50 | cout << node << ": "; 51 | for (auto neighbour : nodes[node].neighbours) { 52 | cout << neighbour.index << "(" << neighbour.weight << "), "; 53 | } 54 | cout << "\n"; 55 | } 56 | } 57 | 58 | void connect(int from, int to, int weight) { 59 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 60 | nodes[from].addNeighbour(to, weight); 61 | nodes[to].addNeighbour(from, weight); 62 | } 63 | } 64 | 65 | vector getAllEdges() const { 66 | vector edges; 67 | 68 | for (int from = 0; from < nodes.size(); from++) { 69 | for (auto neighbour : nodes[from].neighbours) { 70 | int to = neighbour.index; 71 | int weight = neighbour.weight; 72 | if (from < to) { 73 | edges.push_back(Edge{ from, to, weight }); 74 | } 75 | } 76 | } 77 | 78 | return edges; 79 | } 80 | 81 | list kruskal() const { 82 | if (nodes.size() < 1) { 83 | return list(); 84 | } 85 | 86 | vector allEdges = getAllEdges(); 87 | sort(allEdges.begin(), allEdges.end()); 88 | 89 | list tree; 90 | vector components; 91 | components.resize(nodes.size()); 92 | 93 | for (int i = 0; i < nodes.size() + 1; i++) { 94 | components[i] = i; 95 | } 96 | 97 | for (Edge edge : allEdges) { 98 | if (components[edge.from] != components[edge.to]) { 99 | tree.push_back(edge); 100 | int oldComponent = components[edge.from]; 101 | int newComponent = components[edge.to]; 102 | for (int i = 0; i < components.size(); i++) { 103 | if (components[i] == oldComponent) 104 | components[i] = newComponent; 105 | } 106 | } 107 | } 108 | 109 | return tree; 110 | } 111 | }; 112 | 113 | int main() { 114 | Graph g(4); 115 | g.connect(0, 1, 5); 116 | g.connect(1, 2, 2); 117 | g.connect(1, 3, 8); 118 | g.connect(2, 0, 4); 119 | g.connect(2, 3, 3); 120 | g.connect(3, 0, 10); 121 | 122 | list spanningTree = g.kruskal(); 123 | for (Edge edge : spanningTree) { 124 | cout << edge.from << "-" << edge.to << "(" << edge.weight << ")\n"; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Examples/c++/Graph Algorithms/undirected-weighted-Prim.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | struct Pair { 10 | int index; 11 | int distance; 12 | }; 13 | 14 | struct Node { 15 | list neighbours; 16 | 17 | bool hasNeighbour(int index) { 18 | for (auto neighbour : neighbours) { 19 | if (neighbour.index == index) { 20 | return true; 21 | } 22 | } 23 | return false; 24 | } 25 | 26 | void addNeighbour(int index, int distance) { 27 | neighbours.push_back(Pair{ index, distance }); 28 | } 29 | }; 30 | 31 | struct Edge { 32 | int from; 33 | int to; 34 | int distance; 35 | 36 | bool operator<(const Edge& rhs) const { 37 | return distance > rhs.distance; 38 | } 39 | }; 40 | 41 | class Graph { 42 | private: 43 | vector nodes; 44 | 45 | public: 46 | Graph(int nodeCount = 0) { 47 | nodes.resize(nodeCount); 48 | } 49 | 50 | void print() const { 51 | for (int node = 0; node < nodes.size(); node++) { 52 | cout << node << ": "; 53 | for (auto neighbour : nodes[node].neighbours) { 54 | cout << neighbour.index << "(" << neighbour.distance << "), "; 55 | } 56 | cout << "\n"; 57 | } 58 | } 59 | 60 | void connect(int from, int to, int distance) { 61 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 62 | nodes[from].addNeighbour(to, distance); 63 | nodes[to].addNeighbour(from, distance); 64 | } 65 | } 66 | 67 | vector getAllEdges() const { 68 | vector edges; 69 | 70 | for (int from = 0; from < nodes.size(); from++) { 71 | for (auto neighbour : nodes[from].neighbours) { 72 | int to = neighbour.index; 73 | int distance = neighbour.distance; 74 | if (from < to) { 75 | edges.push_back(Edge{ from, to, distance }); 76 | } 77 | } 78 | } 79 | 80 | return edges; 81 | } 82 | 83 | list prim() const { 84 | if (nodes.size() < 1) { 85 | return list(); 86 | } 87 | 88 | // distance[i] will hold the total distance to the i-th node 89 | vector distance(nodes.size(), INT_MAX); 90 | // added[i] will be a marker if we've added the node to the tree 91 | vector added(nodes.size(), false); 92 | 93 | list tree; 94 | distance[0] = 0; 95 | priority_queue nextToProcess; 96 | nextToProcess.push({-1, 0, 0}); // start from the 0th node with no parent 97 | 98 | while (!nextToProcess.empty()) { 99 | Edge nextBest = nextToProcess.top(); 100 | nextToProcess.pop(); 101 | int currentNode = nextBest.to; 102 | 103 | if (added[currentNode]) { 104 | continue; 105 | } 106 | added[currentNode] = true; 107 | 108 | int parent = nextBest.from; 109 | int minDistance = nextBest.distance; 110 | 111 | if (parent != -1) { // It's not the 0th node 112 | tree.push_back({parent, currentNode, minDistance}); 113 | } 114 | 115 | for (auto neighbour : nodes[currentNode].neighbours) { 116 | nextToProcess.push({currentNode, neighbour.index, neighbour.distance}); 117 | } 118 | } 119 | 120 | return tree; 121 | } 122 | }; 123 | 124 | int main() { 125 | Graph g(4); 126 | g.connect(0, 1, 5); 127 | g.connect(1, 2, 2); 128 | g.connect(1, 3, 8); 129 | g.connect(2, 0, 4); 130 | g.connect(2, 3, 3); 131 | g.connect(3, 0, 10); 132 | 133 | list spanningTree = g.prim(); 134 | for (Edge edge : spanningTree) { 135 | cout << edge.from << "-" << edge.to << "(" << edge.distance << ")\n"; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Examples/c++/Graph/directed-unweighted-graph-using-list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct Node { 7 | list neighbours; 8 | 9 | bool hasNeighbour(int index) { 10 | for (auto i : neighbours) { 11 | if (i == index) { 12 | return true; 13 | } 14 | } 15 | return false; 16 | } 17 | 18 | void addNeighbour(int index) { 19 | neighbours.push_back(index); 20 | } 21 | }; 22 | 23 | class Graph { 24 | private: 25 | vector nodes; 26 | 27 | public: 28 | Graph(int nodeCount = 0) { 29 | nodes.resize(nodeCount); 30 | } 31 | 32 | void print() const { 33 | for (int node = 0; node < nodes.size(); node++) { 34 | cout << node << ": "; 35 | for (auto neighbour : nodes[node].neighbours) { 36 | cout << neighbour << ", "; 37 | } 38 | cout << "\n"; 39 | } 40 | } 41 | 42 | void connect(int from, int to) { 43 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 44 | nodes[from].addNeighbour(to); 45 | } 46 | } 47 | }; 48 | 49 | int main() { 50 | Graph g(4); 51 | g.connect(0, 1); 52 | g.connect(1, 0); 53 | g.connect(1, 2); 54 | g.connect(1, 3); 55 | g.connect(2, 1); 56 | g.connect(3, 1); 57 | g.connect(3, 2); 58 | 59 | g.print(); 60 | } -------------------------------------------------------------------------------- /Examples/c++/Graph/directed-weighted-graph-using-list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct Pair { 7 | int index; 8 | int weight; 9 | }; 10 | 11 | struct Node { 12 | list neighbours; 13 | 14 | bool hasNeighbour(int index) { 15 | for (auto neighbour : neighbours) { 16 | if (neighbour.index == index) { 17 | return true; 18 | } 19 | } 20 | return false; 21 | } 22 | 23 | void addNeighbour(int index, int weight) { 24 | neighbours.push_back(Pair{ index, weight }); 25 | } 26 | }; 27 | 28 | class Graph { 29 | private: 30 | vector nodes; 31 | 32 | public: 33 | Graph(int nodeCount = 0) { 34 | nodes.resize(nodeCount); 35 | } 36 | 37 | void print() const { 38 | for (int node = 0; node < nodes.size(); node++) { 39 | cout << node << ": "; 40 | for (auto neighbour : nodes[node].neighbours) { 41 | cout << neighbour.index << "(" << neighbour.weight << "), "; 42 | } 43 | cout << "\n"; 44 | } 45 | } 46 | 47 | void connect(int from, int to, int weight) { 48 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 49 | nodes[from].addNeighbour(to, weight); 50 | } 51 | } 52 | }; 53 | 54 | int main() { 55 | Graph g(4); 56 | g.connect(0, 1, 5); 57 | g.connect(1, 0, 3); 58 | g.connect(1, 2, 2); 59 | g.connect(1, 3, 10); 60 | g.connect(2, 1, 21); 61 | g.connect(3, 1, 9); 62 | g.connect(3, 2, 1); 63 | 64 | g.print(); 65 | } 66 | -------------------------------------------------------------------------------- /Examples/c++/Graph/directed-weighted-graph-using-matrix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class Graph { 6 | private: 7 | vector> adjacencyMatrix; 8 | 9 | public: 10 | Graph(int nodeCount) { 11 | adjacencyMatrix.resize(nodeCount); 12 | for (int row = 0; row < adjacencyMatrix.size(); row++) { 13 | adjacencyMatrix[row].resize(nodeCount); 14 | for (int col = 0; col < adjacencyMatrix.size(); col++) { 15 | adjacencyMatrix[row][col] = 0; // 0 means there is no connection 16 | } 17 | } 18 | } 19 | 20 | void print() const { 21 | for (auto neighbours : adjacencyMatrix) { 22 | for (auto neighbour : neighbours) { 23 | cout << neighbour << " "; 24 | } 25 | cout << "\n"; 26 | } 27 | } 28 | 29 | void connect(int from, int to, int weight = 1) { 30 | // The outer vector contains the node where we start 31 | // The inner vector contains the weight to each neighbour 32 | adjacencyMatrix[from][to] = weight; 33 | 34 | // If the graph wasn't directed we would need to uncomment the row below 35 | // adjacencyMatrix[to][from] = weight; 36 | } 37 | }; 38 | 39 | int main() { 40 | Graph g(4); 41 | // By not specifying weight of each edge the graph becomes unweighted 42 | g.connect(0, 1); 43 | g.connect(1, 0); 44 | g.connect(1, 2); 45 | g.connect(1, 3); 46 | g.connect(2, 1); 47 | g.connect(3, 1); 48 | g.connect(3, 2); 49 | 50 | g.print(); 51 | } -------------------------------------------------------------------------------- /Examples/c++/Graph/undirected-unweighted-graph-using-list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct Node { 7 | list neighbours; 8 | 9 | bool hasNeighbour(int index) { 10 | for (auto i : neighbours) { 11 | if (i == index) { 12 | return true; 13 | } 14 | } 15 | return false; 16 | } 17 | 18 | void addNeighbour(int index) { 19 | neighbours.push_back(index); 20 | } 21 | }; 22 | 23 | class Graph { 24 | private: 25 | vector nodes; 26 | 27 | public: 28 | Graph(int nodeCount = 0) { 29 | nodes.resize(nodeCount); 30 | } 31 | 32 | void print() const { 33 | for (int node = 0; node < nodes.size(); node++) { 34 | cout << node << ": "; 35 | for (auto neighbour : nodes[node].neighbours) { 36 | cout << neighbour << ", "; 37 | } 38 | cout << "\n"; 39 | } 40 | } 41 | 42 | void connect(int from, int to) { 43 | if (!nodes[from].hasNeighbour(to)) { // remove this check to make it multigraph 44 | nodes[from].addNeighbour(to); 45 | nodes[to].addNeighbour(from); 46 | } 47 | } 48 | }; 49 | 50 | int main() { 51 | Graph g(4); 52 | g.connect(0, 1); 53 | g.connect(1, 0); 54 | g.connect(1, 2); 55 | g.connect(1, 3); 56 | g.connect(2, 1); 57 | g.connect(3, 1); 58 | g.connect(3, 2); 59 | 60 | g.print(); 61 | } -------------------------------------------------------------------------------- /Examples/c++/Hashtable/hashtable-using-balanced-tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | class Hashtable { 8 | private: 9 | const int START_SIZE = 10; 10 | 11 | vector> table; 12 | int itemCount = 0; 13 | 14 | int hash(int value, int size) const { 15 | return value % size; 16 | } 17 | 18 | bool listContains(int list, int value) const { 19 | return table[list].count(value) == 1; 20 | } 21 | 22 | double calculateLoadFactor() const { 23 | return double(itemCount) / table.size(); 24 | } 25 | 26 | bool isGrowingNeeded() const { 27 | double loadFactor = calculateLoadFactor(); 28 | return loadFactor > 0.65; 29 | } 30 | 31 | void growHashtable() { 32 | vector> newTable; 33 | newTable.resize(table.size() * 2); 34 | for (auto list : table) { 35 | for (auto element : list) { 36 | int listIndex = hash(element, newTable.size()); // recalculated hash 37 | newTable[listIndex].insert(element); 38 | } 39 | } 40 | 41 | table = newTable; 42 | } 43 | 44 | bool isShrinkingNeeded() const { 45 | double loadFactor = calculateLoadFactor(); 46 | return loadFactor < 0.3 && table.size() > 10; 47 | } 48 | 49 | void shrinkHashtable() { 50 | vector> newTable; 51 | newTable.resize(table.size() / 2); 52 | for (auto list : table) { 53 | for (auto element : list) { 54 | int listIndex = hash(element, newTable.size()); // recalculated hash 55 | newTable[listIndex].insert(element); 56 | } 57 | } 58 | 59 | table = newTable; 60 | } 61 | 62 | public: 63 | Hashtable() { 64 | table.resize(START_SIZE); 65 | } 66 | 67 | void insert(int value) { 68 | int listIndex = hash(value, table.size()); // hash 69 | if (!listContains(listIndex, value)) { 70 | table[listIndex].insert(value); 71 | itemCount++; 72 | 73 | if (isGrowingNeeded()) { 74 | growHashtable(); 75 | } 76 | } 77 | } 78 | 79 | bool contains(int value) const { 80 | int listIndex = hash(value, table.size()); // hash 81 | return listContains(listIndex, value); 82 | } 83 | 84 | void remove(int value) { 85 | int listIndex = hash(value, table.size()); // hash 86 | int oldListSize = table[listIndex].size(); 87 | 88 | table[listIndex].erase(value); 89 | 90 | if (table[listIndex].size() != oldListSize) { 91 | itemCount--; 92 | } 93 | 94 | if (isShrinkingNeeded()) { 95 | shrinkHashtable(); 96 | } 97 | } 98 | 99 | void print() const { 100 | for (auto list : table) { 101 | for (auto element : list) { 102 | cout << element << ", "; 103 | } 104 | } 105 | cout << "\n"; 106 | } 107 | }; 108 | 109 | int main() { 110 | Hashtable t; 111 | t.insert(1); 112 | t.insert(5); 113 | t.insert(12); 114 | t.insert(13); 115 | 116 | t.insert(15); 117 | t.remove(15); 118 | 119 | t.print(); 120 | } 121 | -------------------------------------------------------------------------------- /Examples/c++/Hashtable/hashtable-using-lists.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | class Hashtable { 8 | private: 9 | const int START_SIZE = 10; 10 | 11 | vector> table; 12 | int itemCount = 0; 13 | 14 | int hash(int value, int size) const { 15 | return value % size; 16 | } 17 | 18 | bool listContains(int list, int value) const { 19 | return find(table[list].begin(), table[list].end(), value) != table[list].end(); 20 | } 21 | 22 | double calculateLoadFactor() const { 23 | return double(itemCount) / table.size(); 24 | } 25 | 26 | bool isGrowingNeeded() const { 27 | double loadFactor = calculateLoadFactor(); 28 | return loadFactor > 0.65; 29 | } 30 | 31 | void growHashtable() { 32 | vector> newTable; 33 | newTable.resize(table.size() * 2); 34 | for (auto list : table) { 35 | for (auto element : list) { 36 | int listIndex = hash(element, newTable.size()); // recalculated hash 37 | newTable[listIndex].push_back(element); 38 | } 39 | } 40 | 41 | table = newTable; 42 | } 43 | 44 | bool isShrinkingNeeded() const { 45 | double loadFactor = calculateLoadFactor(); 46 | return loadFactor < 0.3 && table.size() > 10; 47 | } 48 | 49 | void shrinkHashtable() { 50 | vector> newTable; 51 | newTable.resize(table.size() / 2); 52 | for (auto list : table) { 53 | for (auto element : list) { 54 | int listIndex = hash(element, newTable.size()); // recalculated hash 55 | newTable[listIndex].push_back(element); 56 | } 57 | } 58 | 59 | table = newTable; 60 | } 61 | 62 | public: 63 | Hashtable() { 64 | table.resize(START_SIZE); 65 | } 66 | 67 | void insert(int value) { 68 | int listIndex = hash(value, table.size()); // hash 69 | if (!listContains(listIndex, value)) { 70 | table[listIndex].push_back(value); 71 | itemCount++; 72 | 73 | if (isGrowingNeeded()) { 74 | growHashtable(); 75 | } 76 | } 77 | } 78 | 79 | bool contains(int value) const { 80 | int listIndex = hash(value, table.size()); // hash 81 | return listContains(listIndex, value); 82 | } 83 | 84 | void remove(int value) { 85 | int listIndex = hash(value, table.size()); // hash 86 | int oldListSize = table[listIndex].size(); 87 | 88 | table[listIndex].remove(value); 89 | 90 | if (table[listIndex].size() != oldListSize) { 91 | itemCount--; 92 | } 93 | 94 | if (isShrinkingNeeded()) { 95 | shrinkHashtable(); 96 | } 97 | } 98 | 99 | void print() const { 100 | for (auto list : table) { 101 | for (auto element : list) { 102 | cout << element << ", "; 103 | } 104 | } 105 | cout << "\n"; 106 | } 107 | }; 108 | 109 | int main() { 110 | Hashtable t; 111 | t.insert(1); 112 | t.insert(5); 113 | t.insert(12); 114 | t.insert(13); 115 | 116 | t.insert(15); 117 | t.remove(15); 118 | 119 | t.print(); 120 | } 121 | -------------------------------------------------------------------------------- /Examples/c++/Heap/heap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | void swap(int& a, int& b) { 6 | int temp = a; 7 | a = b; 8 | b = temp; 9 | } 10 | 11 | class Heap { 12 | private: 13 | vector data; 14 | 15 | int getLeft(int pos) { 16 | return (pos * 2) + 1; 17 | } 18 | 19 | int getRight(int pos) { 20 | return (pos * 2) + 2; 21 | } 22 | 23 | int getParent(int pos) { 24 | return (pos - 1) / 2; 25 | } 26 | 27 | void siftUp(int pos) { 28 | int parent = getParent(pos); 29 | while (data[pos] > data[parent]) { 30 | swap(data[pos], data[parent]); 31 | if (parent <= 0) { 32 | return; 33 | } 34 | parent = getParent(parent); 35 | pos = getParent(pos); 36 | } 37 | } 38 | 39 | void siftDown(int pos) { 40 | bool hasRight = getRight(pos) < data.size(); 41 | bool hasLeft = getLeft(pos) < data.size(); 42 | 43 | if (hasRight && (data[pos] < data[getLeft(pos)] || data[pos] < data[getRight(pos)])) { 44 | int swapWith = -1; 45 | if (data[getLeft(pos)] < data[getRight(pos)]) { 46 | swapWith = getRight(pos); 47 | } else { 48 | swapWith = getLeft(pos); 49 | } 50 | 51 | swap(data[pos], data[swapWith]); 52 | siftDown(swapWith); 53 | } 54 | else if (hasLeft && data[pos] < data[getLeft(pos)]) { 55 | swap(data[pos], data[getLeft(pos)]); 56 | siftDown(getLeft(pos)); 57 | } 58 | } 59 | 60 | public: 61 | bool isEmpty() const { 62 | return data.size() == 0; 63 | } 64 | void add(int number) { 65 | data.push_back(number); 66 | if (data.size() != 0) { 67 | siftUp(data.size() - 1); 68 | } 69 | } 70 | 71 | int peekTop() { 72 | return data[0]; 73 | } 74 | 75 | void popTop() { 76 | if (isEmpty()) { 77 | return; 78 | } 79 | 80 | swap(data[0], data[data.size() - 1]); 81 | data.pop_back(); 82 | siftDown(0); 83 | } 84 | }; 85 | 86 | int main() { 87 | Heap s; 88 | s.add(1); 89 | s.add(5); 90 | s.add(3); 91 | s.add(4); 92 | s.add(2); 93 | 94 | while(!s.isEmpty()) { 95 | cout << s.peekTop() << " "; 96 | s.popTop(); 97 | } 98 | cout << "\n"; 99 | } 100 | -------------------------------------------------------------------------------- /Examples/c++/KDTree/kd-tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | static const int SIZE = 200001; 5 | 6 | int n, k; 7 | vector> points; 8 | 9 | struct point_comparator { 10 | int dimension; 11 | 12 | point_comparator(int dimension = 0) : dimension(dimension) {} 13 | 14 | bool operator()(const vector& point1, const vector& point2) { 15 | return point1[dimension] < point2[dimension]; 16 | } 17 | }; 18 | 19 | long long distance_squared(vector& point1, vector& point2) { 20 | long long dist = 0; 21 | 22 | for(int i = 0; i < k; i++) { 23 | dist += (point1[i] - point2[i]) * (point1[i] - point2[i]); 24 | } 25 | 26 | return dist; 27 | } 28 | 29 | struct kd_node { 30 | vector point; 31 | 32 | int axis; 33 | 34 | kd_node* left; 35 | kd_node* right; 36 | }; 37 | 38 | kd_node* root; 39 | 40 | int mem_cnt; 41 | kd_node memory_holder[SIZE]; 42 | 43 | 44 | kd_node* build(int from, int to, int axis) { 45 | if (from == to) { 46 | return nullptr; 47 | } 48 | 49 | int mid = (from + to) / 2; 50 | 51 | nth_element(points.begin() + from, 52 | points.begin() + mid, 53 | points.begin() + to, 54 | point_comparator(axis)); 55 | 56 | kd_node* node = &memory_holder[mem_cnt++]; 57 | 58 | node->axis = axis; 59 | node->point = points[mid]; 60 | 61 | node->left = build(from, mid, (axis + 1) % k); 62 | node->right = build(mid + 1, to, (axis + 1) % k); 63 | 64 | return node; 65 | } 66 | 67 | // returns the distance to the nearest neightbour squared 68 | long long nearest_neighbour(kd_node* node, vector& point) { 69 | if (node == nullptr) { 70 | return LLONG_MAX; 71 | } 72 | 73 | long long result = distance_squared(node->point, point); 74 | 75 | if (node->point[node->axis] <= point[node->axis]) { 76 | result = min(result, nearest_neighbour(node->right, point)); 77 | 78 | if (node->left && point[node->axis] - sqrt(result) <= node->point[node->axis]) { 79 | result = min(result, nearest_neighbour(node->left, point)); 80 | } 81 | } else { 82 | result = min(result, nearest_neighbour(node->left, point)); 83 | 84 | if (node->right && point[node->axis] - sqrt(result) >= node->point[node->axis]) { 85 | result = min(result, nearest_neighbour(node->right, point)); 86 | } 87 | } 88 | 89 | return result; 90 | } 91 | 92 | void test() { 93 | // Arrange 94 | n = 6, k = 3; 95 | points.push_back({1, 2, 3}); 96 | points.push_back({-1, 3, 7}); 97 | points.push_back({5, -2, 3}); 98 | points.push_back({1, 1, 1}); 99 | points.push_back({-1, -2, 3}); 100 | points.push_back({1, 3, -2}); 101 | 102 | root = build(0, n, 0); 103 | 104 | // Act, Assert 105 | vector testPoint({2, 2, 2}); 106 | assert(nearest_neighbour(root, testPoint) == 2); 107 | 108 | // Free resources 109 | points.clear(); 110 | n = k = 0; 111 | mem_cnt = 0; 112 | root = nullptr; 113 | } 114 | 115 | int main() { 116 | ios_base::sync_with_stdio(false); 117 | cin.tie(nullptr); 118 | cout.tie(nullptr); 119 | 120 | test(); 121 | 122 | return 0; 123 | } -------------------------------------------------------------------------------- /Examples/c++/Linked List/singly-linked-list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct Node { 6 | int data; 7 | Node* next = nullptr; 8 | 9 | Node(int data, Node* next = nullptr) { 10 | this->data = data; 11 | this->next = next; 12 | } 13 | }; 14 | 15 | class SinglyLL { 16 | private: 17 | Node* head = nullptr; 18 | Node* tail = nullptr; 19 | public: 20 | SinglyLL() = default; 21 | 22 | void freeMemory() { 23 | Node* i = head; 24 | while(i != nullptr) { 25 | Node* next = i->next; 26 | delete i; 27 | i = next; 28 | } 29 | 30 | head = nullptr; 31 | tail = nullptr; 32 | } 33 | 34 | ~SinglyLL() { 35 | freeMemory(); 36 | } 37 | 38 | void copyLinkedList(const SinglyLL& rhs) { 39 | Node* i = rhs.head; 40 | while(i != nullptr) { 41 | push_back(i->data); 42 | i = i->next; 43 | } 44 | } 45 | 46 | SinglyLL& operator=(const SinglyLL& rhs) { 47 | if (this != &rhs) { 48 | freeMemory(); 49 | copyLinkedList(rhs); 50 | } 51 | return *this; 52 | } 53 | 54 | SinglyLL(const SinglyLL& rhs) { 55 | copyLinkedList(rhs); 56 | } 57 | 58 | void push_front(int number) { 59 | Node* newHead = new Node(number, head); 60 | head = newHead; 61 | if (tail == nullptr) { 62 | tail = head; 63 | } 64 | } 65 | 66 | void push_back(int number) { 67 | if (head == nullptr) { 68 | head = new Node(number); 69 | tail = head; 70 | } else { 71 | tail->next = new Node(number); 72 | tail = tail->next; 73 | } 74 | } 75 | 76 | void print() const { 77 | Node* i = head; 78 | while (i != nullptr) { 79 | cout << i->data << " "; 80 | i = i->next; 81 | } 82 | cout << "\n"; 83 | } 84 | 85 | int peek_front() { 86 | if (head != nullptr) { 87 | return head->data; 88 | } else { 89 | throw std::out_of_range("List is empty, cannot peek_front()"); 90 | } 91 | } 92 | 93 | int peek_back() { 94 | if (tail != nullptr) { 95 | return tail->data; 96 | } else { 97 | throw std::out_of_range("List is empty, cannot peek_back()"); 98 | } 99 | } 100 | 101 | void pop_front() { 102 | if (head != nullptr) { 103 | Node* oldHead = head; 104 | if (tail == head) { 105 | tail = nullptr; 106 | } 107 | head = head->next; 108 | delete oldHead; 109 | } else { 110 | throw std::out_of_range("List is empty, cannot pop_front()"); 111 | } 112 | } 113 | 114 | void pop_back() { 115 | if (head != nullptr) { 116 | if (head == tail) { 117 | delete head; 118 | head = nullptr; 119 | tail = nullptr; 120 | } 121 | 122 | // Find the node pointing to the tail 123 | Node* i = head; 124 | while (i-> next != nullptr && i->next != tail) { 125 | i = i->next; 126 | } 127 | 128 | // Delete the tail and point tail to the current node (i) 129 | delete i->next; 130 | i->next = nullptr; 131 | tail = i; 132 | } else { 133 | throw std::out_of_range("List is empty, cannot pop_front()"); 134 | } 135 | } 136 | 137 | void insert(int number, int position) { 138 | if (position == 0) { 139 | push_front(number); 140 | return; 141 | } 142 | 143 | if (head == nullptr) { 144 | throw std::out_of_range("Invalid insert index, list is empty"); 145 | } 146 | 147 | Node* current = head; 148 | Node* previous = nullptr; 149 | for (int i = 0; i < position; i++) { 150 | if (current != nullptr) { 151 | previous = current; 152 | current = current->next; 153 | } else { 154 | throw std::out_of_range("Cannot insert in invalid position"); 155 | } 156 | } 157 | 158 | previous->next = new Node(number, current); 159 | if (tail == previous) { 160 | tail = previous->next; 161 | } 162 | } 163 | 164 | int get(int position) { 165 | if (head == nullptr) { 166 | throw std::out_of_range("List is empty, cannot get from it"); 167 | } 168 | 169 | Node* current = head; 170 | for (int i = 0; i < position; i++) { 171 | if (current->next != nullptr) { 172 | current = current->next; 173 | } else { 174 | throw std::out_of_range("Cannot get from list, no such position"); 175 | } 176 | } 177 | 178 | return current->data; 179 | } 180 | 181 | void remove(int position) { 182 | if (position == 0) { 183 | pop_front(); 184 | return; 185 | } 186 | 187 | if (head == nullptr) { 188 | throw std::out_of_range("Invalid remove index, list is empty"); 189 | } 190 | 191 | Node* current = head; 192 | Node* previous = nullptr; 193 | for (int i = 0; i < position; i++) { 194 | if (current->next != nullptr) { 195 | previous = current; 196 | current = current->next; 197 | } else { 198 | throw std::out_of_range("Cannot insert in invalid position"); 199 | } 200 | } 201 | 202 | previous->next = current->next; 203 | if (tail == current) { 204 | tail = previous; 205 | } 206 | delete current; 207 | } 208 | 209 | }; 210 | 211 | int main() { 212 | SinglyLL l; 213 | l.insert(0, 0); 214 | l.insert(1, 1); 215 | l.insert(2, 2); 216 | l.insert(3, 3); 217 | l.print(); 218 | } -------------------------------------------------------------------------------- /Examples/c++/Queue/queue-using-links.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct Node { 6 | int data; 7 | Node* previous = nullptr; 8 | 9 | Node(int data, Node* previous = nullptr) { 10 | this->data = data; 11 | this->previous = previous; 12 | } 13 | }; 14 | 15 | class Queue { 16 | private: 17 | Node* front = nullptr; 18 | Node* back = nullptr; 19 | public: 20 | Queue() = default; 21 | 22 | void copyQueue(const Queue& rhs) { 23 | Node* i = rhs.front; 24 | while (i != nullptr) { 25 | push(i->data); 26 | i = i->previous; 27 | } 28 | } 29 | 30 | void freeMemory() { 31 | while(front != nullptr) { 32 | Node* previous = front->previous; 33 | delete front; 34 | front = previous; 35 | } 36 | } 37 | 38 | Queue(const Queue& rhs) { 39 | copyQueue(rhs); 40 | } 41 | 42 | Queue& operator=(const Queue& rhs) { 43 | if (this != &rhs) { 44 | freeMemory(); 45 | copyQueue(rhs); 46 | } 47 | return *this; 48 | } 49 | 50 | ~Queue() { 51 | // freeMemory(); 52 | } 53 | 54 | void push(int number) { 55 | if (isEmpty()) { 56 | front = new Node(number); 57 | back = front; 58 | } else { 59 | back->previous = new Node(number); 60 | back = back->previous; 61 | } 62 | } 63 | 64 | void pop() { 65 | if (!isEmpty()) { 66 | Node* oldFront = front; 67 | front = front->previous; 68 | delete oldFront; 69 | } else { 70 | throw std::underflow_error("Queue is empty"); 71 | } 72 | } 73 | 74 | int peek() const { 75 | if (!isEmpty()) { 76 | return front->data; 77 | } else { 78 | throw std::underflow_error("Queue is empty"); 79 | } 80 | } 81 | 82 | bool isEmpty() const { 83 | return front == nullptr; 84 | } 85 | }; 86 | 87 | int main() { 88 | Queue s; 89 | s.push(1); 90 | s.push(2); 91 | s.push(3); 92 | 93 | Queue d(s); 94 | while (!d.isEmpty()) { 95 | cout << d.peek(); 96 | d.pop(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Examples/c++/Queue/queue-using-list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class Queue { 7 | private: 8 | list data; 9 | public: 10 | void push(int number) { 11 | data.push_back(number); 12 | } 13 | 14 | void pop() { 15 | data.pop_front(); 16 | } 17 | 18 | int peek() const { 19 | if (data.size() > 0) { 20 | return data.front(); 21 | } else { 22 | throw std::underflow_error("Queue is empty."); 23 | } 24 | } 25 | 26 | bool isEmpty() const { 27 | return data.size() == 0; 28 | } 29 | }; 30 | 31 | int main() { 32 | Queue q; 33 | q.push(1); 34 | q.push(2); 35 | q.push(3); 36 | 37 | while (!q.isEmpty()) { 38 | cout << q.peek(); 39 | q.pop(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Examples/c++/Searching/binary-search-answer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int binarySearch(int *array, int length, int target) { 5 | 6 | } 7 | 8 | int main() { 9 | int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 10 | int * arrStart = &arr[0]; 11 | 12 | cout << "Index of 2 is " << binarySearch(arr, 10, 2) << "\n"; 13 | cout << "Index of -2 is " << binarySearch(arr, 10, -2) << "\n"; 14 | } -------------------------------------------------------------------------------- /Examples/c++/Searching/binary-search-recursive.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int _binarySearch(int* array, int left, int right, int target) { 5 | if (right - left < 0) { 6 | return -1; 7 | } 8 | 9 | int mid = (right + left) / 2; 10 | if (array[mid] == target) { 11 | return mid; 12 | } else if (array[mid] > target) { 13 | return _binarySearch(array, left, mid - 1, target); 14 | } else if (array[mid] < target) { 15 | return _binarySearch(array, mid + 1, right, target); 16 | } 17 | return -1; 18 | } 19 | 20 | int binarySearch(int *array, int length, int target) { 21 | return _binarySearch(array, 0, length - 1, target); 22 | } 23 | 24 | int main() { 25 | int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 26 | int * arrStart = &arr[0]; 27 | 28 | cout << "Index of 2 is " << binarySearch(arr, 10, 2) << "\n"; 29 | cout << "Index of -2 is " << binarySearch(arr, 10, -2) << "\n"; 30 | } -------------------------------------------------------------------------------- /Examples/c++/Searching/binary-search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int binarySearch(int *array, int length, int target) { 5 | int left = 0; 6 | int right = length - 1; 7 | 8 | while(left <= right) { 9 | int mid = (left + right) / 2; 10 | 11 | if (array[mid] == target) { 12 | return mid; 13 | } 14 | if (array[mid] > target) { 15 | right = mid - 1; 16 | } 17 | if (array[mid] < target) { 18 | left = mid + 1; 19 | } 20 | } 21 | 22 | return -1; 23 | } 24 | 25 | int main() { 26 | int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 27 | int * arrStart = &arr[0]; 28 | 29 | cout << "Index of 2 is " << binarySearch(arr, 10, 2) << "\n"; 30 | cout << "Index of -2 is " << binarySearch(arr, 10, -2) << "\n"; 31 | } -------------------------------------------------------------------------------- /Examples/c++/Searching/exponential-search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int binarySearch(int *array, int length, int target) { 5 | int left = 0; 6 | int right = length - 1; 7 | 8 | while(left <= right) { 9 | int mid = (left + right) / 2; 10 | 11 | if (array[mid] == target) { 12 | return mid; 13 | } 14 | if (array[mid] > target) { 15 | right = mid - 1; 16 | } 17 | if (array[mid] < target) { 18 | left = mid + 1; 19 | } 20 | } 21 | 22 | return -1; 23 | } 24 | 25 | int exponentialSearch(int *array, int length, int target) { 26 | if (length == 0) { 27 | return false; 28 | } 29 | 30 | int right = 1; 31 | while (right < length && array[right] < target) { 32 | right *= 2; 33 | } 34 | 35 | int binaryIndex = binarySearch(array + right/2, min(right + 1, length) - right/2, target); 36 | if (binaryIndex != -1) { 37 | return binaryIndex + right/2; 38 | } else { 39 | return -1; 40 | } 41 | } 42 | 43 | int main() { 44 | int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 45 | int * arrStart = &arr[0]; 46 | 47 | 48 | cout << "Index of 2 is " << exponentialSearch(arr, 10, 2) << "\n"; 49 | cout << "Index of -2 is " << exponentialSearch(arr, 10, -2) << "\n"; 50 | } -------------------------------------------------------------------------------- /Examples/c++/Searching/interpolation-search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int interpolationSearch(int *array, int length, int target) { 5 | int left = 0; 6 | int right = length - 1; 7 | 8 | while (array[right] != array[left] && target >= array[left] && target <= array[right]) { 9 | int mid = left + ((target - array[left]) * (right - left) / (array[right] - array[left])); 10 | 11 | if (array[mid] < target) 12 | left = mid + 1; 13 | else if (target < array[mid]) 14 | right = mid - 1; 15 | else 16 | return mid; 17 | } 18 | 19 | if (target == array[left]) 20 | return left; 21 | else 22 | return -1; 23 | } 24 | 25 | int main() { 26 | int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 27 | int * arrStart = &arr[0]; 28 | 29 | cout << "Index of 2 is " << interpolationSearch(arr, 10, 2) << "\n"; 30 | cout << "Index of -2 is " << interpolationSearch(arr, 10, -2) << "\n"; 31 | } -------------------------------------------------------------------------------- /Examples/c++/Searching/jump-search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int jumpSearch(int *array, int length, int target) { 6 | int left = 0; 7 | int step = sqrt(length); 8 | int right = step; 9 | 10 | while(right < length && array[right] <= target) { 11 | left += step; 12 | right += step; 13 | if(right > length - 1) 14 | right = length; 15 | } 16 | 17 | for(int i = left; i < right; i++) { 18 | if(array[i] == target) 19 | return i; 20 | } 21 | 22 | return -1; 23 | } 24 | 25 | int main() { 26 | int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 27 | int * arrStart = &arr[0]; 28 | 29 | cout << "Index of 2 is " << jumpSearch(arr, 10, 2) << "\n"; 30 | cout << "Index of -2 is " << jumpSearch(arr, 10, -2) << "\n"; 31 | } -------------------------------------------------------------------------------- /Examples/c++/Searching/linear-search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int linearSearch(int *array, int length, int target) { 5 | for (int i = 0; i < length; i++) { 6 | if (array[i] == target) { 7 | return i; 8 | } 9 | } 10 | return -1; 11 | } 12 | 13 | int main() { 14 | int arr[] = {4, 7, 2, 3, 0, 9, 6, 1, 8, 5}; 15 | int * arrStart = &arr[0]; 16 | 17 | cout << "Index of 2 is " << linearSearch(arr, 10, 2) << "\n"; 18 | cout << "Index of -2 is " << linearSearch(arr, 10, -2) << "\n"; 19 | } -------------------------------------------------------------------------------- /Examples/c++/Searching/ternary-search-max.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int ternarySearchMax(int *array, int length, int target) { 5 | 6 | } 7 | 8 | int main() { 9 | int arr[] = {0, 1, 2, 3, 4, 5, 4, 3, 2, 1}; 10 | int * arrStart = &arr[0]; 11 | 12 | int maxIndex = ternarySearchMax(arr, 10); 13 | cout << "Max index is " << maxIndex << " with value " << array[maxIndex] << "\n"; 14 | } -------------------------------------------------------------------------------- /Examples/c++/Searching/ternary-search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int ternarySearch(int *array, int length, int target) { 5 | int left = 0; 6 | int right = length - 1; 7 | 8 | while (left <= right) { 9 | int leftThird = left + (right - left) / 3; 10 | int rightThird = right - (right - left) / 3; 11 | 12 | if (array[leftThird] == target) { 13 | return leftThird; 14 | } 15 | if (array[rightThird] == target) { 16 | return rightThird; 17 | } 18 | 19 | if (target < array[leftThird]) { 20 | right = leftThird - 1; 21 | } else if (target > array[rightThird]) { 22 | left = rightThird + 1; 23 | } else { 24 | left = leftThird + 1; 25 | right = rightThird - 1; 26 | } 27 | } 28 | 29 | return -1; 30 | } 31 | 32 | int main() { 33 | int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 34 | int * arrStart = &arr[0]; 35 | 36 | cout << "Index of 2 is " << ternarySearch(arr, 10, 2) << "\n"; 37 | cout << "Index of -2 is " << ternarySearch(arr, 10, -2) << "\n"; 38 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/bubble-sort-adaptive.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void bubbleSort(int * array, int length) { 10 | for (int i = 0; i < length; i++) { 11 | bool swappedAtLeastOnce = false; 12 | 13 | for (int k = 0; k < length - 1 - i; k++) { 14 | if (array[k] > array[k + 1]) { 15 | swap(array[k], array[k + 1]); 16 | swappedAtLeastOnce = true; 17 | } 18 | } 19 | 20 | if (!swappedAtLeastOnce) { 21 | break; 22 | } 23 | } 24 | } 25 | 26 | int main() { 27 | int arr[] = {2, 5, 3, 6, 1, 4}; 28 | int * arrStart = &arr[0]; 29 | 30 | bubbleSort(arrStart, 6); 31 | 32 | for (int i = 0; i < 6; i++) { 33 | std::cout << arr[i] << ", "; 34 | } 35 | 36 | std::cout << "\n"; 37 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/bubble-sort-cleancode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void bubbleSort(int * array, int length) { 10 | for (int bubbleStartIndex = 0; bubbleStartIndex < length; bubbleStartIndex++) { 11 | for (int bubbleMovedIndex = 0; bubbleMovedIndex < length - 1; bubbleMovedIndex++) { 12 | if (array[bubbleMovedIndex] > array[bubbleMovedIndex + 1]) { 13 | swap(array[bubbleMovedIndex], array[bubbleMovedIndex + 1]); 14 | } 15 | } 16 | } 17 | } 18 | 19 | int main() { 20 | int arr[] = {2, 5, 3, 6, 1, 4}; 21 | int * arrStart = &arr[0]; 22 | 23 | bubbleSort(arrStart, 6); 24 | 25 | for (int i = 0; i < 6; i++) { 26 | std::cout << arr[i] << ", "; 27 | } 28 | 29 | std::cout << "\n"; 30 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/bubble-sort-short.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void bubbleSort(int * array, int length) { 10 | for (int i = 0; i < length; i++) { 11 | for (int k = 0; k < length - 1; k++) { 12 | if (array[k] > array[k + 1]) { 13 | swap(array[k], array[k + 1]); 14 | } 15 | } 16 | } 17 | } 18 | 19 | int main() { 20 | int arr[] = {2, 5, 3, 6, 1, 4}; 21 | int * arrStart = &arr[0]; 22 | 23 | bubbleSort(arrStart, 6); 24 | 25 | for (int i = 0; i < 6; i++) { 26 | std::cout << arr[i] << ", "; 27 | } 28 | 29 | std::cout << "\n"; 30 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/bubble-sort-simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void bubbleSort(int * array, int length) { 10 | for (int i = 0; i < length; i++) { 11 | for (int k = 0; k < length - 1 - i; k++) { 12 | if (array[k] > array[k + 1]) { 13 | swap(array[k], array[k + 1]); 14 | } 15 | } 16 | } 17 | } 18 | 19 | int main() { 20 | int arr[] = {2, 5, 3, 6, 1, 4}; 21 | int * arrStart = &arr[0]; 22 | 23 | bubbleSort(arrStart, 6); 24 | 25 | for (int i = 0; i < 6; i++) { 26 | std::cout << arr[i] << ", "; 27 | } 28 | 29 | std::cout << "\n"; 30 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/bucket-sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void bucketSort(double *array, int length) { 6 | std::vector buckets[length]; 7 | 8 | for(int i = 0; i < length; i++) { 9 | buckets[int(length * array[i])].push_back(array[i]); 10 | } 11 | 12 | for(int i = 0; i < length; i++) { 13 | sort(buckets[i].begin(), buckets[i].end()); 14 | } 15 | 16 | int index = 0; 17 | for(int i = 0; i < length; i++) { 18 | while(!buckets[i].empty()) { 19 | array[index] = buckets[i][0]; 20 | index++; 21 | buckets[i].erase(buckets[i].begin()); 22 | } 23 | } 24 | } 25 | 26 | int main() { 27 | double arr[] = {0.25, 0.36, 0.58, 0.41, 0.29, 0.22, 0.45, 0.79, 0.01, 0.69}; 28 | double * arrStart = &arr[0]; 29 | 30 | bucketSort(arrStart, 10); 31 | 32 | for (int i = 0; i < 10; i++) { 33 | std::cout << arr[i] << ", "; 34 | } 35 | 36 | std::cout << "\n"; 37 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/counting-sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void countingSort(int * array, int length) { 4 | int maxNumber = 0; 5 | for (int i = 0; i < length; i++) { 6 | if (array[i] > maxNumber) { 7 | maxNumber = array[i]; 8 | } 9 | } 10 | 11 | int * countingArray = new int[maxNumber + 1]; 12 | for (int i = 0; i < maxNumber + 1; i++) { 13 | countingArray[i] = 0; 14 | } 15 | 16 | for (int i = 0; i < length; i++) { 17 | countingArray[array[i]]++; 18 | } 19 | 20 | int sortedIndex = 0; 21 | for (int i = 0; i < length; i++) { 22 | while (countingArray[sortedIndex] == 0) { 23 | sortedIndex++; 24 | } 25 | 26 | array[i] = sortedIndex; 27 | countingArray[sortedIndex]--; 28 | } 29 | 30 | delete[] countingArray; 31 | } 32 | 33 | int main() { 34 | int arr[] = {2, 5, 5, 6, 1, 4}; 35 | int * arrStart = &arr[0]; 36 | 37 | countingSort(arrStart, 6); 38 | 39 | for (int i = 0; i < 6; i++) { 40 | std::cout << arr[i] << ", "; 41 | } 42 | 43 | std::cout << "\n"; 44 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/insertion-sort-cleancode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void insertionSort(int * array, int length) { 10 | for (int nextItemToSortIndex = 1; nextItemToSortIndex < length; nextItemToSortIndex++) { 11 | for (int potentiallyBiggerItemIndex = nextItemToSortIndex; 12 | potentiallyBiggerItemIndex > 0 && 13 | array[potentiallyBiggerItemIndex] < array[potentiallyBiggerItemIndex - 1]; 14 | potentiallyBiggerItemIndex--) { 15 | swap(array[potentiallyBiggerItemIndex], array[potentiallyBiggerItemIndex-1]); 16 | } 17 | } 18 | } 19 | 20 | int main() { 21 | int arr[] = {2, 5, 3, 6, 1, 4}; 22 | int * arrStart = &arr[0]; 23 | 24 | insertionSort(arrStart, 6); 25 | 26 | for (int i = 0; i < 6; i++) { 27 | std::cout << arr[i] << ", "; 28 | } 29 | 30 | std::cout << "\n"; 31 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/insertion-sort-short.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void insertionSort(int * array, int length) { 10 | for (int i = 1; i < length; i++) { 11 | for (int k = i; k > 0 && array[k] < array[k - 1]; k--) { 12 | swap(array[k], array[k-1]); 13 | } 14 | } 15 | } 16 | 17 | int main() { 18 | int arr[] = {2, 5, 3, 6, 1, 4}; 19 | int * arrStart = &arr[0]; 20 | 21 | insertionSort(arrStart, 6); 22 | 23 | for (int i = 0; i < 6; i++) { 24 | std::cout << arr[i] << ", "; 25 | } 26 | 27 | std::cout << "\n"; 28 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/insertion-sort-simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void insertionSort(int * array, int length) { 10 | for (int i = 1; i < length; i++) { 11 | for (int k = i; k > 0 && array[k] < array[k - 1]; k--) { 12 | swap(array[k], array[k - 1]); 13 | } 14 | } 15 | } 16 | 17 | int main() { 18 | int arr[] = {2, 5, 3, 6, 1, 4}; 19 | int * arrStart = &arr[0]; 20 | 21 | insertionSort(arrStart, 6); 22 | 23 | for (int i = 0; i < 6; i++) { 24 | std::cout << arr[i] << ", "; 25 | } 26 | 27 | std::cout << "\n"; 28 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/merge-sort-cleancode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void merge(int * originalArray, int * mergeArray, int start, int mid, int end) { 4 | int leftIndex = start; 5 | int rightIndex = mid + 1; 6 | int sortedIndex = start; 7 | 8 | while (leftIndex <= mid && rightIndex <= end) { 9 | if (originalArray[leftIndex] <= originalArray[rightIndex]) { 10 | mergeArray[sortedIndex] = originalArray[leftIndex]; 11 | leftIndex++; 12 | } else { 13 | mergeArray[sortedIndex] = originalArray[rightIndex]; 14 | rightIndex++; 15 | } 16 | 17 | sortedIndex++; 18 | } 19 | 20 | while (leftIndex <= mid) { 21 | mergeArray[sortedIndex] = originalArray[leftIndex]; 22 | leftIndex++; 23 | sortedIndex++; 24 | } 25 | 26 | while (rightIndex <= end) { 27 | mergeArray[sortedIndex] = originalArray[rightIndex]; 28 | rightIndex++; 29 | sortedIndex++; 30 | } 31 | 32 | for (int i = start; i <= end; i++) { 33 | originalArray[i] = mergeArray[i]; 34 | } 35 | } 36 | 37 | void mergeSortRecursive(int * original, int * mergeArray, int start, int end) { 38 | if (start < end) { 39 | int mid = (start + end) / 2; 40 | 41 | mergeSortRecursive(original, mergeArray, start, mid); 42 | mergeSortRecursive(original, mergeArray, mid + 1, end); 43 | 44 | merge(original, mergeArray, start, mid, end); 45 | } 46 | } 47 | 48 | void mergeSort(int * array, int length) { 49 | int * mergeArray = new int[length]; 50 | mergeSortRecursive(array, mergeArray, 0, length - 1); 51 | delete[] mergeArray; 52 | } 53 | 54 | int main() { 55 | int arr[] = {2, 5, 3, 6, 1, 4}; 56 | int * arrStart = &arr[0]; 57 | mergeSort(arrStart, 6); 58 | 59 | for (int i = 0; i < 6; i++) { 60 | std::cout << arr[i] << ", "; 61 | } 62 | 63 | std::cout << "\n"; 64 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/merge-sort-short.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void merge(int * originalArray, int * mergeArray, int start, int mid, int end) { 4 | int left = start; 5 | int right = mid + 1; 6 | 7 | for (int i = start; i <= end; i++) { 8 | if (left <= mid && (right > end || originalArray[left] <= originalArray[right])) { 9 | mergeArray[i] = originalArray[left]; 10 | left++; 11 | } else { 12 | mergeArray[i] = originalArray[right]; 13 | right++; 14 | } 15 | } 16 | 17 | for (int i = start; i <= end; i++) { 18 | originalArray[i] = mergeArray[i]; 19 | } 20 | } 21 | 22 | void _mergeSort(int * originalArray, int * mergeArray, int start, int end) { 23 | if (start < end) { 24 | int mid = (start + end) / 2; 25 | _mergeSort(originalArray, mergeArray, start, mid); 26 | _mergeSort(originalArray, mergeArray, mid + 1, end); 27 | merge(originalArray, mergeArray, start, mid, end); 28 | } 29 | } 30 | 31 | void mergeSort(int * array, int length) { 32 | int * mergeArray = new int[length]; 33 | _mergeSort(array, mergeArray, 0, length - 1); 34 | delete[] mergeArray; 35 | } 36 | 37 | int main() { 38 | int arr[] = {2, 5, 3, 6, 1, 4}; 39 | int * arrStart = &arr[0]; 40 | mergeSort(arrStart, 6); 41 | 42 | for (int i = 0; i < 6; i++) { 43 | std::cout << arr[i] << ", "; 44 | } 45 | 46 | std::cout << "\n"; 47 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/quick-sort-hoare-short.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void swap(int & a, int & b) { 5 | int tmp = a; 6 | a = b; 7 | b = tmp; 8 | } 9 | 10 | int partition(int * array, int start, int end) { 11 | int pivot = array[(start + end) / 2]; 12 | int left = start - 1; 13 | int right = end + 1; 14 | 15 | while (true) { 16 | do { 17 | left++; 18 | } while (array[left] < pivot); 19 | 20 | do { 21 | right--; 22 | } while (array[right] > pivot); 23 | 24 | if (left >= right) { 25 | return right; 26 | } 27 | 28 | swap(array[left], array[right]); 29 | } 30 | } 31 | 32 | void _quickSort(int * array, int start, int end) { 33 | if (start < end) { 34 | int pivot = partition(array, start, end); 35 | _quickSort(array, start, pivot - 1); 36 | _quickSort(array, pivot + 1, end); 37 | } 38 | } 39 | 40 | void quickSort(int * array, int length) { 41 | _quickSort(array, 0, length - 1); 42 | } 43 | 44 | int main() { 45 | int arr[] = {2, 5, 3, 6, 1, 4}; 46 | int * arrStart = &arr[0]; 47 | 48 | quickSort(arrStart, 6); 49 | 50 | for (int i = 0; i < 6; i++) { 51 | std::cout << arr[i] << ", "; 52 | } 53 | 54 | std::cout << "\n"; 55 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/quick-sort-hoare-using-while-loops.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void swap(int & a, int & b) { 5 | int tmp = a; 6 | a = b; 7 | b = tmp; 8 | } 9 | 10 | int partition(int * array, int start, int end) { 11 | int pivot = array[(start + end) / 2]; 12 | int left = start; 13 | int right = end; 14 | 15 | while (left <= right) { 16 | while (array[left] < pivot) { 17 | left++; 18 | } 19 | while (array[right] > pivot) { 20 | right--; 21 | } 22 | 23 | swap(array[left], array[right]); 24 | left++; 25 | right--; 26 | } 27 | 28 | return left; 29 | } 30 | 31 | void _quickSort(int * array, int start, int end) { 32 | if (start < end) { 33 | int pivot = partition(array, start, end); 34 | _quickSort(array, start, pivot - 1); 35 | _quickSort(array, pivot, end); 36 | } 37 | } 38 | 39 | void quickSort(int * array, int length) { 40 | _quickSort(array, 0, length - 1); 41 | } 42 | 43 | int main() { 44 | int arr[] = {2, 5, 3, 6, 1, 4}; 45 | int * arrStart = &arr[0]; 46 | 47 | quickSort(arrStart, 6); 48 | 49 | for (int i = 0; i < 6; i++) { 50 | std::cout << arr[i] << ", "; 51 | } 52 | 53 | std::cout << "\n"; 54 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/quick-sort-lomuto-cleancode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | int partition(int * array, int startIndex, int endIndex) { 10 | int pivot = array[endIndex]; 11 | int pivotIndex = startIndex; 12 | 13 | for (int i = startIndex; i <= endIndex; i++) { 14 | if (array[i] < pivot) { 15 | swap(array[i], array[pivotIndex]); 16 | pivotIndex++; 17 | } 18 | } 19 | 20 | swap(array[endIndex], array[pivotIndex]); 21 | return pivotIndex; 22 | } 23 | 24 | void _quickSort(int * array, int startIndex, int endIndex) { 25 | if (startIndex < endIndex) { 26 | int pivot = partition(array, startIndex, endIndex); 27 | _quickSort(array, startIndex, pivot - 1); 28 | _quickSort(array, pivot + 1, endIndex); 29 | } 30 | } 31 | 32 | void quickSort(int * array, int length) { 33 | _quickSort(array, 0, length - 1); 34 | } 35 | 36 | int main() { 37 | int arr[] = {2, 5, 3, 6, 1, 4}; 38 | int * arrStart = &arr[0]; 39 | 40 | quickSort(arrStart, 6); 41 | 42 | for (int i = 0; i < 6; i++) { 43 | std::cout << arr[i] << ", "; 44 | } 45 | 46 | std::cout << "\n"; 47 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/quick-sort-lomuto-random-pivot.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void swap(int & a, int & b) { 5 | int tmp = a; 6 | a = b; 7 | b = tmp; 8 | } 9 | 10 | int generateRandomNumber(int from, int to) { 11 | std::random_device dev; 12 | std::mt19937 rng(dev()); 13 | std::uniform_int_distribution dist6(from,to); 14 | 15 | return dist6(rng); 16 | } 17 | 18 | int partition(int * array, int start, int end) { 19 | int randomIndex = generateRandomNumber(start, end); 20 | swap(array[end], array[randomIndex]); 21 | 22 | int pivot = array[end]; 23 | int pivotIndex = start; 24 | for (int i = start; i <= end; i++) { 25 | if (array[i] < pivot) { 26 | swap(array[i], array[pivotIndex]); 27 | pivotIndex++; 28 | } 29 | } 30 | swap(array[end], array[pivotIndex]); 31 | return pivotIndex; 32 | } 33 | 34 | void _quickSort(int * array, int start, int end) { 35 | if (start < end) { 36 | int pivot = partition(array, start, end); 37 | _quickSort(array, start, pivot - 1); 38 | _quickSort(array, pivot + 1, end); 39 | } 40 | } 41 | 42 | void quickSort(int * array, int length) { 43 | _quickSort(array, 0, length - 1); 44 | } 45 | 46 | int main() { 47 | int arr[] = {2, 5, 3, 6, 1, 4}; 48 | int * arrStart = &arr[0]; 49 | 50 | quickSort(arrStart, 6); 51 | 52 | for (int i = 0; i < 6; i++) { 53 | std::cout << arr[i] << ", "; 54 | } 55 | 56 | std::cout << "\n"; 57 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/quick-sort-lomuto-short.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | int partition(int * array, int start, int end) { 10 | int pivot = array[end]; 11 | int pivotIndex = start; 12 | for (int i = start; i <= end; i++) { 13 | if (array[i] < pivot) { 14 | swap(array[i], array[pivotIndex]); 15 | pivotIndex++; 16 | } 17 | } 18 | swap(array[end], array[pivotIndex]); 19 | return pivotIndex; 20 | } 21 | 22 | void _quickSort(int * array, int start, int end) { 23 | if (start < end) { 24 | int pivot = partition(array, start, end); 25 | _quickSort(array, start, pivot - 1); 26 | _quickSort(array, pivot + 1, end); 27 | } 28 | } 29 | 30 | void quickSort(int * array, int length) { 31 | _quickSort(array, 0, length - 1); 32 | } 33 | 34 | int main() { 35 | int arr[] = {2, 5, 3, 6, 1, 4}; 36 | int * arrStart = &arr[0]; 37 | 38 | quickSort(arrStart, 6); 39 | 40 | for (int i = 0; i < 6; i++) { 41 | std::cout << arr[i] << ", "; 42 | } 43 | 44 | std::cout << "\n"; 45 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/quick-sort-lomuto-shuffle.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void swap(int & a, int & b) { 5 | int tmp = a; 6 | a = b; 7 | b = tmp; 8 | } 9 | 10 | int generateRandomNumber(int from, int to) { 11 | std::random_device dev; 12 | std::mt19937 rng(dev()); 13 | std::uniform_int_distribution dist6(from,to); 14 | 15 | return dist6(rng); 16 | } 17 | 18 | void shuffle(int * arr, int length) { 19 | for (int i = 0; i < length - 1; i++) { 20 | int swapCurrentWith = generateRandomNumber(i, length - 1); 21 | swap(arr[i], arr[swapCurrentWith]); 22 | } 23 | } 24 | 25 | int partition(int * array, int start, int end) { 26 | int pivot = array[end]; 27 | int pivotIndex = start; 28 | for (int i = start; i <= end; i++) { 29 | if (array[i] < pivot) { 30 | swap(array[i], array[pivotIndex]); 31 | pivotIndex++; 32 | } 33 | } 34 | swap(array[end], array[pivotIndex]); 35 | return pivotIndex; 36 | } 37 | 38 | void _quickSort(int * array, int start, int end) { 39 | if (start < end) { 40 | int pivot = partition(array, start, end); 41 | _quickSort(array, start, pivot - 1); 42 | _quickSort(array, pivot + 1, end); 43 | } 44 | } 45 | 46 | void quickSort(int * array, int length) { 47 | shuffle(array, length); 48 | _quickSort(array, 0, length - 1); 49 | } 50 | 51 | int main() { 52 | int arr[] = {2, 5, 3, 6, 1, 4}; 53 | int * arrStart = &arr[0]; 54 | 55 | quickSort(arrStart, 6); 56 | 57 | for (int i = 0; i < 6; i++) { 58 | std::cout << arr[i] << ", "; 59 | } 60 | 61 | std::cout << "\n"; 62 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/radix-sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int abs(int a) { 6 | return a >= 0 ? a : -a; 7 | } 8 | 9 | void radixSort(int * array, int length) { 10 | int maxNumber = 0; 11 | for (int i = 0; i < length; i++) { 12 | if (abs(array[i]) > maxNumber) { 13 | maxNumber = abs(array[i]); 14 | } 15 | } 16 | 17 | int maxDigits = log10(maxNumber) + 1; 18 | 19 | std::list pocket[10]; 20 | 21 | for(int i = 0; i < maxDigits; i++) { 22 | int m = pow(10, i + 1); 23 | int p = pow(10, i); 24 | 25 | for(int j = 0; j < length; j++) { 26 | int temp = array[j] % m; 27 | int index = temp / p; 28 | pocket[index].push_back(array[j]); 29 | } 30 | 31 | int count = 0; 32 | for(int j = 0; j<10; j++) { 33 | while(!pocket[j].empty()) { 34 | array[count] = *(pocket[j].begin()); 35 | pocket[j].erase(pocket[j].begin()); 36 | count++; 37 | } 38 | } 39 | } 40 | } 41 | 42 | int main() { 43 | int arr[] = {22, 53, 31, 67, 16, 4}; 44 | int * arrStart = &arr[0]; 45 | 46 | radixSort(arrStart, 6); 47 | 48 | for (int i = 0; i < 6; i++) { 49 | std::cout << arr[i] << ", "; 50 | } 51 | 52 | std::cout << "\n"; 53 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/selection-sort-cleancode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void selectionSort(int * array, int length) { 10 | for (int currentIndex = 0; currentIndex < length; currentIndex++) { 11 | int smallestNumberIndex = currentIndex; 12 | 13 | for (int potentialSmallerNumberIndex = currentIndex + 1; 14 | potentialSmallerNumberIndex < length; 15 | potentialSmallerNumberIndex++) { 16 | if (array[potentialSmallerNumberIndex] < array[smallestNumberIndex]) { 17 | smallestNumberIndex = potentialSmallerNumberIndex; 18 | } 19 | } 20 | 21 | swap(array[currentIndex], array[smallestNumberIndex]); 22 | } 23 | } 24 | 25 | int main() { 26 | int arr[] = {2, 5, 3, 6, 1, 4}; 27 | int * arrStart = &arr[0]; 28 | 29 | selectionSort(arrStart, 6); 30 | 31 | for (int i = 0; i < 6; i++) { 32 | std::cout << arr[i] << ", "; 33 | } 34 | 35 | std::cout << "\n"; 36 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/selection-sort-short.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void selectionSort(int * array, int length) { 10 | for (int i = 0; i < length; i++) { 11 | int index = i; 12 | 13 | for (int k = i + 1; k < length; k++) { 14 | if (array[k] < array[index]) { 15 | index = k; 16 | } 17 | } 18 | 19 | swap(array[i], array[index]); 20 | } 21 | } 22 | 23 | int main() { 24 | int arr[] = {2, 5, 3, 6, 1, 4}; 25 | int * arrStart = &arr[0]; 26 | 27 | selectionSort(arrStart, 6); 28 | 29 | for (int i = 0; i < 6; i++) { 30 | std::cout << arr[i] << ", "; 31 | } 32 | 33 | std::cout << "\n"; 34 | } -------------------------------------------------------------------------------- /Examples/c++/Sorting/selection-sort-simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void swap(int & a, int & b) { 4 | int tmp = a; 5 | a = b; 6 | b = tmp; 7 | } 8 | 9 | void selectionSort(int * array, int length) { 10 | for (int i = 0; i < length; i++) { 11 | int index = i; 12 | 13 | for (int k = i + 1; k < length; k++) { 14 | if (array[k] < array[index]) { 15 | index = k; 16 | } 17 | } 18 | 19 | swap(array[i], array[index]); 20 | } 21 | } 22 | 23 | int main() { 24 | int arr[] = {2, 5, 3, 6, 1, 4}; 25 | int * arrStart = &arr[0]; 26 | 27 | selectionSort(arrStart, 6); 28 | 29 | for (int i = 0; i < 6; i++) { 30 | std::cout << arr[i] << ", "; 31 | } 32 | 33 | std::cout << "\n"; 34 | } -------------------------------------------------------------------------------- /Examples/c++/Stack/stack-using-array.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class Stack { 6 | private: 7 | int capacity; 8 | int* data; 9 | int top; // index of the last element 10 | public: 11 | Stack(int capacity) { 12 | this->capacity = capacity; 13 | this->data = new int[capacity]; 14 | top = -1; 15 | } 16 | 17 | void copyStack(const Stack& rhs) { 18 | this->capacity = rhs.capacity; 19 | this->data = new int[capacity]; 20 | this->top = rhs.top; 21 | for (int i = 0; i <= rhs.top; i++) { 22 | this->data[i] = rhs.data[i]; 23 | } 24 | } 25 | 26 | void freeMemory() { 27 | delete[] this->data; 28 | this->data = nullptr; 29 | top = -1; 30 | capacity = 0; 31 | } 32 | 33 | Stack(const Stack& rhs) { 34 | copyStack(rhs); 35 | } 36 | 37 | Stack& operator=(const Stack& rhs) { 38 | if (this != &rhs) { 39 | freeMemory(); 40 | copyStack(rhs); 41 | } 42 | return *this; 43 | } 44 | 45 | ~Stack() { 46 | freeMemory(); 47 | } 48 | 49 | void push(int number) { 50 | if (top < capacity - 1) { 51 | top++; 52 | data[top] = number; 53 | } else { 54 | throw std::overflow_error("Stack is full"); 55 | } 56 | } 57 | 58 | void pop() { 59 | if (top > -1) { 60 | top--; 61 | } else { 62 | throw std::underflow_error("Stack is empty"); 63 | } 64 | } 65 | 66 | int peek() const { 67 | if (top > -1) { 68 | return data[top]; 69 | } else { 70 | throw std::underflow_error("Stack is empty"); 71 | } 72 | } 73 | 74 | bool isEmpty() const { 75 | return top == -1; 76 | } 77 | }; 78 | 79 | int main() { 80 | Stack s(3); 81 | s.push(1); 82 | s.push(2); 83 | s.push(3); 84 | // s.push(4); // overflow 85 | cout << s.peek(); // 3 86 | s.pop(); 87 | cout << s.peek(); // 2 88 | s.pop(); 89 | cout << s.peek(); // 1 90 | s.pop(); 91 | // s.pop(); // underflow 92 | cout << s.isEmpty(); // 1 = true, is indeed empty 93 | } 94 | -------------------------------------------------------------------------------- /Examples/c++/Stack/stack-using-links.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct Node { 6 | int data; 7 | Node* previous = nullptr; 8 | 9 | Node(int data, Node* previous = nullptr) { 10 | this->data = data; 11 | this->previous = previous; 12 | } 13 | }; 14 | 15 | class Stack { 16 | private: 17 | Node* top = nullptr; 18 | public: 19 | Stack() { } 20 | 21 | void _copyStackRecursive(Node* current) { 22 | if (current != nullptr) { 23 | _copyStackRecursive(current->previous); 24 | push(current->data); 25 | } 26 | } 27 | 28 | void copyStack(const Stack& rhs) { 29 | _copyStackRecursive(rhs.top); 30 | } 31 | 32 | void freeMemory() { 33 | while(top != nullptr) { 34 | Node* previous = top->previous; 35 | delete top; 36 | top = previous; 37 | } 38 | } 39 | 40 | Stack(const Stack& rhs) { 41 | copyStack(rhs); 42 | } 43 | 44 | Stack& operator=(const Stack& rhs) { 45 | if (this != &rhs) { 46 | freeMemory(); 47 | copyStack(rhs); 48 | } 49 | return *this; 50 | } 51 | 52 | ~Stack() { 53 | freeMemory(); 54 | } 55 | 56 | void push(int number) { 57 | if (isEmpty()) { 58 | top = new Node(number); 59 | } else { 60 | Node* newTop = new Node(number, top); 61 | top = newTop; 62 | } 63 | } 64 | 65 | void pop() { 66 | if (!isEmpty()) { 67 | Node* oldTop = top; 68 | top = top->previous; 69 | delete oldTop; 70 | } else { 71 | throw std::underflow_error("Stack is empty"); 72 | } 73 | } 74 | 75 | int peek() const { 76 | if (!isEmpty()) { 77 | return top->data; 78 | } else { 79 | throw std::underflow_error("Stack is empty"); 80 | } 81 | } 82 | 83 | bool isEmpty() const { 84 | return top == nullptr; 85 | } 86 | }; 87 | 88 | int main() { 89 | Stack s; 90 | s.push(1); 91 | s.push(2); 92 | s.push(3); 93 | 94 | Stack d(s); 95 | while (!d.isEmpty()) { 96 | cout << d.peek(); 97 | d.pop(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Examples/c++/Stack/stack-using-list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class Stack { 7 | private: 8 | list data; 9 | public: 10 | void push(int number) { 11 | data.push_back(number); 12 | } 13 | 14 | void pop() { 15 | data.pop_back(); 16 | } 17 | 18 | int peek() const { 19 | if (data.size() > 0) { 20 | return data.back(); 21 | } else { 22 | throw std::underflow_error("Stack is empty"); 23 | } 24 | } 25 | 26 | bool isEmpty() const { 27 | return data.size() == 0; 28 | } 29 | }; 30 | 31 | int main() { 32 | Stack s; 33 | s.push(1); 34 | s.push(2); 35 | s.push(3); 36 | 37 | while (!s.isEmpty()) { 38 | cout << s.peek(); 39 | s.pop(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Examples/c++/Stack/stack-using-vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class Stack { 7 | private: 8 | vector data; 9 | public: 10 | void push(int number) { 11 | data.push_back(number); 12 | } 13 | 14 | void pop() { 15 | data.pop_back(); 16 | } 17 | 18 | int peek() const { 19 | if (data.size() > 0) { 20 | return data.back(); 21 | } else { 22 | throw std::underflow_error("Stack is empty"); 23 | } 24 | } 25 | 26 | bool isEmpty() const { 27 | return data.size() == 0; 28 | } 29 | }; 30 | 31 | int main() { 32 | Stack s; 33 | s.push(1); 34 | s.push(2); 35 | s.push(3); 36 | // s.push(4); // overflow 37 | cout << s.peek(); // 3 38 | s.pop(); 39 | cout << s.peek(); // 2 40 | s.pop(); 41 | cout << s.peek(); // 1 42 | s.pop(); 43 | // s.pop(); // underflow 44 | cout << s.isEmpty(); // 1 = true, is indeed empty 45 | } 46 | -------------------------------------------------------------------------------- /Examples/java/02-Searching/SearchTest.java: -------------------------------------------------------------------------------- 1 | package search; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | public class SearchTest { 12 | private static final List testList = Arrays.asList(1, 5, 9, 17, 33, 75); 13 | 14 | @Test 15 | public void testBinarySearchPositive() { 16 | Assert.assertTrue(Search.binarySearch(testList, 17)); 17 | } 18 | 19 | @Test 20 | public void testBinarySearchNegative() { 21 | Assert.assertFalse(Search.binarySearch(testList, 16)); 22 | } 23 | 24 | @Test 25 | public void testJumpSearchPositive() { 26 | Assert.assertTrue(Search.jumpSearch(testList, 17)); 27 | } 28 | 29 | @Test 30 | public void testJumpSearchNegative() { 31 | Assert.assertFalse(Search.jumpSearch(testList, 16)); 32 | } 33 | 34 | @Test 35 | public void testExponentialSearchPositive() { 36 | Assert.assertTrue(Search.exponentialSearch(testList, 17)); 37 | } 38 | 39 | @Test 40 | public void testExponentialSearchNegative() { 41 | Assert.assertFalse(Search.exponentialSearch(testList, 16)); 42 | } 43 | 44 | @Test 45 | public void testTernarySearchPositive() { 46 | Assert.assertTrue(Search.ternarySearch(testList, 17)); 47 | } 48 | 49 | @Test 50 | public void testTernarySearchNegative() { 51 | Assert.assertFalse(Search.ternarySearch(testList, 16)); 52 | } 53 | 54 | @Test 55 | public void testKthSmallestPositive() { 56 | List shuffledList = new ArrayList<>(testList); 57 | Collections.shuffle(shuffledList); 58 | Assert.assertEquals(9, (int) Search.kthSmallestElement(shuffledList, 3)); 59 | } 60 | 61 | @Test 62 | public void testTKthSmallestPNegative() { 63 | List shuffledList = new ArrayList<>(testList); 64 | Collections.shuffle(shuffledList); 65 | Assert.assertNull(Search.kthSmallestElement(shuffledList, 16)); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Examples/java/03-Sorting/SortTest.java: -------------------------------------------------------------------------------- 1 | package Sorting; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | public class SortTest { 11 | private static final List testList = Arrays.asList(5, 1, 4, 7, 13, 2); 12 | private static final List sortedList = Arrays.asList(1, 2, 4, 5, 7, 13); 13 | 14 | @Test 15 | public void testSelectionSort() { 16 | List list = new ArrayList<>(testList); 17 | Sort.selectionSort(list); 18 | Assert.assertEquals(sortedList, list); 19 | } 20 | 21 | @Test 22 | public void testBubbleSort() { 23 | List list = new ArrayList<>(testList); 24 | Sort.bubbleSort(list); 25 | Assert.assertEquals(sortedList, list); 26 | } 27 | 28 | @Test 29 | public void testInsertionSort() { 30 | List list = new ArrayList<>(testList); 31 | Sort.insertionSort(list); 32 | Assert.assertEquals(sortedList, list); 33 | } 34 | 35 | @Test 36 | public void testQuickSort() { 37 | List list = new ArrayList<>(testList); 38 | Sort.quickSort(list); 39 | Assert.assertEquals(sortedList, list); 40 | } 41 | 42 | @Test 43 | public void testMergeSort() { 44 | List list = new ArrayList<>(testList); 45 | Sort.mergeSort(list); 46 | Assert.assertEquals(sortedList, list); 47 | } 48 | 49 | @Test 50 | public void testHeapSort() { 51 | List list = new ArrayList<>(testList); 52 | Sort.heapSort(list); 53 | Assert.assertEquals(sortedList, list); 54 | } 55 | 56 | @Test 57 | public void testCountingSort() { 58 | List list = new ArrayList<>(testList); 59 | Sort.countingSort(list); 60 | Assert.assertEquals(sortedList, list); 61 | } 62 | 63 | @Test 64 | public void testRadixSort() { 65 | List list = new ArrayList<>(testList); 66 | Sort.radixSort(list); 67 | Assert.assertEquals(sortedList, list); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Examples/java/04-LinkedList/DoublyLinkedListTest.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class DoublyLinkedListTest { 7 | @Test 8 | public void testDoublyLinkedList() { 9 | DoublyLinkedList list = new DoublyLinkedList<>(); 10 | 11 | list.addToBeginning(1); 12 | list.addToEnd(5); 13 | list.insertAt(4,1); 14 | list.insertAt(19, 2); 15 | 16 | Assert.assertEquals("[1, 4, 19, 5]", list.toString()); 17 | 18 | list.reverse(); 19 | Assert.assertEquals("[5, 19, 4, 1]", list.toString()); 20 | 21 | list.eraseAt(1); 22 | list.eraseEnd(); 23 | Assert.assertEquals("[5, 4]", list.toString()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Examples/java/04-LinkedList/LinkedList.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | import java.util.Iterator; 4 | 5 | /** 6 | * Singly Linked List. 7 | * Each element has a link to the next element. 8 | * 9 | * O(1) access, insertion and deletion at the beginning of the list. 10 | * O(1) access and insertion at the ending of the list. 11 | * O(size) deletion at the ending of the list. 12 | * O(size) access, insertion and deletion in the middle of the list. 13 | * 14 | * @param Type of the objects stored in the Linked List 15 | */ 16 | public class LinkedList implements Iterable { 17 | private class Node { 18 | T value; 19 | Node link; 20 | 21 | Node () { 22 | value = null; 23 | link = null; 24 | } 25 | 26 | Node (T v, Node l) { 27 | value = v; 28 | link = l; 29 | } 30 | } 31 | 32 | private Node first; 33 | private Node last; 34 | 35 | private int size; 36 | 37 | /** 38 | * Create an empty linked list 39 | */ 40 | public LinkedList() { 41 | first = null; 42 | last = null; 43 | size = 0; 44 | } 45 | 46 | /** 47 | * Insert the object at the end of the linked list. 48 | * 49 | * @param value The object ot be inserted. 50 | */ 51 | public void addToEnd(T value) { 52 | size++; 53 | 54 | if (last == null) { 55 | first = new Node(value, null); 56 | last = first; 57 | return; 58 | } 59 | 60 | last.link = new Node(value, null);; 61 | last = last.link; 62 | } 63 | 64 | /** 65 | * Insert the object at the start of the linked list. 66 | * 67 | * @param value The object ot be inserted. 68 | */ 69 | public void addToBeginning(T value) { 70 | size++; 71 | 72 | if (first == null) { 73 | first = new Node(value, null); 74 | last = first; 75 | return; 76 | } 77 | 78 | first = new Node(value, first); 79 | } 80 | 81 | /** 82 | * Insert the object at a given position in the linked list. 83 | * 84 | * @param value The object ot be inserted. 85 | * @param position The position of the insertion. 86 | */ 87 | public void insertAt(T value, int position) { 88 | if (position < 0) { 89 | throw new IllegalArgumentException("Can't add element at negative position"); 90 | } 91 | 92 | if (position >= size) { 93 | addToEnd(value); 94 | return; 95 | } 96 | 97 | if (position == 0) { 98 | addToBeginning(value); 99 | return; 100 | } 101 | 102 | size++; 103 | 104 | Node temp = goToPosition(position - 1); 105 | temp.link = new Node(value, temp.link); 106 | } 107 | 108 | /** 109 | * Erase the first element of the linked list. 110 | */ 111 | public void eraseBeginning() { 112 | if (size == 0) { 113 | throw new IllegalStateException("Can't delete form an empty LinkedList"); 114 | } 115 | 116 | size--; 117 | first = first.link; 118 | } 119 | 120 | /** 121 | * Erase the last element of the linked list. 122 | */ 123 | public void eraseEnd() { 124 | if (size == 0) { 125 | throw new IllegalStateException("Can't delete form an empty LinkedList"); 126 | } 127 | 128 | size--; 129 | 130 | Node temp = goToPosition(size - 1); 131 | 132 | temp.link = null; 133 | last = temp; 134 | } 135 | 136 | /** 137 | * Erase the element at a given position in the linked list. 138 | * 139 | * @param position The position of the object. 140 | */ 141 | public void eraseAt(int position) { 142 | if (position < 0 || position >= size) { 143 | throw new IllegalArgumentException("Position is out of bounds"); 144 | } 145 | 146 | if (position == 0) { 147 | eraseBeginning(); 148 | return; 149 | } 150 | 151 | if (position == size - 1) { 152 | eraseEnd(); 153 | return; 154 | } 155 | 156 | size--; 157 | 158 | Node temp = goToPosition(position - 1); 159 | temp.link = temp.link.link; 160 | } 161 | 162 | /** 163 | * Return the last element of the linked list. 164 | * 165 | * @return Reference to the object. 166 | */ 167 | public T getBeginning() { 168 | if (size == 0) { 169 | return null; 170 | } 171 | 172 | return first.value; 173 | } 174 | 175 | /** 176 | * Return the first element of the linked list. 177 | * 178 | * @return Reference to the object. 179 | */ 180 | public T getEnd() { 181 | if (size == 0) { 182 | return null; 183 | } 184 | 185 | return last.value; 186 | } 187 | 188 | /** 189 | * Return the element at a given position in the linked list. 190 | * 191 | * @param position The position of the object. 192 | * @return Reference to the object. 193 | */ 194 | public T get(int position) { 195 | if (position < 0 || position >= size) { 196 | throw new IllegalArgumentException("Position is out of bounds"); 197 | } 198 | 199 | return goToPosition(position).value; 200 | } 201 | 202 | /** 203 | * Reverse the elements of the linked list. 204 | * O(size) complexity. 205 | */ 206 | public void reverse() { 207 | if (size == 2) { 208 | T temp = first.value; 209 | first.value = last.value; 210 | last.value = temp; 211 | return; 212 | } 213 | 214 | Node prev = first; 215 | Node cur = prev.link; 216 | Node next = cur.link; 217 | 218 | while (next != null) { 219 | cur.link = prev; 220 | 221 | prev = cur; 222 | cur = next; 223 | next = next.link; 224 | } 225 | 226 | cur.link = prev; 227 | first.link = null; 228 | 229 | Node temp = first; 230 | first = last; 231 | last = temp; 232 | } 233 | 234 | /** 235 | * @return Current number of elements in the linked list. 236 | */ 237 | public int size() { 238 | return size; 239 | } 240 | 241 | @Override 242 | public String toString() { 243 | StringBuilder sb = new StringBuilder(); 244 | 245 | sb.append("["); 246 | 247 | this.forEach(value -> sb.append(value.toString()).append(", ")); 248 | 249 | if (size > 0) { 250 | sb.delete(sb.length() - 2, sb.length()); 251 | } 252 | 253 | sb.append("]"); 254 | 255 | return sb.toString(); 256 | } 257 | 258 | @Override 259 | public Iterator iterator() { 260 | return new LinkedListIterator(); 261 | } 262 | 263 | private Node goToPosition(int position) { 264 | int index = 0; 265 | Node temp = first; 266 | 267 | while (index < position) { 268 | index++; 269 | temp = temp.link; 270 | } 271 | 272 | return temp; 273 | } 274 | 275 | private class LinkedListIterator implements Iterator { 276 | 277 | private int index = 0; 278 | private Node current = first; 279 | 280 | @Override 281 | public boolean hasNext() { 282 | return current != null; 283 | } 284 | 285 | @Override 286 | public T next() { 287 | T value = current.value; 288 | 289 | index++; 290 | current = current.link; 291 | 292 | return value; 293 | } 294 | 295 | @Override 296 | public void remove() { 297 | eraseAt(index); 298 | } 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /Examples/java/04-LinkedList/LinkedListTest.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class LinkedListTest { 7 | @Test 8 | public void testLinkedList() { 9 | LinkedList list = new LinkedList<>(); 10 | 11 | list.addToBeginning(1); 12 | list.addToEnd(5); 13 | list.insertAt(4,1); 14 | list.insertAt(19, 2); 15 | Assert.assertEquals("[1, 4, 19, 5]", list.toString()); 16 | 17 | list.reverse(); 18 | Assert.assertEquals("[5, 19, 4, 1]", list.toString()); 19 | 20 | list.eraseAt(1); 21 | list.eraseEnd(); 22 | Assert.assertEquals("[5, 4]", list.toString()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Examples/java/05-Queue/MinQueue.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | /** 4 | * Queue implementation with an array. 5 | * O(1) push, pop and front operations (Constant Amortized Time) 6 | * O(1) minimum element retrieval with O(size) extra space 7 | * 8 | * @param Type of the elements of the stack. 9 | */ 10 | public class MinQueue> extends Queue { 11 | private final DoublyLinkedList minList; 12 | 13 | /** 14 | * Create an empty queue. 15 | */ 16 | public MinQueue() { 17 | super(); 18 | minList = new DoublyLinkedList<>(); 19 | } 20 | 21 | /** 22 | * Add an element to the back of the queue. 23 | * 24 | * @param value Object to be added. 25 | */ 26 | @Override 27 | public void push(T value) { 28 | while (minList.size() > 0 && minList.getEnd().compareTo(value) > 0) { 29 | minList.eraseEnd(); 30 | } 31 | minList.addToEnd(value); 32 | 33 | super.push(value); 34 | } 35 | 36 | /** 37 | * Remove an element from the front of the queue. 38 | */ 39 | @Override 40 | public void pop() { 41 | if (minList.size() == 0) { 42 | throw new IllegalStateException("Queue is empty"); 43 | } 44 | 45 | if (minList.getBeginning().compareTo(super.front()) == 0) { 46 | minList.eraseBeginning(); 47 | } 48 | 49 | super.pop(); 50 | } 51 | 52 | /** 53 | * Remove the front element from the queue. 54 | * 55 | * @return Reference to the removed object. 56 | */ 57 | @Override 58 | public T poll() { 59 | T result = super.front(); 60 | pop(); 61 | return result; 62 | } 63 | 64 | /** 65 | * Return the minimum element in the queue. 66 | * 67 | * @return Reference to the object. 68 | */ 69 | public T minimum() { 70 | if (minList.size() == 0) { 71 | throw new IllegalStateException("Queue is empty"); 72 | } 73 | 74 | return minList.getBeginning(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Examples/java/05-Queue/Queue.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | /** 4 | * * Queue implementation with an array. 5 | * * O(1) push, pop and front operations (Constant Amortized Time) 6 | * 7 | * @param Type of the elements of the stack. 8 | */ 9 | public class Queue { 10 | private static final int DEFAULT_CAPACITY = 16; 11 | 12 | private Object[] elements; 13 | private int capacity; 14 | private int left; 15 | private int right; 16 | 17 | /** 18 | * Create an empty queue. 19 | */ 20 | public Queue() { 21 | elements = new Object[DEFAULT_CAPACITY]; 22 | capacity = DEFAULT_CAPACITY; 23 | left = 0; 24 | right = -1; 25 | } 26 | 27 | /** 28 | * Add an element to the back of the queue. 29 | * 30 | * @param value Object to be added. 31 | */ 32 | public void push(T value) { 33 | checkCapacity(right - left + 2); 34 | 35 | if (right + 1 == capacity) { 36 | shift(); 37 | } 38 | 39 | elements[++right] = value; 40 | } 41 | 42 | /** 43 | * Return the element at the front of the queue. 44 | * 45 | * @throws IllegalStateException when the queue is empty. 46 | * @return Reference to the object. 47 | */ 48 | public T front() { 49 | if (left > right) { 50 | throw new IllegalStateException("Queue is empty"); 51 | } 52 | 53 | return (T) elements[left]; 54 | } 55 | 56 | /** 57 | * Remove an element from the front of the queue. 58 | * 59 | * @throws IllegalStateException when the queue is empty. 60 | */ 61 | public void pop() { 62 | if (left > right) { 63 | throw new IllegalStateException("Queue is empty"); 64 | } 65 | 66 | checkCapacity(right - left); 67 | left++; 68 | } 69 | 70 | /** 71 | * Remove the front element from the queue. 72 | * 73 | * @return Reference to the removed object. 74 | */ 75 | public T poll() { 76 | T result = front(); 77 | pop(); 78 | return result; 79 | } 80 | 81 | public int size() { 82 | return right - left + 1; 83 | } 84 | 85 | public boolean empty() { 86 | return size() == 0; 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | StringBuilder sb = new StringBuilder(); 92 | 93 | sb.append("["); 94 | 95 | for (int i = left; i <= right; i++) { 96 | sb.append(elements[i].toString()).append(", "); 97 | } 98 | 99 | if (left <= right) { 100 | sb.delete(sb.length() - 2, sb.length()); 101 | } 102 | 103 | sb.append("]"); 104 | 105 | return sb.toString(); 106 | } 107 | 108 | private void checkCapacity(int newSize) { 109 | if (newSize >= 2 * capacity / 3) { 110 | resize(capacity * 2); 111 | } 112 | 113 | if (newSize <= capacity / 3 && capacity > DEFAULT_CAPACITY) { 114 | resize(capacity / 2); 115 | } 116 | } 117 | 118 | private void resize(int newCapacity) { 119 | Object[] temp = new Object[right - left + 1]; 120 | 121 | System.arraycopy(elements, left, temp, left, right - left + 1); 122 | 123 | capacity = newCapacity; 124 | elements = new Object[capacity]; 125 | 126 | System.arraycopy(temp, 0, elements, 0, right - left + 1); 127 | } 128 | 129 | private void shift() { 130 | for (int i = 0; i < right - left + 1; i++) { 131 | elements[i] = elements[left + 1]; 132 | } 133 | 134 | right = right - left; 135 | left = 0; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /Examples/java/05-Queue/QueueTest.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class QueueTest { 7 | @Test 8 | public void testQueue() { 9 | Queue queue = new Queue<>(); 10 | 11 | queue.push(1); 12 | queue.push(7); 13 | queue.push(73); 14 | queue.push(2); 15 | 16 | Assert.assertEquals(1, (int) queue.poll()); 17 | Assert.assertEquals(7, (int) queue.front()); 18 | Assert.assertEquals("[7, 73, 2]", queue.toString()); 19 | } 20 | 21 | @Test 22 | public void testMinQueue() { 23 | MinQueue queue = new MinQueue<>(); 24 | 25 | queue.push(9); 26 | Assert.assertEquals(9, (int) queue.minimum()); 27 | 28 | queue.push(7); 29 | Assert.assertEquals(7, (int) queue.minimum()); 30 | 31 | queue.push(2); 32 | Assert.assertEquals(2, (int) queue.minimum()); 33 | 34 | queue.push(73); 35 | Assert.assertEquals(2, (int) queue.minimum()); 36 | 37 | queue.push(5); 38 | Assert.assertEquals(2, (int) queue.minimum()); 39 | 40 | queue.pop(); 41 | queue.pop(); 42 | queue.pop(); 43 | Assert.assertEquals(5, (int) queue.minimum()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Examples/java/06-Stack/MinStack.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | /** 4 | * Stack implementation with an array. 5 | * O(1) push, pop and top operations (Constant Amortized Time) 6 | * O(1) minimum retrieval with O(size) extra space 7 | * 8 | * @param Type of the elements of the stack. 9 | */ 10 | public class MinStack> extends Stack { 11 | private final Stack minStack; 12 | 13 | /** 14 | * Create an empty stack. 15 | */ 16 | public MinStack() { 17 | super(); 18 | minStack = new Stack<>(); 19 | } 20 | 21 | /** 22 | * Add an element to the top of the stack. 23 | * 24 | * @param value Object to be added. 25 | */ 26 | @Override 27 | public void push(T value) { 28 | super.push(value); 29 | 30 | if (minStack.size() == 0 || value.compareTo(minStack.top()) < 0) { 31 | minStack.push(value); 32 | } 33 | } 34 | 35 | /** 36 | * Remove an element from the top of the stack. 37 | */ 38 | @Override 39 | public void pop() { 40 | if (minStack.size() == 0) { 41 | throw new IllegalStateException("Stack is empty"); 42 | } 43 | 44 | if (minStack.top().compareTo(super.top()) == 0) { 45 | minStack.pop(); 46 | } 47 | 48 | super.pop(); 49 | } 50 | 51 | /** 52 | * Remove the top element from the stack. 53 | * 54 | * @return Reference to the removed object. 55 | */ 56 | @Override 57 | public T poll() { 58 | T result = super.top(); 59 | pop(); 60 | return result; 61 | } 62 | 63 | /** 64 | * Return the minimum element in the stack. 65 | * 66 | * @return Reference to the object. 67 | */ 68 | public T minimum() { 69 | if (minStack.size() == 0) { 70 | throw new IllegalStateException("Stack is empty"); 71 | } 72 | 73 | return minStack.top(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Examples/java/06-Stack/Stack.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | /** 4 | * Stack implementation with an array. 5 | * O(1) push, pop and top operations (Constant Amortized Time) 6 | * 7 | * @param Type of the elements of the stack. 8 | */ 9 | public class Stack { 10 | private static final int DEFAULT_CAPACITY = 16; 11 | 12 | private Object[] elements; 13 | private int capacity; 14 | private int size; 15 | 16 | /** 17 | * Create an empty stack. 18 | */ 19 | public Stack() { 20 | elements = new Object[DEFAULT_CAPACITY]; 21 | capacity = DEFAULT_CAPACITY; 22 | size = 0; 23 | } 24 | 25 | /** 26 | * Add an element to the top of the stack. 27 | * 28 | * @param value Object to be added. 29 | */ 30 | public void push(T value) { 31 | checkCapacity(size + 1); 32 | elements[size++] = value; 33 | } 34 | 35 | /** 36 | * Return the element at the top of the stack. 37 | * 38 | * @return Reference to the object. 39 | */ 40 | @SuppressWarnings("unchecked") 41 | public T top() { 42 | if (size == 0) { 43 | throw new IllegalStateException("Stack is empty"); 44 | } 45 | 46 | return (T) elements[size - 1]; 47 | } 48 | 49 | /** 50 | * Remove an element from the top of the stack. 51 | */ 52 | public void pop() { 53 | if (size == 0) { 54 | throw new IllegalStateException("Stack is empty"); 55 | } 56 | 57 | size--; 58 | } 59 | 60 | /** 61 | * Remove the top element from the stack. 62 | * 63 | * @return Reference to the removed object. 64 | */ 65 | public T poll() { 66 | T result = top(); 67 | pop(); 68 | return result; 69 | } 70 | 71 | /** 72 | * @return The current number of elements in the stack. 73 | */ 74 | public int size() { 75 | return size; 76 | } 77 | 78 | /** 79 | * @return True if the stack has no elements and false otherwise. 80 | */ 81 | public boolean empty() { 82 | return size == 0; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | StringBuilder sb = new StringBuilder(); 88 | 89 | sb.append("["); 90 | 91 | for (int i = 0; i < size; i++) { 92 | sb.append(elements[i].toString()).append(", "); 93 | } 94 | 95 | if (size > 0) { 96 | sb.delete(sb.length() - 2, sb.length()); 97 | } 98 | 99 | sb.append("]"); 100 | 101 | return sb.toString(); 102 | } 103 | 104 | private void checkCapacity(int newSize) { 105 | if (newSize >= 2 * capacity / 3) { 106 | resize(capacity * 2); 107 | } 108 | 109 | if (newSize <= capacity / 3 && capacity > DEFAULT_CAPACITY) { 110 | resize(capacity / 2); 111 | } 112 | } 113 | 114 | private void resize(int newCapacity) { 115 | Object[] temp = new Object[size]; 116 | 117 | System.arraycopy(elements, 0, temp, 0, size); 118 | 119 | capacity = newCapacity; 120 | elements = new Object[capacity]; 121 | 122 | System.arraycopy(temp, 0, elements, 0, size); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Examples/java/06-Stack/StackTest.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class StackTest { 7 | @Test 8 | public void testStack() { 9 | Stack stack = new Stack<>(); 10 | stack.push(1); 11 | stack.push(7); 12 | stack.push(73); 13 | stack.push(2); 14 | 15 | Assert.assertEquals(2, (int) stack.poll()); 16 | Assert.assertEquals(73, (int) stack.top()); 17 | Assert.assertEquals("[1, 7, 73]", stack.toString()); 18 | } 19 | 20 | @Test 21 | public void testMinStack() { 22 | MinStack stack = new MinStack<>(); 23 | 24 | stack.push(3); 25 | Assert.assertEquals(3, (int) stack.minimum()); 26 | 27 | stack.push(7); 28 | Assert.assertEquals(3, (int) stack.minimum()); 29 | 30 | stack.push(2); 31 | Assert.assertEquals(2, (int) stack.minimum()); 32 | 33 | stack.push(73); 34 | Assert.assertEquals(2, (int) stack.minimum()); 35 | 36 | stack.push(5); 37 | Assert.assertEquals(2, (int) stack.minimum()); 38 | 39 | stack.pop(); 40 | stack.pop(); 41 | stack.pop(); 42 | Assert.assertEquals(3, (int) stack.minimum()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Examples/java/09-Heap/Heap.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Heap implementation with an array. 7 | * O(1) top operation. 8 | * O(log N) push and pop operations. 9 | * 10 | * @param Type of the elements of the stack. 11 | */ 12 | public class Heap> { 13 | private static final int DEFAULT_CAPACITY = 16; 14 | 15 | private Object[] elements; 16 | 17 | private int capacity; 18 | private int size; 19 | 20 | private Comparator comparator; 21 | 22 | public Heap(Comparator comparator) { 23 | this.comparator = comparator; 24 | 25 | this.elements = new Object[DEFAULT_CAPACITY]; 26 | this.size = 0; 27 | this.capacity = DEFAULT_CAPACITY; 28 | } 29 | 30 | public void push(T value) { 31 | checkCapacity(size + 1); 32 | elements[size++] = value; 33 | pushUp(size - 1); 34 | } 35 | 36 | void pop() { 37 | if (size == 0) { 38 | return; 39 | } 40 | 41 | checkCapacity(size - 1); 42 | 43 | size--; 44 | Object temp = elements[0]; 45 | elements[0] = elements[size]; 46 | elements[size] = temp; 47 | heapify(0); 48 | } 49 | 50 | @SuppressWarnings("unchecked") 51 | public T top() { 52 | return (T) elements[0]; 53 | } 54 | 55 | public T poll() { 56 | T returnValue = top(); 57 | pop(); 58 | return returnValue; 59 | } 60 | 61 | public int size() { 62 | return size; 63 | } 64 | 65 | public boolean empty() { 66 | return size == 0; 67 | } 68 | 69 | @SuppressWarnings("unchecked") 70 | private void pushUp(int node) { 71 | int parent = (node - 1) / 2; 72 | while (node != 0 && comparator.compare((T) elements[node], (T) elements[parent]) < 0) { 73 | Object temp = elements[node]; 74 | elements[node] = elements[parent]; 75 | elements[parent] = temp; 76 | 77 | node = parent; 78 | parent = (node - 1) / 2; 79 | } 80 | } 81 | 82 | @SuppressWarnings("unchecked") 83 | private void heapify(int node) { 84 | int left = 2 * node + 1; 85 | int right = 2 * node + 2; 86 | 87 | int nextNode = node; 88 | 89 | if (left < size && comparator.compare((T) elements[left], (T) elements[nextNode]) < 0) { 90 | nextNode = left; 91 | } 92 | 93 | if (right < size && comparator.compare((T) elements[right], (T) elements[nextNode]) < 0) { 94 | nextNode = right; 95 | } 96 | 97 | if (nextNode != node) { 98 | Object temp = elements[node]; 99 | elements[node] = elements[nextNode]; 100 | elements[nextNode] = temp; 101 | 102 | heapify(nextNode); 103 | } 104 | } 105 | 106 | private void checkCapacity(int newSize) { 107 | if (newSize >= 2 * capacity / 3) { 108 | resize(capacity * 2); 109 | } 110 | 111 | if (newSize <= capacity / 3 && capacity > DEFAULT_CAPACITY) { 112 | resize(capacity / 2); 113 | } 114 | } 115 | 116 | private void resize(int newCapacity) { 117 | Object[] temp = new Object[size]; 118 | 119 | System.arraycopy(elements, 0, temp, 0, size); 120 | 121 | capacity = newCapacity; 122 | elements = new Object[capacity]; 123 | 124 | System.arraycopy(temp, 0, elements, 0, size); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Examples/java/09-Heap/HeapTest.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class HeapTest { 7 | @Test 8 | public void testMinHeap() { 9 | Heap heap = new Heap<>(Integer::compare); 10 | heap.push(7); 11 | heap.push(5); 12 | 13 | Assert.assertEquals(new Integer(5), heap.top()); 14 | 15 | heap.push(6); 16 | heap.push(3); 17 | 18 | Assert.assertEquals(new Integer(3), heap.poll()); 19 | Assert.assertEquals(new Integer(5), heap.poll()); 20 | Assert.assertEquals(new Integer(6), heap.poll()); 21 | Assert.assertEquals(new Integer(7), heap.poll()); 22 | } 23 | 24 | @Test 25 | public void testMaxHeap() { 26 | Heap heap = new Heap<>((integer, t1) -> Integer.compare(t1, integer)); 27 | heap.push(7); 28 | heap.push(5); 29 | 30 | Assert.assertEquals(new Integer(7), heap.top()); 31 | 32 | heap.push(9); 33 | heap.push(3); 34 | 35 | Assert.assertEquals(new Integer(9), heap.poll()); 36 | Assert.assertEquals(new Integer(7), heap.poll()); 37 | Assert.assertEquals(new Integer(5), heap.poll()); 38 | Assert.assertEquals(new Integer(3), heap.poll()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Examples/java/11-Hashmap/HashTable.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Objects; 6 | import java.util.function.BiConsumer; 7 | 8 | /** 9 | * Hash table implementation with the bucket mechanism for conflict resolution. 10 | * 11 | * O(1) put, get, remove operations (Constant Amortized Time) 12 | * 13 | * @param Type of the keys 14 | * @param Type of the values 15 | */ 16 | public class HashTable { 17 | private static final int DEFAULT_SIZE = 16; 18 | 19 | static class Node { 20 | K key; 21 | V value; 22 | 23 | Node next; 24 | 25 | public Node(K key, V value) { 26 | this.key = key; 27 | this.value = value; 28 | } 29 | } 30 | 31 | private List> buckets; 32 | 33 | private int numberOfBuckets; 34 | private int emptyBuckets; 35 | 36 | private int size; 37 | 38 | /** 39 | * Create an empty hash table. 40 | */ 41 | public HashTable() { 42 | buckets = new ArrayList<>(); 43 | numberOfBuckets = DEFAULT_SIZE; 44 | emptyBuckets = DEFAULT_SIZE; 45 | size = 0; 46 | 47 | for (int i = 0; i < DEFAULT_SIZE; i++) 48 | buckets.add(null); 49 | } 50 | 51 | /** 52 | * Add a (key, value) to the hash table. 53 | * @param key Object representing the key. 54 | * @param value Object representing the value. 55 | */ 56 | public void put(K key, V value) { 57 | if (get(key) != null) { 58 | return; 59 | } 60 | 61 | size++; 62 | 63 | int bucketIndex = getBucketIndex(key); 64 | Node current = buckets.get(bucketIndex); 65 | Node newNode = new Node<>(key, value); 66 | 67 | if (buckets.get(bucketIndex) == null) { 68 | emptyBuckets--; 69 | } 70 | 71 | newNode.next = current; 72 | buckets.set(bucketIndex, newNode); 73 | 74 | if (size >= 2 * numberOfBuckets / 3) { 75 | resize(2 * numberOfBuckets); 76 | } 77 | } 78 | 79 | /** 80 | * Returns the value corresponding to the (key, value) pair with the given key. 81 | * 82 | * @param key Key corresponding to the needed value. 83 | * @return Object reference to the value corresponding to the given key. 84 | */ 85 | public V get(K key) { 86 | int bucketIndex = getBucketIndex(key); 87 | Node current = buckets.get(bucketIndex); 88 | 89 | while (current != null) { 90 | if (current.key.equals(key)) { 91 | return current.value; 92 | } 93 | current = current.next; 94 | } 95 | 96 | return null; 97 | } 98 | 99 | /** 100 | * Erase the (key, value) pair with the given key. 101 | * 102 | * @param key Key corresponding to the value that needs to be erased. 103 | */ 104 | public void erase(K key) { 105 | int bucketIndex = getBucketIndex(key); 106 | 107 | Node current = buckets.get(bucketIndex); 108 | Node previous = null; 109 | 110 | while (current != null && !current.key.equals(key)) { 111 | previous = current; 112 | current = current.next; 113 | } 114 | 115 | if (current == null) { 116 | return; 117 | } 118 | 119 | size--; 120 | 121 | if (previous != null) { 122 | previous.next = current.next; 123 | return; 124 | } 125 | 126 | buckets.set(bucketIndex, current.next); 127 | 128 | if (buckets.get(bucketIndex) == null) { 129 | emptyBuckets++; 130 | } 131 | 132 | if (emptyBuckets >= 2 * numberOfBuckets / 3 && numberOfBuckets > DEFAULT_SIZE) { 133 | resize(numberOfBuckets / 2); 134 | } 135 | } 136 | 137 | /** 138 | * @return Current number of (key, value) pairs in the hash table. 139 | */ 140 | public int size() { 141 | return size; 142 | } 143 | 144 | /** 145 | * @return True if the hash table has no elements and false otherwise. 146 | */ 147 | public boolean empty() { 148 | return size == 0; 149 | } 150 | 151 | @Override 152 | public String toString() { 153 | StringBuilder sb = new StringBuilder(); 154 | sb.append("{"); 155 | 156 | this.forEach((key, value) -> { 157 | sb.append("(").append(key.toString()).append(", ").append(value.toString()).append("), "); 158 | }); 159 | 160 | if (sb.length() > 1) { 161 | sb.delete(sb.length() - 2, sb.length()); 162 | } 163 | 164 | sb.append("}"); 165 | return sb.toString(); 166 | } 167 | 168 | public void forEach(BiConsumer consumer) { 169 | Objects.requireNonNull(consumer); 170 | 171 | buckets.forEach(node -> { 172 | while (node != null) { 173 | consumer.accept(node.key, node.value); 174 | node = node.next; 175 | } 176 | }); 177 | } 178 | 179 | private void resize(int newSize) { 180 | List> temp = buckets; 181 | 182 | buckets = new ArrayList<>(); 183 | numberOfBuckets = newSize; 184 | size = 0; 185 | 186 | for (int i = 0; i < numberOfBuckets; i++) { 187 | buckets.add(null); 188 | } 189 | 190 | for (Node node : temp) { 191 | while (node != null) { 192 | put(node.key, node.value); 193 | node = node.next; 194 | } 195 | } 196 | } 197 | 198 | private int getBucketIndex(K key) { 199 | int hashCode = key.hashCode(); 200 | return hashCode % numberOfBuckets; 201 | } 202 | } -------------------------------------------------------------------------------- /Examples/java/11-Hashmap/HashTableTest.java: -------------------------------------------------------------------------------- 1 | package basic.data.structures; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class HashTableTest { 7 | @Test 8 | public void testHashTable() { 9 | HashTable map = new HashTable<>(); 10 | 11 | map.put("1", 1); 12 | map.put("2", 2); 13 | map.put("3", 3); 14 | map.put("4", 4); 15 | 16 | Assert.assertNull(map.get("7")); 17 | Assert.assertEquals(2, (int) map.get("2")); 18 | 19 | map.erase("3"); 20 | 21 | Assert.assertEquals("{(1, 1), (2, 2), (4, 4)}", map.toString()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/01-DFS.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.Stack; 4 | 5 | public class DFS { 6 | public static void dfs(Graph graph, int vertex) { 7 | graph.visited[vertex] = true; 8 | 9 | graph.adjacencyList.get(vertex).forEach(neighbour -> { 10 | if (!graph.visited[neighbour.to]) { 11 | dfs(graph, neighbour.to); 12 | } 13 | }); 14 | } 15 | 16 | public static void dfsIterative(Graph graph, int start) { 17 | Stack stack = new Stack<>(); 18 | stack.push(start); 19 | graph.visited[start] = true; 20 | 21 | while (!stack.empty()) { 22 | int vertex = stack.pop(); 23 | 24 | graph.adjacencyList.get(vertex).forEach(neighbour -> { 25 | if (!graph.visited[neighbour.to]) { 26 | stack.push(neighbour.to); 27 | graph.visited[neighbour.to] = true; 28 | } 29 | }); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/02-BFS.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import basic.data.structures.Queue; 4 | 5 | public class BFS { 6 | public static void bfs(Graph graph, int start) { 7 | Queue queue = new Queue<>(); 8 | queue.push(start); 9 | graph.visited[start] = true; 10 | 11 | while (!queue.empty()) { 12 | int vertex = queue.poll(); 13 | 14 | graph.adjacencyList.get(vertex).forEach(neighbour -> { 15 | if (!graph.visited[neighbour.to]) { 16 | queue.push(neighbour.to); 17 | graph.visited[neighbour.to] = true; 18 | } 19 | }); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/03-TopologicalSort.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.Stack; 7 | 8 | /** 9 | * Implementation of topological sorting 10 | * Works for acyclic directed graph (DAG) 11 | * O(n) complexity 12 | */ 13 | public class TopologicalSort { 14 | /** 15 | * Returns a list of all the vertices of the graph in their sorted order. 16 | */ 17 | public static List sortedVertices(DirectedGraph graph) { 18 | List result = new ArrayList<>(); 19 | Stack s = new Stack<>(); 20 | Arrays.fill(graph.visited, false); 21 | 22 | for (int vertex = 0; vertex < graph.vertices; vertex++) { 23 | if (!graph.visited[vertex]) { 24 | topSort(graph, vertex, s); 25 | } 26 | } 27 | Arrays.fill(graph.visited, false); 28 | 29 | while (!s.empty()) { 30 | result.add(s.pop()); 31 | } 32 | return result; 33 | } 34 | 35 | private static void topSort(DirectedGraph graph, int vertex, Stack s) { 36 | graph.visited[vertex] = true; 37 | 38 | graph.adjacencyList.get(vertex).forEach(neighbour -> { 39 | if (!graph.visited[neighbour.to]) { 40 | topSort(graph, neighbour.to, s); 41 | } 42 | }); 43 | 44 | s.push(vertex); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/04-Cycles.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Cycles { 6 | /** 7 | * Check if a graph contains a cycle. 8 | * O(V + E) 9 | * 10 | * @param graph Graph or DirectedGraph object. 11 | * @return true if the given graph has a cycle and false otherwise. 12 | */ 13 | public static boolean findCycle(Graph graph) { 14 | int[] colour = new int[graph.vertices]; 15 | Arrays.fill(colour, 0); 16 | 17 | if (graph instanceof DirectedGraph) { 18 | return findCycleDfs((DirectedGraph) graph, 0, colour); 19 | } 20 | 21 | return findCycleDfs(graph, 0, -1, colour); 22 | } 23 | 24 | private static boolean findCycleDfs(Graph graph, int vertex, int parent, int[] colour) { 25 | colour[vertex] = 1; 26 | 27 | for (Graph.ReachableVertex neighbour : graph.adjacencyList.get(vertex)) { 28 | if (colour[neighbour.to] == 0) { 29 | if (findCycleDfs(graph, neighbour.to, vertex, colour)) { 30 | return true; 31 | } 32 | } else if (colour[neighbour.to] == 1 && vertex != parent) { 33 | return true; 34 | } 35 | } 36 | 37 | colour[vertex] = 2; 38 | return false; 39 | } 40 | 41 | private static boolean findCycleDfs(DirectedGraph graph, int vertex, int[] colour) { 42 | colour[vertex] = 1; 43 | 44 | for (Graph.ReachableVertex neighbour : graph.adjacencyList.get(vertex)) { 45 | if (colour[neighbour.to] == 0) { 46 | if (findCycleDfs(graph, neighbour.to, vertex, colour)) { 47 | return true; 48 | } 49 | } else if (colour[neighbour.to] == 1) { 50 | return true; 51 | } 52 | } 53 | 54 | colour[vertex] = 2; 55 | return false; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/05-NumberOfPathsOfFixedLength.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.Arrays; 4 | 5 | public class NumberOfPathsOfFixedLength { 6 | public static class PathsIndex { 7 | private final int k; 8 | private int[][] matrix; 9 | 10 | /** 11 | * Create an index over the given graph that can answer 12 | * queries about the number of paths of some fixed length k. 13 | * 14 | * Build time: O(V^3) 15 | * Query time: O(1) 16 | * 17 | * @param k the length of the paths. 18 | */ 19 | public PathsIndex(Graph g, int k) { 20 | this.k = k; 21 | matrix = g.getAdjacencyMatrix(); 22 | for (int i = 0; i < matrix.length; i++) { 23 | for (int j = 0; j < matrix.length; j++) { 24 | if (matrix[i][j] > 0) { 25 | matrix[i][j] = 1; 26 | } 27 | } 28 | } 29 | matrix = powMatrix(matrix, k); 30 | } 31 | 32 | /** 33 | * Retrurns the number of paths starting at from and ending at to with length k. 34 | * 35 | * @param from starting vertex 36 | * @param to ending vertex 37 | * @return one integer - the number of paths. 38 | */ 39 | public int paths(int from, int to) { 40 | return matrix[from][to]; 41 | } 42 | 43 | /** 44 | * @return the length of the paths. 45 | */ 46 | public int pathLength() { 47 | return k; 48 | } 49 | 50 | private int[][] powMatrix(int[][] mat, int degree) { 51 | if (degree == 0) { 52 | return identityMatrix(mat.length); 53 | } 54 | 55 | if (degree == 1) { 56 | return mat; 57 | } 58 | 59 | int[][] res = powMatrix(mat, degree / 2); 60 | 61 | res = multiplyMatrix(res, res); 62 | 63 | if (degree % 2 == 0) { 64 | return res; 65 | } 66 | 67 | return multiplyMatrix(res, mat); 68 | } 69 | 70 | private int[][] identityMatrix(int size) { 71 | int[][] res = new int[size][size]; 72 | 73 | for (int i = 0; i < size; i++) { 74 | res[i][i] = 1; 75 | } 76 | 77 | return res; 78 | } 79 | 80 | private int[][] multiplyMatrix(int[][] a, int[][] b) { 81 | int[][] res = new int[a.length][a.length]; 82 | 83 | for (int i = 0; i < a.length; i++) { 84 | for (int j = 0; j < a.length; j++) { 85 | for (int p = 0; p < a.length; p++) { 86 | res[i][j] += a[i][p] * b[p][j]; 87 | } 88 | } 89 | } 90 | 91 | return res; 92 | } 93 | } 94 | 95 | /** 96 | * Create an index over the given graph that can answer 97 | * queries about the number of paths of some fixed length k. 98 | * 99 | * Build time: O(V^3) 100 | * Query time: O(1) 101 | * 102 | * @param k the length of the paths. 103 | */ 104 | public static PathsIndex createIndex(Graph graph, int k) { 105 | return new PathsIndex(graph, k); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/06-Bridges.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * Find all bridges in a graph 9 | * O(V + E) complexity 10 | */ 11 | public class Bridges { 12 | /** 13 | * Returns a list of all the brides in the given graph 14 | */ 15 | public static List getBridges(Graph graph) { 16 | List result = new ArrayList<>(); 17 | int[] in = new int[graph.vertices]; 18 | int[] low = new int[graph.vertices]; 19 | Integer timer = 0; 20 | Arrays.fill(graph.visited, false); 21 | 22 | for (int vertex = 0; vertex < graph.vertices; vertex++) { 23 | if (!graph.visited[vertex]) { 24 | dfs(graph, vertex, -1, in, low, timer, result); 25 | } 26 | } 27 | Arrays.fill(graph.visited, false); 28 | 29 | return result; 30 | } 31 | 32 | private static void dfs(Graph graph, int node, int parent, int[] in, int[] low, Integer timer, List bridges) { 33 | graph.visited[node] = true; 34 | in[node] = low[node] = timer++; 35 | 36 | for (Graph.ReachableVertex neighbour : graph.adjacencyList.get(node)) { 37 | if (!graph.visited[neighbour.to]) { 38 | dfs(graph, neighbour.to, node, in, low, timer, bridges); 39 | 40 | low[node] = Math.min(low[node], low[neighbour.to]); 41 | 42 | if (low[neighbour.to] > in[node]) { 43 | bridges.add(new Graph.Edge(node, neighbour.to)); 44 | } 45 | } else if (neighbour.to != parent) { 46 | low[node] = Math.min(low[node], in[neighbour.to]); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/07-ArticulationPoints.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * Find all articulation points in a graph 9 | * O(V + E) complexity 10 | */ 11 | public class ArticulationPoints { 12 | /** 13 | * Returns a list of all the articulation points in the given graph 14 | */ 15 | public static List getArticulationPoints(Graph graph) { 16 | List result = new ArrayList<>(); 17 | int[] in = new int[graph.vertices]; 18 | int[] low = new int[graph.vertices]; 19 | Integer timer = 0; 20 | Arrays.fill(graph.visited, false); 21 | 22 | for (int vertex = 0; vertex < graph.vertices; vertex++) { 23 | if (!graph.visited[vertex]) { 24 | dfs(graph, vertex, -1, in, low, timer, result); 25 | } 26 | } 27 | Arrays.fill(graph.visited, false); 28 | 29 | return result; 30 | } 31 | 32 | private static void dfs(Graph graph, int node, int parent, int[] in, int[] low, Integer timer, List articulationPoints) { 33 | graph.visited[node] = true; 34 | in[node] = low[node] = timer++; 35 | 36 | int splits = 0; 37 | for (Graph.ReachableVertex neighbour : graph.adjacencyList.get(node)) { 38 | if (!graph.visited[neighbour.to]) { 39 | dfs(graph, neighbour.to, node, in, low, timer, articulationPoints); 40 | 41 | low[node] = Math.min(low[node], low[neighbour.to]); 42 | 43 | if (low[neighbour.to] >= in[node] && parent != -1) { 44 | articulationPoints.add(node); 45 | } 46 | 47 | splits++; 48 | } else if (neighbour.to != parent) { 49 | low[node] = Math.min(low[node], in[neighbour.to]); 50 | } 51 | } 52 | 53 | if (parent == -1 && splits > 1) { 54 | articulationPoints.add(node); 55 | } 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/08-BellmanFord.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.Arrays; 4 | 5 | public class BellmanFord { 6 | /** 7 | * Find the distance from a starting vertex to all other using the Bellman-Ford algorithm. 8 | * O(VE) complexity. 9 | * 10 | * @param graph Graph to be processed. 11 | * @param start starting vertex. 12 | * @return int array filled with the distance to all vertices. 13 | */ 14 | public static int[] shortestPaths(Graph graph, int start) { 15 | int[] dist = new int[graph.vertices]; 16 | Arrays.fill(dist, Integer.MAX_VALUE); 17 | dist[start] = 0; 18 | 19 | boolean relaxed = true; 20 | 21 | while (relaxed) { 22 | relaxed = false; 23 | 24 | for (Graph.Edge edge : graph.edgesList) { 25 | if (dist[edge.from] == Integer.MAX_VALUE) { 26 | continue; 27 | } 28 | 29 | if (dist[edge.from] + edge.cost < dist[edge.to]) { 30 | dist[edge.to] = dist[edge.from] + edge.cost; 31 | relaxed = true; 32 | } 33 | } 34 | } 35 | 36 | return dist; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/09-Dijkstra.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.Arrays; 4 | import java.util.TreeSet; 5 | 6 | public class Dijkstra { 7 | /** 8 | * Find the distance from a starting vertex to all other using the Dijkstra algorithm. 9 | * O(E log V) complexity. 10 | * 11 | * @param graph Graph to be processed. 12 | * @param start starting vertex. 13 | * @return int array filled with the distance to all vertices. 14 | */ 15 | public static int[] dijkstraSparse(Graph graph, int start) { 16 | int[] dist = new int[graph.vertices]; 17 | Arrays.fill(dist, Integer.MAX_VALUE); 18 | 19 | TreeSet heap = new TreeSet<>(); 20 | heap.add(new Graph.ReachableVertex(start, 0)); 21 | dist[start] = 0; 22 | 23 | while (!heap.isEmpty()) { 24 | int vertex = heap.pollFirst().to; 25 | 26 | graph.adjacencyList.get(vertex).forEach(neighbour -> { 27 | if (dist[vertex] + neighbour.cost < dist[neighbour.to]) { 28 | heap.remove(new Graph.ReachableVertex(neighbour.to, dist[neighbour.to])); 29 | dist[neighbour.to] = dist[vertex] + neighbour.cost; 30 | heap.add(new Graph.ReachableVertex(neighbour.to, dist[neighbour.to])); 31 | } 32 | }); 33 | } 34 | 35 | return dist; 36 | } 37 | 38 | /** 39 | * Find the distance from a starting vertex to all other using the Dijkstra algorithm. 40 | * O(V^2) complexity. 41 | * 42 | * @param graph Graph to be processed. 43 | * @param start starting vertex. 44 | * @return int array filled with the distance to all vertices. 45 | */ 46 | public static int[] dijkstraDense(Graph graph, int start) { 47 | int[] dist = new int[graph.vertices]; 48 | Arrays.fill(dist, Integer.MAX_VALUE); 49 | dist[start] = 0; 50 | 51 | boolean[] marked = new boolean[graph.vertices]; 52 | 53 | for (int iteration = 1; iteration < graph.vertices; iteration++) { 54 | int vertex = -1; 55 | 56 | for (int i = 0; i < graph.vertices; i++) { 57 | if (marked[i]) { 58 | continue; 59 | } 60 | 61 | if (vertex == -1 || dist[vertex] > dist[i]) { 62 | vertex = i; 63 | } 64 | } 65 | 66 | marked[vertex] = true; 67 | 68 | for (Graph.ReachableVertex neighbour : graph.adjacencyList.get(vertex)) { 69 | if (dist[vertex] + neighbour.cost < dist[neighbour.to]) { 70 | dist[neighbour.to] = dist[vertex] + neighbour.cost; 71 | } 72 | } 73 | } 74 | 75 | return dist; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/10-Floyd.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | public class Floyd { 4 | /** 5 | * Find the distance between every pair of vertices from the given graph. 6 | * O(V^3) complexity. 7 | * 8 | * @param graph Graph to be processed. 9 | * @return int matrix containing the distances between each pair of vertices. 10 | */ 11 | public static int[][] floyd(Graph graph) { 12 | int[][] adjacencyMatrix = graph.getAdjacencyMatrix(); 13 | int[][] dist = new int[graph.vertices][graph.vertices]; 14 | 15 | for (int u = 0; u < graph.vertices; u++) { 16 | for (int v = 0; v < graph.vertices; v++) { 17 | if (adjacencyMatrix[u][v] == 0 && u != v) { 18 | dist[u][v] = Integer.MAX_VALUE; 19 | } else { 20 | dist[u][v] = adjacencyMatrix[u][v]; 21 | } 22 | } 23 | } 24 | 25 | for (int k = 0; k < graph.vertices; k++) { 26 | for (int u = 0; u < graph.vertices; u++) { 27 | for (int v = 0; v < graph.vertices; v++) { 28 | if (dist[u][k] != Integer.MAX_VALUE && dist[k][v] != Integer.MAX_VALUE) { 29 | dist[u][v] = Math.min(dist[u][v], dist[u][k] + dist[k][v]); 30 | } 31 | } 32 | } 33 | } 34 | 35 | return dist; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/11-Prim.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.TreeSet; 4 | 5 | public class Prim { 6 | /** 7 | * Find a minimum spanning three of a given graph using Prim's algorithm. 8 | * O(E log V) 9 | * 10 | * @param graph Given graph to find the minimum spanning tree of. 11 | * @return Graph object that is the required minimum spanning tree or null if the given graph is disjoint. 12 | */ 13 | public static Graph minimumSpanningTree(Graph graph) { 14 | Graph minSpanningTree = new Graph(graph.vertices); 15 | 16 | Graph.ReachableVertex[] cost_to = new Graph.ReachableVertex[graph.vertices]; 17 | for (int i = 0; i < cost_to.length; i++) { 18 | cost_to[i] = new Graph.ReachableVertex(); 19 | } 20 | 21 | cost_to[0].cost = 0; 22 | 23 | boolean[] marked = new boolean[graph.vertices]; 24 | 25 | TreeSet heap = new TreeSet<>(); 26 | heap.add(new Graph.ReachableVertex(0, 0)); 27 | 28 | for (int iteration = 0; iteration < graph.vertices; iteration++) { 29 | if (heap.size() == 0) { 30 | return null; 31 | } 32 | 33 | int node = heap.pollFirst().to; 34 | marked[node] = true; 35 | 36 | if (cost_to[node].to != -1) { 37 | minSpanningTree.addEdge(node, cost_to[node].to, cost_to[node].cost); 38 | } 39 | 40 | graph.adjacencyList.get(node).forEach(neighbour -> { 41 | if (!marked[neighbour.to] && neighbour.cost < cost_to[neighbour.to].cost) { 42 | heap.remove(new Graph.ReachableVertex(neighbour.to, cost_to[neighbour.to].cost)); 43 | cost_to[neighbour.to] = new Graph.ReachableVertex(node, neighbour.cost); 44 | heap.add(new Graph.ReachableVertex(neighbour.to, cost_to[neighbour.to].cost)); 45 | } 46 | }); 47 | } 48 | 49 | return minSpanningTree; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/12-Kruskal.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.Iterator; 4 | 5 | public class Kruskal { 6 | /** 7 | * Find a minimum spanning three of a given graph using Kruskal's algorithm. 8 | * O(E log V) 9 | * 10 | * @param graph Given graph to find the minimum spanning tree of. 11 | * @return Graph object that is the required minimum spanning tree or null if the given graph is disjoint. 12 | */ 13 | public static Graph minimumSpanningTree(Graph graph) { 14 | Graph minSpanningTree = new Graph(graph.vertices); 15 | graph.edgesList.sort(Graph.Edge::compareTo); 16 | 17 | DisjointSet disjointSet = new DisjointSet(graph.vertices); 18 | 19 | int components = graph.vertices; 20 | Iterator it = graph.edgesList.iterator(); 21 | 22 | while (components > 1) { 23 | if (!it.hasNext()) { 24 | return null; 25 | } 26 | 27 | Graph.Edge edge = it.next(); 28 | 29 | int root1 = disjointSet.find(edge.from); 30 | int root2 = disjointSet.find(edge.to); 31 | 32 | if (root1 != root2) { 33 | disjointSet.unite(root1, root2); 34 | minSpanningTree.addEdge(edge.from, edge.to, edge.cost); 35 | components--; 36 | } 37 | } 38 | 39 | return minSpanningTree; 40 | } 41 | 42 | private static class DisjointSet { 43 | private static class Set { 44 | int parent; 45 | int depth; 46 | 47 | public Set(int parent) { 48 | this.depth = 0; 49 | this.parent = parent; 50 | } 51 | } 52 | 53 | private final Set[] set; 54 | 55 | public DisjointSet(int size) { 56 | this.set = new Set[size]; 57 | for (int i = 0; i < size; i++) { 58 | this.set[i] = new Set(i); 59 | } 60 | } 61 | 62 | public int find(int a) { 63 | if (a == set[a].parent) { 64 | return a; 65 | } 66 | 67 | int root = find(set[a].parent); 68 | set[a].parent = root; 69 | 70 | return root; 71 | } 72 | 73 | public void unite(int a, int b) { 74 | if (set[a].depth > set[b].depth) { 75 | set[b].parent = a; 76 | } else if (set[b].depth > set[a].depth) { 77 | set[a].parent = b; 78 | } else { 79 | set[b].parent = a; 80 | set[a].depth++; 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/13-EdmondsKarp.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import basic.data.structures.Queue; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | /** 10 | * Find the maximum flow in a graph 11 | * The cost property will be the edge capacity 12 | * O(VE^2) complexity 13 | */ 14 | public class EdmondsKarp { 15 | /** 16 | * Return the maximum flow in the given graph from the source to the sink 17 | */ 18 | public static int maxFlow(Graph graph, int source, int sink) { 19 | int flow = 0; 20 | int[][] capacity = graph.getAdjacencyMatrix(); 21 | int[] parent = new int[graph.vertices]; 22 | 23 | int currentFLow = bfs(graph, source, sink, parent, capacity); 24 | while (currentFLow != 0) { 25 | flow += currentFLow; 26 | 27 | int node = sink; 28 | while (node != source) { 29 | int previous = parent[node]; 30 | capacity[previous][node] -= currentFLow; 31 | capacity[node][previous] += currentFLow; 32 | node = previous; 33 | } 34 | 35 | currentFLow = bfs(graph, source, sink, parent, capacity); 36 | } 37 | 38 | return flow; 39 | } 40 | 41 | private static int bfs(Graph g, int from, int to, int[] parent, int[][] capacity) { 42 | Arrays.fill(parent, -1); 43 | parent[from] = Integer.MIN_VALUE; 44 | 45 | Queue> q = new Queue<>(); 46 | q.push(new Pair<>(from, Integer.MAX_VALUE)); 47 | 48 | while (!q.empty()) { 49 | int node = q.front().first; 50 | int flow = q.front().second; 51 | q.pop(); 52 | 53 | for (Graph.ReachableVertex neighbour : g.adjacencyList.get(node)) { 54 | if (parent[neighbour.to] == -1 && capacity[node][neighbour.to] != 0) { 55 | parent[neighbour.to] = node; 56 | int current_flow = Math.min(flow, capacity[node][neighbour.to]); 57 | 58 | if (neighbour.to == to) { 59 | return current_flow; 60 | } 61 | 62 | q.push(new Pair<>(neighbour.to, current_flow)); 63 | } 64 | } 65 | } 66 | 67 | return 0; 68 | } 69 | 70 | private static class Pair { 71 | public F first; 72 | public S second; 73 | 74 | public Pair(F f, S s) { 75 | first = f; 76 | second = s; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/DirectedGraph.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | public class DirectedGraph extends Graph { 4 | public DirectedGraph(int vertices) { 5 | super(vertices); 6 | } 7 | 8 | @Override 9 | public void addEdge(int from, int to) { 10 | adjacencyList.get(from).add(new ReachableVertex(to)); 11 | edgesList.add(new Edge(from, to)); 12 | edges++; 13 | } 14 | 15 | @Override 16 | public void addEdge(int from, int to, int cost) { 17 | adjacencyList.get(from).add(new ReachableVertex(to, cost)); 18 | edgesList.add(new Edge(from, to, cost)); 19 | edges++; 20 | } 21 | 22 | @Override 23 | public int[][] getAdjacencyMatrix() { 24 | int[][] matrix = new int[vertices][vertices]; 25 | edgesList.forEach(edge -> { 26 | matrix[edge.from][edge.to] = edge.cost; 27 | }); 28 | return matrix; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/Graph.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Objects; 6 | 7 | public class Graph { 8 | public int vertices; 9 | public int edges; 10 | 11 | public boolean[] visited; 12 | 13 | public List edgesList; 14 | public List> adjacencyList; 15 | 16 | public Graph(int vertices) { 17 | this.vertices = vertices; 18 | this.visited = new boolean[vertices]; 19 | 20 | this.edgesList = new ArrayList<>(); 21 | 22 | this.adjacencyList = new ArrayList<>(); 23 | for (int i = 0; i < vertices; i++) { 24 | this.adjacencyList.add(new ArrayList<>()); 25 | } 26 | } 27 | 28 | public void addEdge(int from, int to) { 29 | adjacencyList.get(from).add(new ReachableVertex(to)); 30 | adjacencyList.get(to).add(new ReachableVertex(from)); 31 | 32 | edgesList.add(new Edge(from, to)); 33 | edgesList.add(new Edge(to, from)); 34 | 35 | edges++; 36 | } 37 | 38 | public void addEdge(int from, int to, int cost) { 39 | adjacencyList.get(from).add(new ReachableVertex(to, cost)); 40 | adjacencyList.get(to).add(new ReachableVertex(from, cost)); 41 | 42 | edgesList.add(new Edge(from, to, cost)); 43 | edgesList.add(new Edge(to, from, cost)); 44 | 45 | edges++; 46 | } 47 | 48 | public int[][] getAdjacencyMatrix() { 49 | int[][] matrix = new int[vertices][vertices]; 50 | edgesList.forEach(edge -> { 51 | matrix[edge.from][edge.to] = edge.cost; 52 | matrix[edge.to][edge.from] = edge.cost; 53 | }); 54 | return matrix; 55 | } 56 | 57 | public static class Edge implements Comparable { 58 | public int from; 59 | public int to; 60 | public int cost; 61 | 62 | public Edge(int from, int to) { 63 | this.from = from; 64 | this.to = to; 65 | this.cost = 0; 66 | } 67 | 68 | public Edge(int from, int to, int cost) { 69 | this.from = from; 70 | this.to = to; 71 | this.cost = cost; 72 | } 73 | 74 | @Override 75 | public int compareTo(Edge other) { 76 | if (this.cost == other.cost) { 77 | if (this.from == other.from) { 78 | return Integer.compare(this.to, other.to); 79 | } 80 | return Integer.compare(this.from, other.from); 81 | } 82 | return Integer.compare(this.cost, other.cost); 83 | } 84 | 85 | @Override 86 | public boolean equals(Object o) { 87 | if (this == o) return true; 88 | if (!(o instanceof Edge)) return false; 89 | Edge edge = (Edge) o; 90 | return this.compareTo(edge) == 0; 91 | } 92 | } 93 | 94 | public static class ReachableVertex implements Comparable { 95 | public int to; 96 | public int cost; 97 | 98 | public ReachableVertex() { 99 | this.to = -1; 100 | this.cost = Integer.MAX_VALUE; 101 | } 102 | 103 | public ReachableVertex(int to) { 104 | this.to = to; 105 | this.cost = 0; 106 | } 107 | 108 | public ReachableVertex(int to, int cost) { 109 | this.to = to; 110 | this.cost = cost; 111 | } 112 | 113 | @Override 114 | public int compareTo(ReachableVertex other) { 115 | if (this.cost == other.cost) { 116 | return Integer.compare(this.to, other.to); 117 | } 118 | return Integer.compare(this.cost, other.cost); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Examples/java/13-14-15-Graphs/GraphsTest.java: -------------------------------------------------------------------------------- 1 | package graphs; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import java.util.Objects; 7 | import java.util.function.BiFunction; 8 | import java.util.function.Consumer; 9 | 10 | public class GraphsTest { 11 | @Test 12 | public void topologicalSort() { 13 | Integer[] expectedResult = new Integer[]{5, 4, 2, 3, 1, 0}; 14 | Assert.assertArrayEquals(expectedResult, TopologicalSort.sortedVertices(buildDirectedGraph(6, this::addEdges3)).toArray()); 15 | } 16 | 17 | @Test 18 | public void testBridges() { 19 | Graph.Edge[] expectedResult = new Graph.Edge[]{new Graph.Edge(2, 3)}; 20 | Assert.assertArrayEquals(expectedResult, Bridges.getBridges(buildGraph(6, this::addEdges2)).toArray()); 21 | } 22 | 23 | @Test 24 | public void testArticulationPoints() { 25 | Integer[] expectedResult = new Integer[]{3, 2}; 26 | Assert.assertArrayEquals(expectedResult, ArticulationPoints.getArticulationPoints(buildGraph(6, this::addEdges2)).toArray()); 27 | } 28 | 29 | @Test 30 | public void testNumberOfPathsOfFixedLength() { 31 | NumberOfPathsOfFixedLength.PathsIndex index = NumberOfPathsOfFixedLength.createIndex(buildGraph(9, this::addEdges1), 4); 32 | Assert.assertEquals(16, index.paths(2, 4)); 33 | } 34 | 35 | @Test 36 | public void testDijkstra() { 37 | testShortestPaths(Dijkstra::dijkstraSparse); 38 | testShortestPaths(Dijkstra::dijkstraDense); 39 | } 40 | 41 | @Test 42 | public void testBellmanFord() { 43 | testShortestPaths(BellmanFord::shortestPaths); 44 | } 45 | 46 | @Test 47 | public void testFloyd() { 48 | int [][] expectedResult = { 49 | {0, 4, 12, 19, 21, 11, 9, 8, 14}, 50 | {4, 0, 8, 15, 22, 12, 12, 11, 10}, 51 | {12, 8, 0, 7, 14, 4, 6, 7, 2}, 52 | {19, 15, 7, 0, 9, 11, 13, 14, 9}, 53 | {21, 22, 14, 9, 0, 10, 12, 13, 16}, 54 | {11, 12, 4, 11, 10, 0, 2, 3, 6}, 55 | {9, 12, 6, 13, 12, 2, 0, 1, 6}, 56 | {8, 11, 7, 14, 13, 3, 1, 0, 7}, 57 | {14, 10, 2, 9, 16, 6, 6, 7, 0} 58 | }; 59 | Assert.assertArrayEquals(expectedResult, Floyd.floyd(buildGraph(9, this::addEdges1))); 60 | } 61 | 62 | @Test 63 | public void testPrim() { 64 | testMinimumSpanningTree(Prim.minimumSpanningTree(buildGraph(9, this::addEdges1))); 65 | } 66 | 67 | @Test 68 | public void testKruskal() { 69 | testMinimumSpanningTree(Kruskal.minimumSpanningTree(buildGraph(9, this::addEdges1))); 70 | } 71 | 72 | @Test 73 | public void testCycles() { 74 | Assert.assertTrue(Cycles.findCycle(buildGraph(9, this::addEdges1))); 75 | Assert.assertFalse(Cycles.findCycle(buildDirectedGraph(9, this::addEdges1))); 76 | } 77 | 78 | @Test 79 | public void testEdmondsKarp() { 80 | Assert.assertEquals(12, EdmondsKarp.maxFlow(buildGraph(9, this::addEdges1), 0, 7)); 81 | } 82 | 83 | public void testShortestPaths(BiFunction function) { 84 | int[] expectedResult = {0, 4, 12, 19, 21, 11, 9, 8, 14}; 85 | Assert.assertArrayEquals(expectedResult, function.apply(buildGraph(9, this::addEdges1), 0)); 86 | } 87 | 88 | public void testMinimumSpanningTree(Graph tree) { 89 | Assert.assertEquals(9, Objects.requireNonNull(tree).vertices); 90 | 91 | DFS.dfs(tree, 0); 92 | for (int vertex = 0; vertex < tree.vertices; vertex++) { 93 | Assert.assertTrue(tree.visited[vertex]); 94 | } 95 | 96 | int sum = 0; 97 | for (int i = 0; i < tree.edgesList.size(); i += 2) { 98 | sum += tree.edgesList.get(i).cost; 99 | } 100 | Assert.assertEquals(37, sum); 101 | } 102 | 103 | public Graph buildGraph(int vertices, Consumer f) { 104 | Graph graph = new Graph(vertices); 105 | f.accept(graph); 106 | return graph; 107 | } 108 | 109 | public DirectedGraph buildDirectedGraph(int vertices, Consumer f) { 110 | DirectedGraph graph = new DirectedGraph(vertices); 111 | f.accept(graph); 112 | return graph; 113 | } 114 | 115 | public void addEdges1(Graph graph) { 116 | graph.addEdge(0, 1, 4); 117 | graph.addEdge(0, 7, 8); 118 | graph.addEdge(1, 2, 8); 119 | graph.addEdge(1, 7, 11); 120 | graph.addEdge(2, 3, 7); 121 | graph.addEdge(2, 5, 4); 122 | graph.addEdge(2, 8, 2); 123 | graph.addEdge(3, 4, 9); 124 | graph.addEdge(3, 5, 14); 125 | graph.addEdge(4, 5, 10); 126 | graph.addEdge(5, 6, 2); 127 | graph.addEdge(6, 7, 1); 128 | graph.addEdge(6, 8, 6); 129 | graph.addEdge(7, 8, 7); 130 | } 131 | 132 | public void addEdges2(Graph graph) { 133 | graph.addEdge(0, 1); 134 | graph.addEdge(0, 2); 135 | graph.addEdge(1, 2); 136 | graph.addEdge(2, 3); 137 | graph.addEdge(3, 4); 138 | graph.addEdge(4, 5); 139 | graph.addEdge(5, 3); 140 | } 141 | 142 | public void addEdges3(DirectedGraph graph) { 143 | graph.addEdge(5, 2); 144 | graph.addEdge(5, 0); 145 | graph.addEdge(4, 0); 146 | graph.addEdge(4, 1); 147 | graph.addEdge(2, 3); 148 | graph.addEdge(3, 1); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Exercises/01-ComplexityOfAlgorithms.md: -------------------------------------------------------------------------------- 1 | # Сложност на алгоритми 2 | 3 | ## Cheat sheet 4 | ![](https://i.stack.imgur.com/5eFMU.png) 5 | 6 | ## 1 7 | 8 | ```c++ 9 | bool isEven(int number) { 10 | return number % 2 ? false : true; 11 | } 12 | ``` 13 | 14 | ## 2 15 | 16 | ```c++ 17 | int getElement(int arr[], int index) { 18 | return arr[index]; 19 | } 20 | ``` 21 | 22 | ## 3 23 | 24 | ```c++ 25 | int maxElement(vector numbers) { 26 | int max = numbers[0]; 27 | for(auto i = numbers.begin(); i != numbers.end(); i++) { 28 | if(*i > max){ 29 | max = *i; 30 | } 31 | } 32 | return max; 33 | } 34 | ``` 35 | 36 | ## 4 37 | 38 | ```c++ 39 | int findDuplicateNotSmartOne(vector v) { 40 | for(int i = 0; i < v.size(); i++) { 41 | for(int j = 0; j < v.size(); j++) { 42 | if(v[i] == v[j] && i != j) { 43 | return v[i]; 44 | } 45 | } 46 | } 47 | return -1; 48 | } 49 | ``` 50 | 51 | ## 5 52 | 53 | ```c++ 54 | vector findXYZ(int numberToSumTo, int maxCycles) { 55 | vector result; 56 | for(int x = 0; x < maxCycles; x++) { 57 | for(int y = 0; y < maxCycles; y++) { 58 | for(int z = 0; z < maxCycles; z++) { 59 | if(x + y + z == numberToSumTo) { 60 | result.push_back(x); 61 | result.push_back(y); 62 | result.push_back(z); 63 | } 64 | } 65 | } 66 | } 67 | return result; 68 | } 69 | ``` 70 | 71 | ## 6 72 | 73 | ```c++ 74 | void logit(int n) { 75 | for(int i = n; i > 0; i = i/2) { 76 | cout< 0; i--) { 86 | for(int j = n; j > 0; j = j/2) { 87 | cout << i << " " << j; 88 | } 89 | } 90 | } 91 | ``` 92 | 93 | ## 8 94 | 95 | ```c++ 96 | void powerSet(string str, int index = -1, string curr = "") { 97 | int n = str.length(); 98 | if (index == n) 99 | return; 100 | 101 | cout << curr << "\n"; 102 | for (int i = index + 1; i < n; i++) { 103 | curr += str[i]; 104 | powerSet(str, i, curr); 105 | curr.erase(curr.size() - 1); 106 | } 107 | return; 108 | } 109 | ``` 110 | 111 | ## 9 112 | 113 | ```c++ 114 | void permute(string a, int l, int r) { 115 | if (l == r) 116 | { 117 | cout< 0) { 191 | k = k >> 1; 192 | } 193 | } 194 | ``` 195 | 196 | 197 | ## Answers 198 | 199 | 1. O(1) 200 | 2. O(1) 201 | 3. O(numbers.size()) 202 | 4. O(v.size() ^ 2) 203 | 5. O(maxCycles ^ 3) 204 | 6. O(log(n)) 205 | 7. O(n * log(n)) 206 | 8. O(2 ^ str.size()) 207 | 9. O(a.size()!) 208 | 10. O(n*log(n)) 209 | 11. O(n) 210 | 12. O(2^n) 211 | 13. O(n^2) 212 | 14. O(1) 213 | -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework1/cloning-socks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void solve() { 5 | int x, y; 6 | cin >> x >> y; 7 | 8 | y--; 9 | 10 | if(x < y or (y == 0 and x > 0) or y < 0) { 11 | cout << "no\n"; 12 | return; 13 | } 14 | 15 | if((x - y) % 2 != 0) { 16 | cout << "no\n"; 17 | return; 18 | } 19 | 20 | cout << "yes\n"; 21 | } 22 | 23 | int main() { 24 | ios::sync_with_stdio(false); 25 | cin.tie(nullptr); 26 | cout.tie(nullptr); 27 | 28 | int t; 29 | cin >> t; 30 | for (int i = 0; i < t; i++) { 31 | solve(); 32 | } 33 | 34 | return 0; 35 | } -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework1/darts.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | vector < pair > v; 5 | vector doubles; 6 | 7 | int main() { 8 | int n; 9 | cin >> n; 10 | v.push_back(make_pair(0, 1)); 11 | for (int i = 1; i <= 20; i++) { 12 | v.push_back(make_pair(i, 1)); 13 | v.push_back(make_pair(i, 2)); 14 | v.push_back(make_pair(i, 3)); 15 | 16 | doubles.push_back(i); 17 | } 18 | 19 | v.push_back(make_pair(25, 1)); 20 | v.push_back(make_pair(25, 2)); 21 | 22 | doubles.push_back(25); 23 | 24 | int ans = 0; 25 | 26 | for (int i = 0; i < doubles.size(); i++) { 27 | if (doubles[i] * 2 == n) { 28 | ans++; 29 | } 30 | } 31 | 32 | for (int i = 0; i < v.size(); i++) { 33 | for (int j = 0; j < doubles.size(); j++) { 34 | if (v[i].first * v[i].second + doubles[j] * 2 == n) { 35 | ans++; 36 | } 37 | } 38 | } 39 | 40 | for (int i = 0; i < v.size(); i++) { 41 | for (int j = 0; j < v.size(); j++) { 42 | for (int l = 0; l < doubles.size(); l++) { 43 | if (v[i].first * v[i].second + v[j].first * v[j].second + doubles[l] * 2 == n) { 44 | ans++; 45 | } 46 | } 47 | } 48 | } 49 | 50 | cout << ans << endl; 51 | return 0; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework1/mission-sda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int M, N; 6 | cin >> M >> N; 7 | 8 | int input = 0; 9 | long long sum = 0; 10 | 11 | for (int i = 0; i < N; i++) { 12 | cin >> input; 13 | sum += input; 14 | } 15 | 16 | int NtimesM = N * M; 17 | if (sum >= NtimesM) { 18 | cout << "yes\n"; 19 | } else { 20 | cout << "no\n"; 21 | } 22 | } -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework2/electrical-energy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | static const int SIZE = 100000 + 7; 5 | 6 | int n; 7 | int arr[SIZE]; 8 | 9 | long long merge(int* a, int from, int mid, int to) { 10 | int* l = new int[mid - from + 1]; 11 | int* r = new int[to - mid]; 12 | 13 | int index = 0; 14 | for (int i = from; i <= mid; i++) { 15 | l[index++] = a[i]; 16 | } 17 | 18 | index = 0; 19 | for (int i = mid + 1; i <= to; i++) { 20 | r[index++] = a[i]; 21 | } 22 | 23 | 24 | int i = 0; 25 | int j = 0; 26 | long long res = 0; 27 | 28 | index = 0; 29 | while (i < mid - from + 1 && j < to - mid) { 30 | if (l[i] <= r[j]) { 31 | a[from + index++] = l[i++]; 32 | } else { 33 | res += mid - from + 1 - i; 34 | a[from + index++] = r[j++]; 35 | } 36 | } 37 | 38 | while (i < mid - from + 1) { 39 | a[from + index++] = l[i++]; 40 | } 41 | 42 | while (j < to - mid) { 43 | a[from + index++] = r[j++]; 44 | } 45 | 46 | delete[] l; 47 | delete[] r; 48 | return res; 49 | } 50 | 51 | long long countInversions(int* arr, int from, int to) { 52 | if (from == to) { 53 | return 0LL; 54 | } 55 | 56 | int mid = (from + to) / 2; 57 | 58 | long long leftRes = countInversions(arr, from, mid); 59 | long long rightRes = countInversions(arr, mid + 1, to); 60 | return leftRes + rightRes + merge(arr, from, mid, to); 61 | } 62 | 63 | void input() { 64 | cin >> n; 65 | for (int i = 0; i < n; i++) { 66 | cin >> arr[i]; 67 | } 68 | } 69 | 70 | int main() { 71 | ios::sync_with_stdio(false); 72 | cin.tie(nullptr); 73 | cout.tie(nullptr); 74 | 75 | input(); 76 | cout << countInversions(arr, 0, n - 1) << "\n"; 77 | 78 | return 0; 79 | } -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework2/permutations.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | const int ALPHABET_SIZE = 'z' + 1; 6 | 7 | bool check(char * a, char * b, int length) { 8 | int alphabet[ALPHABET_SIZE] { 0 }; 9 | for (int i = 0; i < length; i++) { 10 | alphabet[a[i]]++; 11 | } 12 | for (int i = 0; i < length; i++) { 13 | alphabet[b[i]]--; 14 | } 15 | 16 | for (int i = 0; i < ALPHABET_SIZE; i++) { 17 | if (alphabet[i] != 0) { 18 | return false; 19 | } 20 | } 21 | return true; 22 | } 23 | 24 | int main() { 25 | std::ios_base::sync_with_stdio(false); 26 | std::cin.tie(NULL); 27 | 28 | int length = 0; 29 | cin >> length; 30 | char * a = new char[length + 1]; 31 | char * b = new char[length + 1]; 32 | 33 | cin >> a; 34 | cin >> b; 35 | 36 | if (check(a , b, length)) { 37 | cout << "yes\n"; 38 | } else { 39 | cout << "no\n"; 40 | } 41 | 42 | delete[] a; 43 | delete[] b; 44 | } -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework2/schedule.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAX_N = 1000024; 5 | 6 | struct Time { 7 | int start; 8 | int duration; 9 | 10 | bool operator<(const Time& other) const { 11 | return start + duration < other.start + other.duration; 12 | } 13 | }; 14 | 15 | Time t[MAX_N]; 16 | 17 | int main() { 18 | ios_base::sync_with_stdio(false); 19 | cin.tie(NULL); 20 | 21 | int n = 0; 22 | cin >> n; 23 | 24 | for (int i = 0; i < n; i++) { 25 | cin >> t[i].start >> t[i].duration; 26 | } 27 | 28 | sort(t, t + n); 29 | 30 | int last = 0, ans = 0; 31 | for (int i = 0; i < n; i++) { 32 | if (t[i].start >= last) { 33 | ans++; 34 | last = t[i].start + t[i].duration; 35 | } 36 | } 37 | 38 | cout << ans << endl; 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework3/balloons-and-candy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int SIZE = 100000 + 7; 5 | 6 | long long n, m; 7 | pair arr[SIZE]; 8 | 9 | void input() { 10 | cin >> n >> m; 11 | 12 | for (int i = 0; i < n; i++) { 13 | cin >> arr[i].first; 14 | } 15 | 16 | for (int i = 0; i < n; i++) { 17 | cin >> arr[i].second; 18 | } 19 | } 20 | 21 | bool check(long long num) { 22 | long long baloons = m; 23 | for (int i = 0; i < n; i++) { 24 | if (arr[i].second == 0) { 25 | continue; 26 | } 27 | 28 | long long temp = num / arr[i].second; 29 | 30 | if (temp >= arr[i].first) { 31 | continue; 32 | } 33 | 34 | baloons -= (arr[i].first - temp); 35 | 36 | if (baloons < 0) { 37 | return false; 38 | } 39 | } 40 | return true; 41 | } 42 | 43 | void solve() { 44 | long long left = 0; 45 | long long right = 1000000000000000000; 46 | 47 | long long ans; 48 | while (left <= right) { 49 | long long mid = (left + right) / 2; 50 | 51 | if (check(mid)) { 52 | ans = mid; 53 | right = mid - 1; 54 | } else { 55 | left = mid + 1; 56 | } 57 | } 58 | 59 | cout << ans << endl; 60 | } 61 | 62 | int main() { 63 | ios::sync_with_stdio(false); 64 | cin.tie(nullptr); 65 | 66 | input(); 67 | solve(); 68 | 69 | return 0; 70 | } -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework3/cows.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAX_N = 100024; 5 | 6 | int n, k; 7 | int a[MAX_N]; 8 | 9 | bool check(int m) { 10 | int cows = 1; 11 | int last = a[0]; 12 | for (int i = 1; i < n; i++) { 13 | if (a[i] - last >= m) { 14 | cows++; 15 | last = a[i]; 16 | } 17 | } 18 | 19 | return cows >= k; 20 | } 21 | 22 | int main() { 23 | scanf("%d %d", &n, &k); 24 | 25 | for (int i = 0; i < n; i++) { 26 | scanf("%d", a + i); 27 | } 28 | sort(a, a + n); 29 | 30 | int l = 0, r = 2000000000; 31 | int ans = 0; 32 | while (l <= r) { 33 | int mid = l + (r - l) / 2; 34 | 35 | if (check(mid)) { 36 | ans = mid; 37 | l = mid + 1; 38 | } else { 39 | r = mid - 1; 40 | } 41 | } 42 | 43 | printf("%d\n", ans); 44 | return 0; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework3/monster-trucks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | struct Truck { 11 | long long distance = 0; 12 | long long price = 0; 13 | }; 14 | 15 | long long Price(Truck* trucks, long long arrSize, long long distance) { 16 | long long price = 0; 17 | for (long long i = 0; i < arrSize; i++) { 18 | price += abs(trucks[i].distance - distance) * trucks[i].price; 19 | } 20 | return price; 21 | } 22 | 23 | long long Min(long long a, long long b) { 24 | return a < b ? a : b; 25 | } 26 | 27 | long long MinPriceTernaryNaive(Truck* trucks, long long size, long long left, long long right) { 28 | if (right - left < 3) { // brute force small intervals 29 | long long currentMin = Price(trucks, size, left); 30 | for (long long i = left + 1; i < right + 1; i++) { 31 | currentMin = Min(currentMin, Price(trucks, size, i)); 32 | } 33 | return currentMin; 34 | } 35 | else if (left < right) { 36 | long long leftThird = left + (right - left) / 3; 37 | long long rightThird = right - (right - left) / 3; 38 | 39 | long long leftPrice = Price(trucks, size, leftThird); 40 | long long rightPrice = Price(trucks, size, rightThird); 41 | 42 | if (leftPrice < rightPrice) { 43 | return MinPriceTernaryNaive(trucks, size, left, rightThird); 44 | } 45 | else if (leftPrice > rightPrice) { 46 | return MinPriceTernaryNaive(trucks, size, leftThird, right); 47 | } 48 | else { 49 | return leftPrice; 50 | } 51 | } 52 | return -1; // in case some error occurs 53 | } 54 | 55 | bool Compare(Truck& lhs, Truck& rhs) { 56 | return (lhs.distance < rhs.distance); 57 | } 58 | 59 | int main() { 60 | long long N; 61 | cin >> N; 62 | Truck* trucks = new Truck[N]; 63 | for (long long i = 0; i < N; i++) { 64 | cin >> trucks[i].distance; 65 | cin >> trucks[i].price; 66 | } 67 | 68 | sort(trucks, trucks + N, Compare); 69 | 70 | if (N > 1) { 71 | cout << MinPriceTernaryNaive(trucks, N, trucks[0].distance, trucks[N-1].distance); 72 | } 73 | else { 74 | cout << 0; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework3/strawberries.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAX_N = 100024; 5 | 6 | long long a[MAX_N]; 7 | long long p[MAX_N]; 8 | 9 | int main() { 10 | long long n; 11 | scanf("%lld", &n); 12 | 13 | scanf("%lld", &a[0]); 14 | p[0] = a[0]; 15 | for (int i = 1; i < n; i++) { 16 | scanf("%lld", &a[i]); 17 | p[i] = p[i - 1] + a[i]; 18 | } 19 | 20 | long long m; 21 | scanf("%lld", &m); 22 | 23 | for (int i = 0; i < m; i++) { 24 | long long q; 25 | scanf("%lld", &q); 26 | 27 | long long l = 0, r = n - 1; 28 | long long ans = n; 29 | while (l <= r) { 30 | int m = (l + r) / 2; 31 | if (p[m] >= q) { 32 | ans = m; 33 | r = m - 1; 34 | } else { 35 | l = m + 1; 36 | } 37 | } 38 | 39 | ans++; 40 | printf("%lld\n", ans); 41 | } 42 | 43 | return 0; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework4/truck-ordering.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void solve() { 5 | int n; 6 | cin >> n; 7 | 8 | stack street; 9 | int nextNum = 1; 10 | 11 | for (int i = 0; i < n; i++) { 12 | int num; 13 | cin >> num; 14 | 15 | while (street.empty() == false && street.top() == nextNum) { 16 | nextNum++; 17 | street.pop(); 18 | } 19 | 20 | if (nextNum == num) { 21 | nextNum++; 22 | } else { 23 | street.push(num); 24 | } 25 | } 26 | 27 | while (street.empty() == false && street.top() == nextNum) { 28 | nextNum++; 29 | street.pop(); 30 | } 31 | 32 | if (street.empty()) { 33 | cout << "yes\n"; 34 | return; 35 | } 36 | cout << "no\n"; 37 | } 38 | 39 | int main() { 40 | ios_base::sync_with_stdio(false); 41 | cin.tie(nullptr); 42 | cout.tie(nullptr); 43 | 44 | int t; 45 | cin >> t; 46 | 47 | for (int i = 0; i < t; i++) { 48 | solve(); 49 | } 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework5/los-binares.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct Node { 5 | int data; 6 | int level = 0; 7 | Node* left = nullptr; 8 | Node* right = nullptr; 9 | 10 | Node() = default; 11 | 12 | Node(int value, int level) { 13 | data = value; 14 | this->level = level; 15 | } 16 | }; 17 | 18 | class BST { 19 | private: 20 | Node* root = nullptr; 21 | 22 | int _level(int value, Node* current) const { 23 | if (current) { 24 | if (current->data == value) { 25 | return current->level; 26 | } else if (current->data < value) { 27 | return _level(value, current->right); 28 | } else { 29 | return _level(value, current->left); 30 | } 31 | } else { 32 | return -1; 33 | } 34 | } 35 | 36 | Node* _insert(int value, Node* current, int currentLevel) { 37 | if (!current) { 38 | return new Node(value, currentLevel); 39 | } 40 | 41 | if (value < current->data) { 42 | current->left = _insert(value, current->left, currentLevel + 1); 43 | } else if (value > current->data) { 44 | current->right = _insert(value, current->right, currentLevel + 1); 45 | } 46 | 47 | return current; 48 | } 49 | 50 | public: 51 | int level(int value) const { 52 | return _level(value, root); 53 | } 54 | 55 | void insert(int value) { 56 | root = _insert(value, root, 0); 57 | } 58 | 59 | }; 60 | 61 | int main() { 62 | BST s; 63 | 64 | int N, K; 65 | cin >> N >> K; 66 | for (int i = 0; i < N; i++) { 67 | int in; 68 | cin >> in; 69 | s.insert(in); 70 | } 71 | 72 | for (int i = 0; i < K; i++) { 73 | int in; 74 | cin >> in; 75 | cout << s.level(in) << "\n"; 76 | } 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework5/student-queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int MAX_N = 100024; 5 | 6 | queue < pair > groups[MAX_N]; 7 | queue groupQueue; 8 | 9 | int main() { 10 | int n, m; 11 | cin >> n >> m; 12 | 13 | int i; 14 | for (i = 0; i < n; i++) { 15 | string name; 16 | int group; 17 | cin >> name >> group; 18 | 19 | if (groups[group].empty()) { 20 | groupQueue.push(group); 21 | } 22 | groups[group].push({name, i}); 23 | 24 | if (i > 0 && i % 2 == 0) { 25 | cout << groups[groupQueue.front()].front().first << " "; 26 | cout << groups[groupQueue.front()].front().second << " " << i << endl; 27 | groups[groupQueue.front()].pop(); 28 | if (groups[groupQueue.front()].empty()) { 29 | groupQueue.pop(); 30 | } 31 | } 32 | } 33 | 34 | if (i % 2 == 1) { 35 | i++; 36 | } 37 | 38 | while (!groupQueue.empty()) { 39 | while (!groups[groupQueue.front()].empty()) { 40 | cout << groups[groupQueue.front()].front().first << " "; 41 | cout << groups[groupQueue.front()].front().second << " " << i << endl; 42 | groups[groupQueue.front()].pop(); 43 | i += 2; 44 | } 45 | groupQueue.pop(); 46 | } 47 | 48 | return 0; 49 | } 50 | 51 | /** 52 | 8 53 | Ivan 10 54 | Nikolay 10 55 | Vasil 3 56 | Daniel 4 57 | Yoanna 3 58 | Maria 3 59 | Pesho 666 60 | Gosho 10 61 | 62 | */ 63 | -------------------------------------------------------------------------------- /Homeworks 2019-2020/Homework7/file-systems.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | struct Node { 9 | string name; 10 | vector sub; 11 | Node* parent = nullptr; 12 | 13 | Node(const string& name, Node* parent = nullptr) : name(name), parent(parent) { } 14 | 15 | bool hasSub(string dir) { 16 | for (Node* i : sub) { 17 | if (i->name == dir) { 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | 24 | void mkdir(const string& dir) { 25 | if (hasSub(dir)) { 26 | cout << "Directory already exists\n"; 27 | } else { 28 | sub.push_back(new Node(dir, this)); 29 | } 30 | } 31 | 32 | void ls() { 33 | sort(sub.begin(), sub.end(), [](const auto& lhs, const auto& rhs) { 34 | return lhs->name < rhs->name; }); 35 | 36 | for (auto i : sub) { 37 | cout << i->name << " "; 38 | } 39 | 40 | cout << "\n"; 41 | } 42 | 43 | Node* cd(const string& dir) { 44 | if (dir == "..") { 45 | if (parent) { 46 | return parent; 47 | } 48 | } else { 49 | for (Node* i : sub) { 50 | if (i->name == dir) { 51 | return i; 52 | } 53 | } 54 | } 55 | 56 | cout << "No such directory\n"; 57 | return this; 58 | } 59 | 60 | void pwd() const { 61 | stack dirs; 62 | const Node* current = this; 63 | while (current != nullptr) { 64 | dirs.push(current->name); 65 | current = current->parent; 66 | } 67 | 68 | while (!dirs.empty()) { 69 | cout << dirs.top() << "/"; 70 | dirs.pop(); 71 | } 72 | cout << "\n"; 73 | } 74 | }; 75 | 76 | int main() { 77 | int N; 78 | string in; 79 | 80 | Node* current = new Node(""); 81 | 82 | cin >> N; 83 | for (int i = 0; i < N; i++) { 84 | cin >> in; 85 | if (in == "mkdir") { 86 | cin >> in; 87 | current->mkdir(in); 88 | } else if (in == "ls") { 89 | current->ls(); 90 | } else if (in == "cd") { 91 | cin >> in; 92 | current = current->cd(in); 93 | } else if (in == "pwd") { 94 | current->pwd(); 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /Homeworks 2020-2021/Homework 1/Another_arrays_interview_problem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const long long MOD = 1000000007; 4 | 5 | long long a[1000000], pref[1000000], suffProduct = 1, ans[1000000]; 6 | 7 | int main() 8 | { 9 | for(int j=0;j<10;++j) 10 | { 11 | 12 | char fileName[20] = "input0X.txt"; 13 | fileName[6] = '0' + j; 14 | freopen(fileName, "r", stdin); 15 | char fileName2[20] = "output0X.txt"; 16 | fileName2[7] = '0' + j; 17 | freopen(fileName2, "w", stdout); 18 | int n; 19 | cin>>n; 20 | cin>>a[0]; 21 | pref[0] = 1; 22 | for(int i=1;i>a[i]; 25 | pref[i] = (pref[i-1] * a[i-1])%MOD; 26 | } 27 | suffProduct = 1; 28 | for(int i=n-1;i>=0;--i) 29 | { 30 | ans[i] = (suffProduct * pref[i])%MOD; 31 | suffProduct = (suffProduct * a[i])%MOD; 32 | } 33 | for(int i=0;i 2 | using namespace std; 3 | 4 | int arr[1000000]; 5 | 6 | int getAnswer(int arrLen, int* arr) 7 | { 8 | for(int i=0; i 0 && arr[i] <= arrLen && arr[i] != i+1) 11 | { 12 | swap(arr[i], arr[arr[i]-1]); 13 | /// here the decrementation if i is needed because the value we swap arr[i] with may also need to change position. An example of this is the array [3, 4, -1, 1] 14 | --i; 15 | } 16 | } 17 | int ans = arrLen+1; 18 | for(int i=0; i 2 | using namespace std; 3 | 4 | long long a, b, ans = 0; 5 | bool used[10]; 6 | 7 | void gen(long long x) 8 | { 9 | if(x > b) 10 | return; 11 | if(x >= a) 12 | ans ++; 13 | for(int i=0;i<10;++i) 14 | { 15 | if(!used[i]) 16 | { 17 | used[i] = 1; 18 | gen(x*10+i); 19 | used[i] = 0; 20 | } 21 | } 22 | } 23 | 24 | int main() 25 | { 26 | cin>>a>>b; 27 | for(int i=1;i<10;++i) 28 | { 29 | used[i] = 1; 30 | gen(i); 31 | used[i] = 0; 32 | } 33 | cout< nums[i - 1]: 7 | total += nums[i] - nums[i - 1] 8 | print(total) 9 | -------------------------------------------------------------------------------- /Homeworks 2020-2021/Homework 1/unique_using_combinatorics.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def uniques_between(a, b): 5 | if b - a < 1000: 6 | return uniques_between_naive(a, b) # the logic breaks for b - a < 10 so let's brute force it 7 | a_len = len(str(a)) 8 | b_len = len(str(b)) 9 | uniques = uniques_with_n_digits_bigger_than_w(a) - uniques_with_n_digits_bigger_than_w(b) 10 | while a_len < b_len: 11 | a_len += 1 12 | uniques += uniques_with_n_digits(a_len) 13 | 14 | return uniques 15 | 16 | 17 | def uniques_between_naive(a, b): 18 | total = 0 19 | for i in range(a, b + 1): 20 | if len(set(str(i))) == len(str(i)): 21 | total += 1 22 | return total 23 | 24 | 25 | def uniques_with_n_digits_bigger_than_w(w): 26 | n = len(str(w)) 27 | w = next_unique(w) 28 | last_non_zero = len(w) - 1 29 | while last_non_zero >= 0 and w[last_non_zero] == 0: 30 | last_non_zero -= 1 31 | 32 | uniques = 0 33 | while len(w) == n: 34 | used_digits = set(w[0: last_non_zero]) 35 | available_digits = set( 36 | range(w[last_non_zero], 10)).difference(used_digits) 37 | local_uniques = len(available_digits) 38 | for i in range(last_non_zero + 1, len(w)): 39 | local_uniques *= 10 - i 40 | uniques += local_uniques 41 | w[last_non_zero] = 0 42 | last_non_zero -= 1 43 | w = plus_one(w, last_non_zero) 44 | 45 | return uniques 46 | 47 | 48 | def uniques_with_n_digits(n): 49 | uniques = 9 50 | while n > 1: 51 | uniques *= 10 - n + 1 52 | n -= 1 53 | return uniques 54 | 55 | 56 | def next_unique(num): 57 | if isinstance(num, int): 58 | num = list(map(lambda x: int(x), list(str(num)))) 59 | 60 | digits = set() 61 | fail_index = None 62 | second_zero = None 63 | for index, digit in enumerate(num): 64 | if digit not in digits and second_zero is None: 65 | digits.add(digit) 66 | elif digit == 0 and second_zero is None: 67 | second_zero = index 68 | elif digit == 0: 69 | pass 70 | elif digit != 0 and second_zero is not None: 71 | fail_index = second_zero 72 | break 73 | else: 74 | fail_index = index 75 | break 76 | 77 | if fail_index is not None: 78 | for i in range(fail_index + 1, len(num)): 79 | num[i] = 0 80 | num = plus_one(num, fail_index) 81 | return next_unique(num) 82 | return num 83 | 84 | 85 | def plus_one(arr_num, index): 86 | carry = 1 87 | for i in range(index, -1, -1): 88 | arr_num[i] += carry 89 | if arr_num[i] >= 10: 90 | arr_num[i] -= 10 91 | carry = 1 92 | else: 93 | carry = 0 94 | if carry == 1: 95 | arr_num = [1] + arr_num 96 | return arr_num 97 | 98 | 99 | start, end = list(map(lambda x: int(x), sys.stdin.readline().split(' '))) 100 | 101 | print(uniques_between(start, end)) 102 | -------------------------------------------------------------------------------- /Homeworks 2020-2021/Homework 2/memories.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int n; 7 | pair a[10000000]; 8 | 9 | bool cmp(pair a, pair b) 10 | { 11 | if(a.first == b.first) 12 | return a.second > b.second; 13 | return a.first < b.first; 14 | } 15 | 16 | int main() 17 | { 18 | cin>>n; 19 | cerr< rightMost) 30 | rightMost = a[i].second; 31 | else 32 | ans++; 33 | } 34 | cout<= intervals[i][0]: 11 | new[-1][1] = max(new[-1][1], intervals[i][1]) 12 | else: 13 | new.append(intervals[i]) 14 | 15 | return new 16 | 17 | intervals = [] 18 | lines = sys.stdin.readlines() 19 | for i in range(1, len(lines)): 20 | intervals.append(list(map(lambda x: int(x), lines[i].split()))) 21 | 22 | for i in merge(intervals): 23 | print(i[0], i[1]) 24 | -------------------------------------------------------------------------------- /Homeworks 2020-2021/Homework 2/walkingMedian.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | int a[1000000]; 4 | int main() 5 | { 6 | ios::sync_with_stdio(false); 7 | int n; 8 | cin>>n; 9 | cin>>a[0]; 10 | cout<>a[i]; 14 | int x = a[i], j = i; 15 | while(x < a[j-1] && j != 0) 16 | { 17 | a[j] = a[j-1]; 18 | --j; 19 | } 20 | a[j] = x; 21 | for(int j=0;j<=i;++j) 22 | { 23 | cout< 2 | using namespace std; 3 | 4 | int bs1(vector&v, int num) { 5 | int l = 0; 6 | int r = v.size() - 1; 7 | 8 | while (l <= r) { 9 | int mid = (l + r) >> 1; 10 | if (v[mid] <= num) { 11 | l = mid + 1; 12 | } else { 13 | r = mid - 1; 14 | } 15 | } 16 | return l - 1; 17 | } 18 | 19 | int bs2(vector&v, int num) { 20 | int l = 0; 21 | int r = v.size() - 1; 22 | 23 | while (l <= r) { 24 | int mid = (l + r) >> 1; 25 | if (v[mid] >= num) { 26 | r = mid - 1; 27 | } else { 28 | l = mid + 1; 29 | } 30 | } 31 | return r + 1; 32 | } 33 | 34 | void solve() { 35 | int n, q; 36 | cin >> n >> q; 37 | 38 | vector v; 39 | for (int i = 0; i < n; i++) { 40 | int num; 41 | cin >> num; 42 | v.push_back(num); 43 | } 44 | 45 | sort(v.begin(), v.end()); 46 | 47 | for (int i = 0; i < q; i++) { 48 | int a, b; 49 | cin >> a >> b; 50 | 51 | if (a > b) { 52 | cout << 0 << endl; 53 | } else { 54 | cout << bs1(v, b) - bs2(v, a) + 1 << endl; 55 | } 56 | } 57 | } 58 | 59 | int main() { 60 | ios_base::sync_with_stdio(false); 61 | cin.tie(nullptr); 62 | 63 | solve(); 64 | 65 | return 0; 66 | } -------------------------------------------------------------------------------- /Homeworks 2020-2021/Homework 3/02-the-perfect-printer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void solve() { 5 | long long n; 6 | int k; 7 | cin >> n >> k; 8 | 9 | vector p; 10 | for (int i = 0; i < k; i++) { 11 | int pr; 12 | cin >> pr; 13 | p.push_back(pr); 14 | } 15 | 16 | long long l = 0; 17 | long long r = LLONG_MAX; 18 | 19 | long long ans = LLONG_MAX; 20 | while (l <= r) { 21 | long long mid = (l + r) / 2; 22 | 23 | long long cur = n; 24 | for (int pr : p) { 25 | cur -= mid / pr; 26 | 27 | if (cur <= 0) { 28 | break; 29 | } 30 | } 31 | 32 | if (cur > 0) { 33 | l = mid + 1; 34 | } else { 35 | ans = mid; 36 | r = mid - 1; 37 | } 38 | } 39 | 40 | cout << ans << endl; 41 | } 42 | 43 | int main() { 44 | ios_base::sync_with_stdio(false); 45 | cin.tie(nullptr); 46 | 47 | solve(); 48 | 49 | return 0; 50 | } -------------------------------------------------------------------------------- /Homeworks 2020-2021/Homework 3/03-genetic-engineering.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | long long pw3[34]; 5 | 6 | int rec(long long num, long long start_num, int p, int d) { 7 | if (p == 0) { 8 | return d; 9 | } 10 | 11 | long long mid1 = start_num + (pw3[p] / 3); 12 | long long mid2 = start_num + (pw3[p] / 3) * 2; 13 | 14 | if (mid1 <= num && num < mid2) { 15 | return d; 16 | } 17 | if (num < mid1) { 18 | return rec(num, start_num, p - 1, d + 1); 19 | } 20 | return rec(num, mid2, p - 1, d + 1); 21 | } 22 | 23 | void solve() { 24 | int n, p; 25 | cin >> p >> n; 26 | 27 | pw3[0] = 1; 28 | for (int i = 1; i <= 33; i++) { 29 | pw3[i] = pw3[i - 1] * 3; 30 | } 31 | 32 | for (int i = 0; i < n; i++) { 33 | long long num; 34 | cin >> num; 35 | cout << rec(num, 1, p, 1) << "\n"; 36 | } 37 | } 38 | 39 | int main() { 40 | ios_base::sync_with_stdio(false); 41 | cin.tie(nullptr); 42 | 43 | solve(); 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /Homeworks 2020-2021/Homework 3/04-weird-queries.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int SIZE = 200001; 5 | 6 | int n, q, s; 7 | int a[SIZE]; 8 | int prefixSum[SIZE]; 9 | 10 | void input() { 11 | cin >> n >> q; 12 | for (int i = 0; i < n; i++) { 13 | cin >> a[i]; 14 | } 15 | } 16 | 17 | int findLast(int num) { 18 | int res = -1; 19 | int r = num; 20 | int l = 0; 21 | 22 | while (l <= r) { 23 | int mid = (l + r) >> 1; 24 | 25 | int intervalSum = prefixSum[num] - prefixSum[mid] + a[mid]; 26 | 27 | if (intervalSum > s) { 28 | res = mid; 29 | l = mid + 1; 30 | } else { 31 | r = mid - 1; 32 | } 33 | } 34 | 35 | return num - res; 36 | } 37 | 38 | int findFirst(int num) { 39 | int l = 0, r = n - 1; 40 | 41 | while (l <= r) { 42 | int mid = (l + r) >> 1; 43 | 44 | if (a[mid] <= num) { 45 | l = mid + 1; 46 | } else { 47 | r = mid - 1; 48 | } 49 | } 50 | 51 | return l - 1; 52 | } 53 | 54 | void solve() { 55 | sort(a, a + n); 56 | 57 | prefixSum[0] = a[0]; 58 | for (int i = 1; i < n; i++) { 59 | prefixSum[i] = prefixSum[i - 1] + a[i]; 60 | } 61 | 62 | for (int i = 0; i < q; i++) { 63 | int p; 64 | cin >> s >> p; 65 | cout << findLast(findFirst(p)) << "\n"; 66 | } 67 | } 68 | 69 | int main() { 70 | ios_base::sync_with_stdio(false); 71 | cin.tie(nullptr); 72 | 73 | input(); 74 | solve(); 75 | 76 | return 0; 77 | } -------------------------------------------------------------------------------- /Homeworks 2020-2021/Homework 3/05-between-us-bonus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | double distance(pair a, pair b) { 5 | return sqrt((a.first - b.first) * (a.first - b.first) + 6 | (a.second - b.second) * (a.second - b.second)); 7 | } 8 | 9 | void solve() { 10 | double x1, y1; 11 | cin >> x1 >> y1; 12 | 13 | double x2, y2; 14 | cin >> x2 >> y2; 15 | 16 | double v1, v2; 17 | cin >> v1 >> v2; 18 | 19 | double l = min(x1, x2); 20 | double r = max(x1, x2); 21 | 22 | double ans = (double) INT_MAX; 23 | 24 | int iterations = 30; 25 | while (iterations--) { 26 | double mid1 = l + (r - l) / 3.0; 27 | double mid2 = r - (r - l) / 3.0; 28 | 29 | double time1 = distance({x1, y1}, {mid1, 0.0}) / v1 + 30 | distance({mid1, 0.0}, {x2, y2}) / v2; 31 | 32 | double time2 = distance({x1, y1}, {mid2, 0.0}) / v1 + 33 | distance({mid2, 0.0}, {x2, y2}) / v2; 34 | 35 | ans = min(ans, min(time1, time2)); 36 | 37 | if (time1 <= time2) { 38 | r = mid2; 39 | } else { 40 | l = mid1; 41 | } 42 | } 43 | 44 | cout << ans << "\n"; 45 | } 46 | 47 | int main() { 48 | ios_base::sync_with_stdio(false); 49 | cin.tie(nullptr); 50 | cout << fixed << setprecision(5); 51 | 52 | int t; 53 | cin >> t; 54 | for (int i = 0; i < t; i++) { 55 | solve(); 56 | } 57 | 58 | return 0; 59 | } -------------------------------------------------------------------------------- /Lectures/00-Prerequisites/readme.md: -------------------------------------------------------------------------------- 1 | At this lecture you could find refreshing materials for the tools and programming language which will be needed for the Data Structures and algorithms course. 2 | -------------------------------------------------------------------------------- /Lectures/01-ComplexityOfAlgorithms/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/02-Sorting/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/03-Searching/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/04-LinkedList/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/05-Queue/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/06-Stack/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/07-Trees,BinarySearchTree/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/08-BalancedTrees/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/09-Heap/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/10-GeometricSearch, KDTree/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/11-Hashmap/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/12-DynamicProgramming/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/13-Graph. Representation and definitions/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/14-Grapht.Shortest Path, Dijkstra/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/15-MinimumSpanningTree/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /Lectures/16-Euler and Hamiltonian Sycle. P,NP,NP Complete tasks/readme.md: -------------------------------------------------------------------------------- 1 | Description of the lecture and the materials. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # data-structures-and-algorithms 2 | This project contains learning materials for the Data Structures and Algorithms course for students from Software Engineering program at Sofia University, Faculty of Mathematics and informatics 3 | -------------------------------------------------------------------------------- /Tests/Test 5/wave_game.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | class Node 5 | { 6 | public: 7 | int x; // x coordainate 8 | int y; // y coordainate 9 | int dist; // distance from the start 10 | Node(int x, int y, int distance) // constructor 11 | { 12 | this->x = x; 13 | this->y = y; 14 | this->dist = distance; 15 | } 16 | }; 17 | int arr[500][500], n, m; // the matrix and its dimensions 18 | int startX, startY, Distance; // the start coordinates and the distance 19 | bool used[500][500]; // boolean matrix where we will save if we used curtain vertex 20 | int sum; // the sum of all vertices at the given distance from start 21 | queue q; // the queue where we will push the vertices 22 | void read() // input 23 | { 24 | cin >> n >> m; 25 | for (int i = 0; i < n; i++) 26 | { 27 | for (int j = 0; j < m; j++) 28 | { 29 | cin >> arr[i][j]; 30 | } 31 | } 32 | cin >> startX >> startY >> Distance; 33 | } 34 | bool isValid(int x, int y, int dist) // Check if the coordinates are valid, the distance is lower than the target and it is not used 35 | { 36 | if (x > -1 && y > -1 && x < n && y < m && dist <= Distance && arr[x][y] != -1 && used[x][y] == false) 37 | return true; 38 | else 39 | return false; 40 | } 41 | void solve() 42 | { 43 | q.push(Node(startX - 1, startY - 1, 1)); // we start from (1,1) and it is at disatance 1 from itself 44 | 45 | used[startX - 1][startY - 1] = true; // mark it as visited 46 | 47 | while (!q.empty()) 48 | { 49 | Node current = q.front(); 50 | q.pop(); 51 | 52 | if (current.dist == Distance) // if it is at the right distance add it to the sum 53 | { 54 | sum += arr[current.x][current.y]; 55 | } 56 | else 57 | { 58 | // push the neighboring vertices into the queue if they are valid destinations and then use them 59 | if (isValid(current.x + 1, current.y, current.dist + 1)) 60 | { 61 | used[current.x + 1][current.y] = true; 62 | q.push(Node(current.x + 1, current.y, current.dist + 1)); 63 | } 64 | 65 | if (isValid(current.x - 1, current.y, current.dist + 1)) 66 | { 67 | used[current.x - 1][current.y] = true; 68 | q.push(Node(current.x - 1, current.y, current.dist + 1)); 69 | } 70 | 71 | if (isValid(current.x, current.y + 1, current.dist + 1)) 72 | { 73 | used[current.x][current.y + 1] = true; 74 | q.push(Node(current.x, current.y + 1, current.dist + 1)); 75 | } 76 | 77 | if (isValid(current.x, current.y - 1, current.dist + 1)) 78 | { 79 | used[current.x][current.y - 1] = true; 80 | q.push(Node(current.x, current.y - 1, current.dist + 1)); 81 | } 82 | } 83 | } 84 | } 85 | 86 | int main() 87 | { 88 | read(); 89 | solve(); 90 | cout << sum << endl; 91 | return 0; 92 | } -------------------------------------------------------------------------------- /Tests/Test1/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | 9 | int main() 10 | { 11 | int n; 12 | cin >> n; 13 | int arr[10000]; 14 | int x; 15 | for(int i = 0 ; i < 10000;i++){ 16 | arr[i] = 0; 17 | } 18 | for(int i = 0 ; i < n; i++){ 19 | 20 | cin >> x; 21 | arr[x]++; 22 | } 23 | for(int i = 10000-1; i >=0 ;i--){ 24 | for(int j = 0 ; j < arr[i];j++){ 25 | cout << i <<" "; 26 | } 27 | } 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Tests/Test2/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | 9 | struct Node { 10 | Node * next; 11 | int data; 12 | Node(Node* _next,int _data){ 13 | next = _next; 14 | data = _data; 15 | } 16 | }; 17 | class LinkedList{ 18 | public: 19 | LinkedList(){ 20 | head = NULL; 21 | } 22 | ~LinkedList(){ 23 | Node* tmp; 24 | while(head!=NULL){ 25 | tmp = head; 26 | head = head->next; 27 | delete tmp; 28 | } 29 | } 30 | void add(int number){ 31 | Node *tmp = new Node(head,number); 32 | head = tmp; 33 | } 34 | void print(){ 35 | Node* curr = head; 36 | while(curr!=NULL){ 37 | cout << curr->data << " "; 38 | curr = curr->next; 39 | } 40 | } 41 | void removeComplex(int devidedBy){ 42 | // TODO: write your code here 43 | Node* prev = NULL; 44 | Node* curr = head; 45 | 46 | while(curr!= NULL){ 47 | if(curr->data%devidedBy==0){ 48 | Node* tmp = curr; 49 | curr = curr->next; 50 | if(prev==NULL){ 51 | head = curr; 52 | }else{ 53 | prev->next = curr; 54 | } 55 | delete tmp; 56 | }else{ 57 | prev = curr; 58 | curr = curr->next; 59 | } 60 | 61 | } 62 | 63 | } // end removeComplex 64 | private: 65 | Node* head; 66 | }; 67 | int main(){ 68 | LinkedList l; 69 | 70 | int n; 71 | cin >> n; 72 | int number; 73 | for(int i = 0 ; i < n ; i++){ 74 | cin >>number; 75 | l.add(number); 76 | } 77 | int devidedBy; 78 | cin >> devidedBy; 79 | l.removeComplex(devidedBy); 80 | l.print(); 81 | } -------------------------------------------------------------------------------- /Tests/Test3/penultimate-descendants.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | struct Node { 9 | Node *left; 10 | Node *right; 11 | int value; 12 | Node(int value) { 13 | this->value = value; 14 | this->left = NULL; 15 | this->right = NULL; 16 | } 17 | }; 18 | 19 | class BST { 20 | 21 | public: 22 | BST() { 23 | root = NULL; 24 | } 25 | 26 | void insert(int value) { 27 | root = insert(root, value); 28 | } 29 | 30 | void deletePenultimateAndPrint() { 31 | deletePenultimate(root); 32 | inorder(root); 33 | } 34 | 35 | private: 36 | void deletePenultimate(Node* node) { 37 | if (node == nullptr) { 38 | return; 39 | } 40 | 41 | if (isLeaf(node->left) && (node->right == nullptr || isLeaf(node->right))) { 42 | node->value = node->left->value; 43 | delete node->left; 44 | node->left = nullptr; 45 | } else if (node->left == nullptr && isLeaf(node->right)) { 46 | node->value = node->right->value; 47 | delete node->right; 48 | node->right = nullptr; 49 | } 50 | 51 | deletePenultimate(node->left); 52 | deletePenultimate(node->right); 53 | } 54 | 55 | bool isLeaf(Node* node) { 56 | if (node == nullptr) { 57 | return false; 58 | } 59 | 60 | return node->left == nullptr && node->right == nullptr; 61 | } 62 | 63 | void inorder(Node* node) { 64 | if (node == nullptr) { 65 | return; 66 | } 67 | 68 | inorder(node->left); 69 | cout << (node->value) << " "; 70 | inorder(node->right); 71 | } 72 | 73 | Node* root; 74 | 75 | Node* insert(Node *curNode, int value) { 76 | if (curNode == NULL) { 77 | curNode = new Node(value); 78 | } else if (curNode->value < value) { 79 | curNode->right = insert(curNode->right, value); 80 | } else if (curNode->value > value) { 81 | curNode->left = insert(curNode->left, value); 82 | } else { 83 | //if we already have this value at the tree - do nothing 84 | } 85 | return curNode; 86 | } 87 | }; 88 | 89 | int main() { 90 | int n; 91 | cin >> n; 92 | int value; 93 | BST tree; 94 | for(int i = 0 ; i < n; i++) { 95 | cin >> value; 96 | tree.insert(value); 97 | } 98 | tree.deletePenultimateAndPrint(); 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /Tests/Test3/print-specific-level.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | struct Node { 9 | Node *left; 10 | Node *right; 11 | int value; 12 | Node(int value) { 13 | this->value = value; 14 | this->left = NULL; 15 | this->right = NULL; 16 | } 17 | }; 18 | 19 | class BST { 20 | 21 | public: 22 | BST() { 23 | root = NULL; 24 | } 25 | 26 | void insert(int value) { 27 | root = insert(root, value); 28 | } 29 | 30 | void printKDistant(int k) { 31 | printKDistant(root, k); 32 | } 33 | 34 | private: 35 | void printKDistant(Node* node, int k) { 36 | if (node == nullptr) { 37 | return; 38 | } 39 | 40 | if (k == 0) { 41 | cout << (node->value) << " "; 42 | return; 43 | } 44 | 45 | printKDistant(node->right, k - 1); 46 | printKDistant(node->left, k - 1); 47 | } 48 | 49 | Node* root; 50 | 51 | Node* insert(Node *curNode, int value) { 52 | if (curNode == NULL) { 53 | curNode = new Node(value); 54 | } else if (curNode->value < value) { 55 | curNode->right = insert(curNode->right, value); 56 | } else if (curNode->value > value) { 57 | curNode->left = insert(curNode->left, value); 58 | } else { 59 | //if we already have this value at the tree - do nothing 60 | } 61 | return curNode; 62 | } 63 | }; 64 | 65 | int main() { 66 | int n; 67 | cin >> n; 68 | int value; 69 | BST tree; 70 | for(int i = 0 ; i < n; i++) { 71 | cin >> value; 72 | tree.insert(value); 73 | } 74 | int k; 75 | cin >> k; 76 | tree.printKDistant(k); 77 | return 0; 78 | } 79 | --------------------------------------------------------------------------------