diff --git a/.gitignore b/.gitignore index 1a5f7b618..ed3934e45 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,6 @@ # Executables *.exe +a.out *.out *.app diff --git a/.vscode/settings.json b/.vscode/settings.json index 8b117a5fd..0ab2708d0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -63,5 +63,9 @@ "utility": "cpp", "valarray": "cpp", "algorithm": "cpp" - } -} \ No newline at end of file + }, + "C_Cpp.clang_format_style": "{BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 80, UseTab: Never}", + "editor.formatOnSave": true, + "editor.formatOnType": true, + "editor.formatOnPaste": true +} diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index adafa955a..9f0205bfd 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -12,8 +12,11 @@ We are very happy that you consider implementing algorithms and data structures - You submitted work fulfils or mostly fulfils our styles and standards. **New implementation** New implementation are welcome! + **Improving comments** and **adding tests** to existing algorithms are much appreciated. +**Issues** Please avoid opening issues asking to be "assigned” to a particular algorithm. This merely creates unnecessary noise for maintainers. Instead, please submit your implementation in a pull request and it will be evaluated by project maintainers. + ### Making Changes #### Code diff --git a/DIRECTORY.md b/DIRECTORY.md index d9ca3ae36..9e36309dc 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -4,6 +4,7 @@ * [Knight Tour](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/knight_tour.cpp) * [Minimax](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/minimax.cpp) * [N Queens](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/n_queens.cpp) + * [N Queens All Solution Optimised](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/n_queens_all_solution_optimised.cpp) * [Nqueen Print All Solutions](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/nqueen_print_all_solutions.cpp) * [Rat Maze](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/rat_maze.cpp) * [Sudoku Solve](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/sudoku_solve.cpp) @@ -13,6 +14,7 @@ * [False-Position](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/computer_oriented_statistical_methods/false-position.cpp) * [Gaussian Elimination](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/computer_oriented_statistical_methods/Gaussian_elimination.cpp) * [Newton Raphson](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/computer_oriented_statistical_methods/Newton_Raphson.CPP) + * [Ordinary Least Squares Regressor](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/computer_oriented_statistical_methods/ordinary_least_squares_regressor.cpp) * [Secant Method](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/computer_oriented_statistical_methods/Secant_method.CPP) * [Successive Approximation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/computer_oriented_statistical_methods/successive_approximation.CPP) @@ -26,7 +28,7 @@ * [Cll](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/cll/cll.h) * [Main Cll](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/cll/main_cll.cpp) * [Disjoint Set](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/disjoint_set.cpp) - * [Doubly Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/Doubly%20Linked%20List.cpp) + * [Doubly Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/doubly_linked_list.cpp) * [Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/linked_list.cpp) * [Linkedlist Implentation Usingarray](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/linkedList_implentation_usingArray.cpp) * [List Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/List%20Array.cpp) @@ -72,13 +74,19 @@ ## Graph * [Bfs](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/BFS.cpp) + * [Bridge Finding With Tarjan Algorithm](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/bridge_finding_with_tarjan_algorithm.cpp) + * [Connected Components](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/connected_components.cpp) + * [Connected Components With Dsu](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/connected_components_with_dsu.cpp) * [Dfs](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/DFS.cpp) * [Dfs With Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/DFS_with_stack.cc) * [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/Dijkstra.cpp) * [Kosaraju](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/kosaraju.cpp) * [Kruskal](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/Kruskal.cpp) * [Lca](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/lca.cpp) + * [Max Flow With Ford Fulkerson And Edmond Karp Algo](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/max_flow_with_ford_fulkerson_and_edmond_karp_algo.cpp) + * [Prim](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/prim.cpp) * [Topological-Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/Topological-Sort.cpp) + * [Topological Sort By Kahns Algo](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/topological_sort_by_kahns_algo.cpp) ## Greedy Algorithms * [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/greedy_algorithms/Dijkstra.cpp) @@ -95,9 +103,12 @@ ## Math * [Binary Exponent](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/binary_exponent.cpp) + * [Double Factorial](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/double_factorial.cpp) * [Eulers Totient Function](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/eulers_totient_function.cpp) + * [Extended Euclid Algorithm](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/extended_euclid_algorithm.cpp) * [Factorial](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/factorial.cpp) * [Fast Power](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/fast_power.cpp) + * [Fibonacci](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/fibonacci.cpp) * [Greatest Common Divisor](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/greatest_common_divisor.cpp) * [Greatest Common Divisor Euclidean](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/greatest_common_divisor_euclidean.cpp) * [Modular Inverse Fermat Little Theorem](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_inverse_fermat_little_theorem.cpp) @@ -114,6 +125,7 @@ * [Array Right Rotation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/Array%20Right%20Rotation.cpp) * [Circular Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/Circular%20Linked%20List.cpp) * [Circular Queue Using Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/Circular%20Queue%20Using%20Array.cpp) + * [Get Size Of Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/get_size_of_linked_list.cpp) * [Intersection Of 2 Arrays](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/Intersection_of_2_arrays.cpp) * [Reverse A Linked List Using Recusion](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/Reverse%20a%20Linked%20List%20using%20Recusion.cpp) * [Selectionsortlinkedlist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/selectionSortLinkedList.cpp) @@ -146,6 +158,9 @@ ## Probability * [Addition Rule](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/probability/addition_rule.cpp) + * [Bayes Theorem](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/probability/bayes_theorem.cpp) + * [Binomial Dist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/probability/binomial_dist.cpp) + * [Poisson Dist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/probability/poisson_dist.cpp) ## Range Queries * [Bit](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/range_queries/bit.cpp) @@ -154,11 +169,12 @@ * [Segtree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/range_queries/segTree.cpp) ## Search - * [Binary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/Binary%20Search.cpp) + * [Binary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/binary_search.cpp) * [Exponential Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/exponential_search.cpp) * [Hash Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/hash_search.cpp) * [Interpolation Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/Interpolation%20Search.cpp) * [Interpolation Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/interpolation_search.cpp) + * [Jump Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/jump_search.cpp) * [Linear Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/Linear%20Search.cpp) * [Median Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/median_search.cpp) * [Searching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/searching.cpp) @@ -185,8 +201,10 @@ * [Selection Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/Selection%20Sort.cpp) * [Shell Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/Shell%20Sort.cpp) * [Slow Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/Slow%20Sort.cpp) + * [Swap Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/swap_sort.cpp) * [Tim Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/Tim%20Sort.cpp) ## Strings * [Brute Force String Searching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/strings/brute_force_string_searching.cpp) * [Knuth Morris Pratt](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/strings/knuth_morris_pratt.cpp) + * [Rabin Karp](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/strings/rabin_karp.cpp) diff --git a/backtracking/n_queens_all_solution_optimised.cpp b/backtracking/n_queens_all_solution_optimised.cpp new file mode 100644 index 000000000..1db730f63 --- /dev/null +++ b/backtracking/n_queens_all_solution_optimised.cpp @@ -0,0 +1,75 @@ +#include +#define n 4 +#define inc_loop(var, start, stop) for (int var=start; var <= stop; var++) +#define dec_loop(var, start, stop) for (int var=start; var >= stop; var--) +void PrintSol(int Board[n][n]) { + inc_loop(i, 0, n-1) { + inc_loop(j, 0, n-1) + std::cout << Board[i][j] << " "; + std::cout << std::endl; + } + std::cout << std::endl; + if (n%2 == 0 || (n%2 == 1 && Board[n/2+1][0] != 1)) { + inc_loop(i, 0, n-1) { + dec_loop(j, n-1, 0) + std::cout << Board[i][j] << " "; + std::cout << std::endl; + } + std::cout << std::endl; + } +} + +bool CanIMove(int Board[n][n], int row, int col) { + /// check in the row + inc_loop(i, 0, col-1) { + if (Board[row][i] == 1) + return false; + } + /// check the first diagonal + for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) { + if (Board[i][j] == 1) + return false; + } + /// check the second diagonal + for (int i = row, j = col; i <= n - 1 && j >= 0; i++, j--) { + if (Board[i][j] == 1) + return false; + } + return true; +} + +void NQueenSol(int Board[n][n], int col) { + if (col >= n) { + PrintSol(Board); + return; + } + inc_loop(i, 0, n-1) { + if (CanIMove(Board, i, col)) { + Board[i][col] = 1; + NQueenSol(Board, col + 1); + Board[i][col] = 0; + } + } +} + +int main() { + int Board[n][n] = {0}; + if (n%2 == 0) { + inc_loop(i, 0, n/2-1) { + if (CanIMove(Board, i, 0)) { + Board[i][0] = 1; + NQueenSol(Board, 1); + Board[i][0] = 0; + } + } + } else { + inc_loop(i, 0, n/2) { + if (CanIMove(Board, i, 0)) { + Board[i][0] = 1; + NQueenSol(Board, 1); + Board[i][0] = 0; + } + } + } + return 0; +} diff --git a/computer_oriented_statistical_methods/ordinary_least_squares_regressor.cpp b/computer_oriented_statistical_methods/ordinary_least_squares_regressor.cpp new file mode 100644 index 000000000..f50ccf1b1 --- /dev/null +++ b/computer_oriented_statistical_methods/ordinary_least_squares_regressor.cpp @@ -0,0 +1,349 @@ +/** + * Program that gets the number of data samples and number of features per + * sample along with output per sample. It applies OLS regression to compute + * the regression output for additional test data samples. + **/ +#include +#include +#include + +template +std::ostream &operator<<(std::ostream &out, + std::vector> const &v) { + const int width = 10; + const char separator = ' '; + + for (size_t row = 0; row < v.size(); row++) { + for (size_t col = 0; col < v[row].size(); col++) + out << std::left << std::setw(width) << std::setfill(separator) + << v[row][col]; + out << std::endl; + } + + return out; +} + +template +std::ostream &operator<<(std::ostream &out, std::vector const &v) { + const int width = 15; + const char separator = ' '; + + for (size_t row = 0; row < v.size(); row++) + out << std::left << std::setw(width) << std::setfill(separator) << v[row]; + + return out; +} + +template +inline bool is_square(std::vector> const &A) { + // Assuming A is square matrix + size_t N = A.size(); + for (size_t i = 0; i < N; i++) + if (A[i].size() != N) + return false; + return true; +} + +/** + * matrix multiplication + **/ +template +std::vector> operator*(std::vector> const &A, + std::vector> const &B) { + // Number of rows in A + size_t N_A = A.size(); + // Number of columns in B + size_t N_B = B[0].size(); + + std::vector> result(N_A); + + if (A[0].size() != B.size()) { + std::cerr << "Number of columns in A != Number of rows in B (" + << A[0].size() << ", " << B.size() << ")" << std::endl; + return result; + } + + for (size_t row = 0; row < N_A; row++) { + std::vector v(N_B); + for (size_t col = 0; col < N_B; col++) { + v[col] = static_cast(0); + for (size_t j = 0; j < B.size(); j++) + v[col] += A[row][j] * B[j][col]; + } + result[row] = v; + } + + return result; +} + +template +std::vector operator*(std::vector> const &A, + std::vector const &B) { + // Number of rows in A + size_t N_A = A.size(); + + std::vector result(N_A); + + if (A[0].size() != B.size()) { + std::cerr << "Number of columns in A != Number of rows in B (" + << A[0].size() << ", " << B.size() << ")" << std::endl; + return result; + } + + for (size_t row = 0; row < N_A; row++) { + result[row] = static_cast(0); + for (size_t j = 0; j < B.size(); j++) + result[row] += A[row][j] * B[j]; + } + + return result; +} + +template +std::vector operator*(float const scalar, std::vector const &A) { + // Number of rows in A + size_t N_A = A.size(); + + std::vector result(N_A); + + for (size_t row = 0; row < N_A; row++) { + result[row] += A[row] * static_cast(scalar); + } + + return result; +} + +template +std::vector operator*(std::vector const &A, float const scalar) { + // Number of rows in A + size_t N_A = A.size(); + + std::vector result(N_A); + + for (size_t row = 0; row < N_A; row++) + result[row] = A[row] * static_cast(scalar); + + return result; +} + +template +std::vector operator/(std::vector const &A, float const scalar) { + return (1.f / scalar) * A; +} + +template +std::vector operator-(std::vector const &A, std::vector const &B) { + // Number of rows in A + size_t N = A.size(); + + std::vector result(N); + + if (B.size() != N) { + std::cerr << "Vector dimensions shouldbe identical!" << std::endl; + return A; + } + + for (size_t row = 0; row < N; row++) + result[row] = A[row] - B[row]; + + return result; +} + +template +std::vector operator+(std::vector const &A, std::vector const &B) { + // Number of rows in A + size_t N = A.size(); + + std::vector result(N); + + if (B.size() != N) { + std::cerr << "Vector dimensions shouldbe identical!" << std::endl; + return A; + } + + for (size_t row = 0; row < N; row++) + result[row] = A[row] + B[row]; + + return result; +} + +/** + * Get matrix inverse using Row-trasnformations + **/ +template +std::vector> +get_inverse(std::vector> const &A) { + // Assuming A is square matrix + size_t N = A.size(); + + std::vector> inverse(N); + for (size_t row = 0; row < N; row++) { + // preallocatae a resultant identity matrix + inverse[row] = std::vector(N); + for (size_t col = 0; col < N; col++) + inverse[row][col] = (row == col) ? 1.f : 0.f; + } + + if (!is_square(A)) { + std::cerr << "A must be a square matrix!" << std::endl; + return inverse; + } + + // preallocatae a temporary matrix identical to A + std::vector> temp(N); + for (size_t row = 0; row < N; row++) { + std::vector v(N); + for (size_t col = 0; col < N; col++) + v[col] = static_cast(A[row][col]); + temp[row] = v; + } + + // start transformations + for (size_t row = 0; row < N; row++) { + for (size_t row2 = row; row2 < N && temp[row][row] == 0; row2++) { + // this to ensure diagonal elements are not 0 + temp[row] = temp[row] + temp[row2]; + inverse[row] = inverse[row] + inverse[row2]; + } + + for (size_t col2 = row; col2 < N && temp[row][row] == 0; col2++) { + // this to further ensure diagonal elements are not 0 + for (size_t row2 = 0; row2 < N; row2++) { + temp[row2][row] = temp[row2][row] + temp[row2][col2]; + inverse[row2][row] = inverse[row2][row] + inverse[row2][col2]; + } + } + + if (temp[row][row] == 0) { + // Probably a low-rank matrix and hence singular + std::cerr << "Low-rank matrix, no inverse!" << std::endl; + return inverse; + } + + // set diagonal to 1 + float divisor = static_cast(temp[row][row]); + temp[row] = temp[row] / divisor; + inverse[row] = inverse[row] / divisor; + // Row transformations + for (size_t row2 = 0; row2 < N; row2++) { + if (row2 == row) + continue; + float factor = temp[row2][row]; + temp[row2] = temp[row2] - factor * temp[row]; + inverse[row2] = inverse[row2] - factor * inverse[row]; + } + } + + return inverse; +} + +/** + * matrix transpose + **/ +template +std::vector> +get_transpose(std::vector> const &A) { + std::vector> result(A[0].size()); + + for (size_t row = 0; row < A[0].size(); row++) { + std::vector v(A.size()); + for (size_t col = 0; col < A.size(); col++) + v[col] = A[col][row]; + + result[row] = v; + } + return result; +} + +template +std::vector fit_OLS_regressor(std::vector> const &X, + std::vector const &Y) { + // NxF + std::vector> X2 = X; + for (size_t i = 0; i < X2.size(); i++) + // add Y-intercept -> Nx(F+1) + X2[i].push_back(1); + // (F+1)xN + std::vector> Xt = get_transpose(X2); + // (F+1)x(F+1) + std::vector> tmp = get_inverse(Xt * X2); + // (F+1)xN + std::vector> out = tmp * Xt; + // cout << endl + // << "Projection matrix: " << X2 * out << endl; + + // Fx1,1 -> (F+1)^th element is the independent constant + return out * Y; +} + +/** + * Given data and OLS model coeffficients, predict + * regression estimates + **/ +template +std::vector predict_OLS_regressor(std::vector> const &X, + std::vector const &beta) { + std::vector result(X.size()); + + for (size_t rows = 0; rows < X.size(); rows++) { + // -> start with constant term + result[rows] = beta[X[0].size()]; + for (size_t cols = 0; cols < X[0].size(); cols++) + result[rows] += beta[cols] * X[rows][cols]; + } + // Nx1 + return result; +} + +int main() { + size_t N, F; + + std::cout << "Enter number of features: "; + // number of features = columns + std::cin >> F; + std::cout << "Enter number of samples: "; + // number of samples = rows + std::cin >> N; + + std::vector> data(N); + std::vector Y(N); + + std::cout + << "Enter training data. Per sample, provide features ad one output." + << std::endl; + + for (size_t rows = 0; rows < N; rows++) { + std::vector v(F); + std::cout << "Sample# " << rows + 1 << ": "; + for (size_t cols = 0; cols < F; cols++) + // get the F features + std::cin >> v[cols]; + data[rows] = v; + // get the corresponding output + std::cin >> Y[rows]; + } + + std::vector beta = fit_OLS_regressor(data, Y); + std::cout << std::endl << std::endl << "beta:" << beta << std::endl; + + size_t T; + std::cout << "Enter number of test samples: "; + // number of test sample inputs + std::cin >> T; + std::vector> data2(T); + // vector Y2(T); + + for (size_t rows = 0; rows < T; rows++) { + std::cout << "Sample# " << rows + 1 << ": "; + std::vector v(F); + for (size_t cols = 0; cols < F; cols++) + std::cin >> v[cols]; + data2[rows] = v; + } + + std::vector out = predict_OLS_regressor(data2, beta); + for (size_t rows = 0; rows < T; rows++) + std::cout << out[rows] << std::endl; + + return 0; +} diff --git a/data_structure/Doubly Linked List.cpp b/data_structure/Doubly Linked List.cpp deleted file mode 100644 index 84a239d3f..000000000 --- a/data_structure/Doubly Linked List.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include -using namespace std; - -struct node -{ - int val; - node *prev; - node *next; -}; - -node *start; - -void insert(int x) -{ - node *t = start; - if (start != NULL) - { - while (t->next != NULL) - { - t = t->next; - } - node *n = new node; - t->next = n; - n->prev = t; - n->val = x; - n->next = NULL; - } - else - { - node *n = new node; - n->val = x; - n->prev = NULL; - n->next = NULL; - start = n; - } -} - -void remove(int x) -{ - node *t = start; - while (t->val != x) - { - t = t->next; - } - t->prev->next = t->next; - t->next->prev = t->prev; - delete t; -} - -void search(int x) -{ - node *t = start; - int found = 0; - while (t != NULL) - { - if (t->val == x) - { - cout << "\nFound"; - found = 1; - break; - } - t = t->next; - } - if (found == 0) - { - cout << "\nNot Found"; - } -} - -void show() -{ - node *t = start; - while (t != NULL) - { - cout << t->val << "\t"; - t = t->next; - } -} - -void reverseShow() -{ - node *t = start; - while (t->next != NULL) - { - t = t->next; - } - while (t != NULL) - { - cout << t->val << "\t"; - t = t->prev; - } -} - -int main() -{ - int choice, x; - do - { - cout << "\n1. Insert"; - cout << "\n2. Delete"; - cout << "\n3. Search"; - cout << "\n4. Forward print"; - cout << "\n5. Reverse print"; - cout << "\n\nEnter you choice : "; - cin >> choice; - switch (choice) - { - case 1: - cout << "\nEnter the element to be inserted : "; - cin >> x; - ; - insert(x); - break; - case 2: - cout << "\nEnter the element to be removed : "; - cin >> x; - remove(x); - break; - case 3: - cout << "\nEnter the element to be searched : "; - cin >> x; - search(x); - break; - case 4: - show(); - break; - case 5: - reverseShow(); - break; - } - } while (choice != 0); - - return 0; -} diff --git a/data_structure/doubly_linked_list.cpp b/data_structure/doubly_linked_list.cpp new file mode 100644 index 000000000..4fc38abfc --- /dev/null +++ b/data_structure/doubly_linked_list.cpp @@ -0,0 +1,138 @@ +#include +#include +#include + +struct node { + int val; + node *prev; + node *next; +}*start; + +class double_linked_list { + public: + double_linked_list() { + start = NULL; + } + void insert(int x); + void remove(int x); + void search(int x); + void show(); + void reverseShow(); +}; + +void double_linked_list::insert(int x) { + node *t = start; + if (start != NULL) { + while (t->next != NULL) { + t = t->next; + } + node *n = new node; + t->next = n; + n->prev = t; + n->val = x; + n->next = NULL; + } else { + node *n = new node; + n->val = x; + n->prev = NULL; + n->next = NULL; + start = n; + } +} + +void double_linked_list::remove(int x) { + node *t = start; + while (t != NULL && t->val != x) { + t = t-> next; + } + if (t == NULL) { + return; + } + if (t->prev == NULL) { + if (t->next == NULL) { + start = NULL; + } else { + start = t->next; + start->prev = NULL; + } + } else if (t->next == NULL) { + t->prev->next = NULL; + } else { + t->prev->next = t->next; + t->next->prev = t->prev; + } + delete t; +} + +void double_linked_list::search(int x) { + node *t = start; + int found = 0; + while (t != NULL) { + if (t->val == x) { + std::cout << "\nFound"; + found = 1; + break; + } + t = t->next; + } + if (found == 0) { + std::cout << "\nNot Found"; + } +} + +void double_linked_list::show() { + node *t = start; + while (t != NULL) { + std::cout << t->val << "\t"; + t = t->next; + } +} + +void double_linked_list::reverseShow() { + node *t = start; + while (t != NULL && t->next != NULL) { + t = t->next; + } + while (t != NULL) { + std::cout << t->val << "\t"; + t = t->prev; + } +} + +int main() { + int choice, x; + double_linked_list ob; + do { + std::cout << "\n1. Insert"; + std::cout << "\n2. Delete"; + std::cout << "\n3. Search"; + std::cout << "\n4. Forward print"; + std::cout << "\n5. Reverse print"; + std::cout << "\n\nEnter you choice : "; + std::cin >> choice; + switch (choice) { + case 1: + std::cout << "\nEnter the element to be inserted : "; + std::cin >> x; + ob.insert(x); + break; + case 2: + std::cout << "\nEnter the element to be removed : "; + std::cin >> x; + ob.remove(x); + break; + case 3: + std::cout << "\nEnter the element to be searched : "; + std::cin >> x; + ob.search(x); + break; + case 4: + ob.show(); + break; + case 5: + ob.reverseShow(); + break; + } + } while (choice != 0); + return 0; +} diff --git a/graph/bridge_finding_with_tarjan_algorithm.cpp b/graph/bridge_finding_with_tarjan_algorithm.cpp new file mode 100644 index 000000000..ca124f512 --- /dev/null +++ b/graph/bridge_finding_with_tarjan_algorithm.cpp @@ -0,0 +1,79 @@ +/* + * Copyright : 2020 , MIT + * Author : Amit Kumar (offamitkumar) + * Last Modified Date: May 24, 2020 + * + */ +#include // for std::vector +#include // for min & max +#include // for cout +using std::vector; +using std::cout; +using std::min; +class Solution { + vector < vector < int > > graph; + vectorin_time , out_time; + int timer; + vector < vector < int > > bridge; + vectorvisited; + void dfs(int current_node , int parent) { + visited.at(current_node) = true; + in_time[current_node] = out_time[current_node] = timer++; + for ( auto&itr : graph[current_node] ) { + if (itr == parent) { + continue; + } + if (!visited[itr]) { + dfs(itr , current_node); + if (out_time[itr] > in_time[current_node]) { + bridge.push_back({itr, current_node}); + } + } + out_time[current_node] = min(out_time[current_node], out_time[itr]); + } + } + + public: + vector > search_bridges(int n, + const vector>& connections) { + timer = 0; + graph.resize(n); + in_time.assign(n, 0); + visited.assign(n, false); + out_time.assign(n, 0); + for (auto&itr : connections) { + graph.at(itr[0]).push_back(itr[1]); + graph.at(itr[1]).push_back(itr[0]); + } + dfs(0, -1); + return bridge; + } +}; +int main(void) { + Solution s1; + int number_of_node = 5; + vector< vector >node; + node.push_back({0, 1}); + node.push_back({1, 3}); + node.push_back({1, 2}); + node.push_back({2, 4}); + /* + * 0 <--> 1 <---> 2 + * ^ ^ + * | | + * | | + * \/ \/ + * 3 4 + * + * In this graph there are 4 bridges [0,2] , [2,4] , [3,5] , [1,2] + * + * I assumed that the graph is bi-directional and connected. + * + */ + vector< vector > bridges = s1.search_bridges(number_of_node , node); + cout << bridges.size() << " bridges found!\n"; + for (auto&itr : bridges) { + cout << itr[0] << " --> " << itr[1] << '\n'; + } + return 0; +} diff --git a/graph/connected_components_with_dsu.cpp b/graph/connected_components_with_dsu.cpp new file mode 100644 index 000000000..2c5c6dab5 --- /dev/null +++ b/graph/connected_components_with_dsu.cpp @@ -0,0 +1,55 @@ +#include +#include +#include + +int N; // denotes number of nodes; +std::vector parent; +std::vector siz; +void make_set() { // function the initialize every node as it's own parent + for (int i = 1; i <= N; i++) { + parent[i] = i; + siz[i] = 1; + } +} +// To find the component where following node belongs to +int find_set(int v) { + if (v == parent[v]) + return v; + return parent[v] = find_set(parent[v]); +} + +void union_sets(int a, int b) { // To join 2 components to belong to one + a = find_set(a); + b = find_set(b); + if (a != b) { + if (siz[a] < siz[b]) + std::swap(a, b); + parent[b] = a; + siz[a] += siz[b]; + } +} + +int no_of_connected_components() { // To find total no of connected components + std::set temp; // temp set to count number of connected components + for (int i = 1; i <= N; i++) + temp.insert(find_set(i)); + return temp.size(); +} + +// All critical/corner cases have been taken care of. +// Input your required values: (not hardcoded) +int main() { + std::cin >> N; + parent.resize(N + 1); + siz.resize(N + 1); + make_set(); + int edges; + std::cin >> edges; // no of edges in the graph + while (edges--) { + int node_a, node_b; + std::cin >> node_a >> node_b; + union_sets(node_a, node_b); + } + std::cout << no_of_connected_components() << std::endl; + return 0; +} diff --git a/graph/max_flow_with_ford_fulkerson_and_edmond_karp_algo.cpp b/graph/max_flow_with_ford_fulkerson_and_edmond_karp_algo.cpp new file mode 100644 index 000000000..ee394d9f0 --- /dev/null +++ b/graph/max_flow_with_ford_fulkerson_and_edmond_karp_algo.cpp @@ -0,0 +1,122 @@ +/* + * Author: Amit Kumar + * Created: May 24, 2020 + * Copyright: 2020, Open-Source + * Last Modified: May 25, 2020 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +// std::max capacity of node in graph +const int MAXN = 505; +class Graph { + int residual_capacity[MAXN][MAXN]; + int capacity[MAXN][MAXN]; // used while checking the flow of edge + int total_nodes; + int total_edges, source, sink; + int parent[MAXN]; + std::vector >edge_participated; + std::bitset visited; + int max_flow = 0; + bool bfs(int source, int sink) { // to find the augmented - path + memset(parent, -1, sizeof(parent)); + visited.reset(); + std::queueq; + q.push(source); + bool is_path_found = false; + while (q.empty() == false && is_path_found == false) { + int current_node = q.front(); + visited.set(current_node); + q.pop(); + for (int i = 0; i < total_nodes; ++i) { + if (residual_capacity[current_node][i] > 0 && !visited[i]) { + visited.set(i); + parent[i] = current_node; + if (i == sink) { + return true; + } + q.push(i); + } + } + } + return false; + } + + public: + Graph() { + memset(residual_capacity, 0, sizeof(residual_capacity)); + } + void set_graph(void) { + std::cin >> total_nodes >> total_edges >> source >> sink; + for (int start, destination, capacity_, i = 0; i < total_edges; ++i) { + std::cin >> start >> destination >> capacity_; + residual_capacity[start][destination] = capacity_; + capacity[start][destination] = capacity_; + } + } + void ford_fulkerson(void) { + while (bfs(source, sink)) { + int current_node = sink; + int flow = std::numeric_limits::max(); + while (current_node != source) { + int parent_ = parent[current_node]; + flow = std::min(flow, residual_capacity[parent_][current_node]); + current_node = parent_; + } + current_node = sink; + max_flow += flow; + while ( current_node != source ) { + int parent_ = parent[current_node]; + residual_capacity[parent_][current_node] -= flow; + residual_capacity[current_node][parent_] += flow; + current_node = parent_; + } + } + } + void print_flow_info(void) { + for (int i = 0; i < total_nodes; ++i) { + for (int j = 0; j < total_nodes; ++j) { + if (capacity[i][j] && + residual_capacity[i][j] < capacity[i][j]) { + edge_participated.push_back( + std::make_tuple(i, j, + capacity[i][j]-residual_capacity[i][j])); + } + } + } + std::cout << "\nNodes : " << total_nodes + << "\nMax flow: " << max_flow + << "\nEdge present in flow: " << edge_participated.size() + << '\n'; + std::cout<< "\nSource\tDestination\tCapacity\total_nodes"; + for (auto&edge_data : edge_participated) { + int source, destination, capacity_; + std::tie(source, destination, capacity_) = edge_data; + std::cout << source << "\t" << destination << "\t\t" + << capacity_ <<'\t'; + } + } +}; +int main(void) { + /* + Input Graph: (for testing ) + 4 5 0 3 + 0 1 10 + 1 2 1 + 1 3 1 + 0 2 1 + 2 3 10 + */ + Graph graph; + graph.set_graph(); + graph.ford_fulkerson(); + graph.print_flow_info(); + return 0; +} + diff --git a/graph/prim.cpp b/graph/prim.cpp new file mode 100644 index 000000000..2923b5b25 --- /dev/null +++ b/graph/prim.cpp @@ -0,0 +1,58 @@ +// C++ program to implement Prim's Algorithm +#include +#include +#include + +const int MAX = 1e4 + 5; +typedef std:: pair PII; + +bool marked[MAX]; +std:: vector adj[MAX]; + +int prim(int x) { + // priority queue to maintain edges with respect to weights + std:: priority_queue, std:: greater > Q; + int y; + int minimumCost = 0; + PII p; + + Q.push(std:: make_pair(0, x)); + while (!Q.empty()) { + // Select the edge with minimum weight + p = Q.top(); + Q.pop(); + x = p.second; + // Checking for cycle + if (marked[x] == true) + continue; + minimumCost += p.first; + marked[x] = true; + for (int i = 0; i < adj[x].size(); ++i) { + y = adj[x][i].second; + if (marked[y] == false) + Q.push(adj[x][i]); + } + } + return minimumCost; +} + +int main() { + int nodes, edges, x, y; + int weight, minimumCost; + + std:: cin >> nodes >> edges; // number of nodes & edges in graph + if (nodes == 0 || edges == 0) + return 0; + + // Edges with their nodes & weight + for (int i = 0; i < edges; ++i) { + std::cin >> x >> y >> weight; + adj[x].push_back(std:: make_pair(weight, y)); + adj[y].push_back(std:: make_pair(weight, x)); + } + + // Selecting 1 as the starting node + minimumCost = prim(1); + std:: cout << minimumCost << std:: endl; + return 0; +} diff --git a/graph/topological_sort_by_kahns_algo.cpp b/graph/topological_sort_by_kahns_algo.cpp new file mode 100644 index 000000000..eda2a74bc --- /dev/null +++ b/graph/topological_sort_by_kahns_algo.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +int *topoSortKahn(int N, std::vector adj[]); + +int main() { + int nodes, edges; + std::cin >> edges >> nodes; + if (edges == 0 || nodes == 0) + return 0; + int u, v; + + std::vectorgraph[nodes]; + // create graph + // example + // 6 6 + // 5 0 5 2 2 3 4 0 4 1 1 3 + + for (int i = 0; i < edges; i++) { + std::cin >> u >> v; + graph[u].push_back(v); + } + + int *topo = topoSortKahn(nodes, graph); + // topologically sorted nodes + for (int i = 0; i < nodes; i++) { + std::cout << topo[i] << " "; + } +} + +int* topoSortKahn(int V, std::vector adj[]) { + std::vectorvis(V+1, false); + std::vectordeg(V+1, 0); + for (int i = 0; i < V; i++) { + for (int j = 0; j < adj[i].size(); j++) { + deg[adj[i][j]]++; + } + } + std::queueq; + for (int i = 0; i < V; i++) { + if (deg[i] == 0) { + q.push(i); + vis[i] = true; + } + } + int *arr = new int[V+1]; + memset(arr, 0, V+1); + int count = 0; + while (!q.empty()) { + int cur = q.front(); + q.pop(); + arr[count] = cur; + count++; + for (int i = 0; i < adj[cur].size(); i++) { + if (!vis[adj[cur][i]]) { + deg[adj[cur][i]]--; + if (deg[adj[cur][i]] == 0) { + q.push(adj[cur][i]); + vis[adj[cur][i]] = true; + } + } + } + } + return arr; +} diff --git a/math/double_factorial.cpp b/math/double_factorial.cpp new file mode 100644 index 000000000..7b0d1d970 --- /dev/null +++ b/math/double_factorial.cpp @@ -0,0 +1,28 @@ +#include +#include + +/* Double factorial of a non-negative integer n, is defined as the product of +all the integers from 1 to n that have the same parity (odd or even) as n. +It is also called as semifactorial of a number and is denoted by !! */ + +uint64_t double_factorial_iterative(uint64_t n) { + uint64_t res = 1; + for ( uint64_t i = n; i >= 0; i -= 2 ) { + if (i == 0 || i == 1) return res; + res *= i; + } +} + +/* Recursion can be costly for large numbers */ + +uint64_t double_factorial_recursive(uint64_t n) { + if (n <= 1) return 1; + return n * double_factorial_recursive(n - 2); +} + +int main() { + uint64_t n{}; + std::cin >> n; + assert(n >= 0); + std::cout << double_factorial_iterative(n); +} diff --git a/math/extended_euclid_algorithm.cpp b/math/extended_euclid_algorithm.cpp new file mode 100644 index 000000000..3db14802f --- /dev/null +++ b/math/extended_euclid_algorithm.cpp @@ -0,0 +1,28 @@ +#include +// Finding coefficients of a and b ie x and y in gcd(a, b) = a * x + b * y +// d is gcd(a, b) +// This is also used in finding Modular multiplicative inverse of a number. +// (A * B)%M == 1 Here B is the MMI of A for given M, +// so extendedEuclid (A, M) gives B. + +int d, x, y; +void extendedEuclid(int A, int B) { + if (B == 0) { + d = A; + x = 1; + y = 0; + } else { + extendedEuclid(B, A%B); + int temp = x; + x = y; + y = temp - (A/B)*y; + } +} + +int main() { + int a, b; + std::cin >> a >> b; + extendedEuclid(a, b); + std::cout << x << " " << y << std::endl; + return 0; +} diff --git a/math/fibonacci.cpp b/math/fibonacci.cpp new file mode 100644 index 000000000..1c07cd93f --- /dev/null +++ b/math/fibonacci.cpp @@ -0,0 +1,25 @@ +#include +#include + +/* Calculate the the value on Fibonacci's sequence given an +integer as input +Fibonacci = 0, 1, 1, 2, 3, 5, + 8, 13, 21, 34, 55, + 89, 144, ... */ + +int fibonacci(uint n) { + /* If the input is 0 or 1 just return the same + This will set the first 2 values of the sequence */ + if (n <= 1) + return n; + + /* Add the last 2 values of the sequence to get next */ + return fibonacci(n-1) + fibonacci(n-2); +} + +int main() { + int n; + std::cin >> n; + assert(n >= 0); + std::cout << "F(" << n << ")= " << fibonacci(n) << std::endl; +} diff --git a/math/sqrt_double.cpp b/math/sqrt_double.cpp index e3418bfc3..5a0fd1c88 100644 --- a/math/sqrt_double.cpp +++ b/math/sqrt_double.cpp @@ -6,6 +6,9 @@ number in O(logn) time, with precision fixed */ double Sqrt(double x) { + if ( x > 0 && x < 1 ) { + return 1/Sqrt(1/x); + } double l = 0, r = x; /* Epsilon is the precision. A great precision is diff --git a/operations_on_datastructures/get_size_of_linked_list.cpp b/operations_on_datastructures/get_size_of_linked_list.cpp new file mode 100644 index 000000000..84f8db07f --- /dev/null +++ b/operations_on_datastructures/get_size_of_linked_list.cpp @@ -0,0 +1,36 @@ +#include + +class Node { + public: + int val; + Node *next; + + Node(int v, Node *n) : val(v), next(n) {} // Default constructor for Node +}; + +int getSize(Node *root) { + if (root == NULL) { + return 0; + } + // Each node will return 1 so the total adds up to be the size + return 1 + getSize(root->next); +} + +int main() { + Node *myList = new Node(0, NULL); // Initializes the LinkedList + Node *temp = myList; + // Creates a linked lists of total size 10, numbered 1 - 10 + for (int i = 1; i < 10; i++) { + temp->next = new Node(i, NULL); + temp = temp->next; + } + // Creating other lists for checking purposes + Node *secondList = new Node(0, NULL); // List of size 1 + Node *thirdList = NULL; // List of size 0 + + std::cout << getSize(myList) << std::endl + << getSize(secondList) << std::endl + << getSize(thirdList) << std::endl; + + return 0; +} diff --git a/probability/bayes_theorem.cpp b/probability/bayes_theorem.cpp new file mode 100644 index 000000000..d30be6c9a --- /dev/null +++ b/probability/bayes_theorem.cpp @@ -0,0 +1,30 @@ +#include + +// bayes' theorem > https://en.wikipedia.org/wiki/Bayes%27_theorem + +// bayes' theorem allows one to find P(A|B) given P(B|A) +// or P(B|A) given P(A|B) and P(A) and P(B) + +// note P(A|B) is read 'The probability of A given that the event B has occured' + +// returns P(A|B) + +double bayes_AgivenB(double BgivenA, double A, double B) { + return (BgivenA * A) / B; +} + +// returns P(B|A) + +double bayes_BgivenA(double AgivenB, double A, double B) { + return (AgivenB * B) / A; +} + +int main() { + double A = 0.01; + double B = 0.1; + double BgivenA = 0.9; + double AgivenB = bayes_AgivenB(BgivenA, A, B); + std::cout << "A given B = " << AgivenB << std::endl; + std::cout << "B given A = " << bayes_BgivenA(AgivenB, A, B) << std::endl; + return 0; +} diff --git a/probability/binomial_dist.cpp b/probability/binomial_dist.cpp new file mode 100644 index 000000000..b21a3e0fc --- /dev/null +++ b/probability/binomial_dist.cpp @@ -0,0 +1,81 @@ +#include +#include + +// the binomial distribution models the number of +// successes in a sequence of n independent events + +// n : number of trials +// p : probability of success +// x : desired successes + +// finds the expected value of a binomial distribution + +double binomial_expected(double n, double p) { + return n * p; +} + +// finds the variance of the binomial distribution + +double binomial_variance(double n, double p) { + return n * p * (1 - p); +} + +// finds the standard deviation of the binomial distribution + +double binomial_standard_deviation(double n, double p) { + return sqrt(binomial_variance(n, p)); +} + +// Computes n choose r +// n being the trials and r being the desired successes + +double nCr(double n, double r) { + double numerator = n; + double denominator = r; + + for (int i = n - 1 ; i >= ((n - r) + 1); i--) { + numerator *= i; + } + + for (int i = 1; i < r ; i++) { + denominator *= i; + } + + return numerator / denominator; +} + +// calculates the probability of exactly x successes + +double binomial_x_successes(double n, double p, double x) { + return nCr(n, x) * pow(p, x) * pow(1-p, n-x); +} + +// calculates the probability of a result within a range (inclusive, inclusive) + +double binomial_range_successes( + double n, double p, double lower_bound, double upper_bound) { + double probability = 0; + for (int i = lower_bound; i <= upper_bound; i++) { + probability += nCr(n, i) * pow(p, i) * pow(1 - p, n - i); + } + return probability; +} + +int main() { + std::cout << "expected value : " + < +#include + +// The Poisson distribution counts how many +// events occur over a set time interval +// https://en.wikipedia.org/wiki/Poisson_distribution + +// calculate the events per unit time +// e.g 5 dollars every 2 mins = 5 / 2 = 2.5 + +double poisson_rate(double events, double timeframe) { + return events / timeframe; +} + +// calculate the expected value over a time +// e.g rate of 2.5 over 10 mins = 2.5 x 10 = 25 + +double poisson_expected(double rate, double time) { + return rate * time; +} + +// find the factorial of a given number + +double fact(double x) { + double x_fact = x; + for (int i = x - 1; i > 0; i--) { + x_fact *= i; + } + + if (x_fact <= 0) { + x_fact = 1; + } + return x_fact; +} + +// find the probability of x successes in a Poisson dist + +double poisson_x_successes(double expected, double x) { + return (pow(expected, x) * exp(-expected)) / fact(x); +} + +// probability of a success in range for Poisson dist (inclusive, inclusive) + +double poisson_range_successes(double expected, double lower, double upper) { + double probability = 0; + for (int i = lower; i <= upper; i++) { + probability += poisson_x_successes(expected, i); + } + return probability; +} + +int main() { + double rate, expected; + rate = poisson_rate(3, 1); + std::cout << "Poisson rate : " << rate << std::endl; + + expected = poisson_expected(rate, 2); + std::cout << "Poisson expected : " << expected << std::endl; + + std::cout << "Poisson 0 successes : " + < -using namespace std; -int binary_search(int a[], int l, int r, int key) -{ - while (l <= r) - { - int m = l + (r - l) / 2; - if (key == a[m]) - return m; - else if (key < a[m]) - r = m - 1; - else - l = m + 1; - } - return -1; -} -int main(int argc, char const *argv[]) -{ - int n, key; - cout << "Enter size of array: "; - cin >> n; - cout << "Enter array elements: "; - int a[n]; - for (int i = 0; i < n; ++i) - { - cin >> a[i]; - } - cout << "Enter search key: "; - cin >> key; - int res = binary_search(a, 0, n - 1, key); - if (res != -1) - cout << key << " found at index " << res << endl; - else - cout << key << " not found" << endl; - return 0; -} \ No newline at end of file diff --git a/search/binary_search.cpp b/search/binary_search.cpp new file mode 100644 index 000000000..9933c9816 --- /dev/null +++ b/search/binary_search.cpp @@ -0,0 +1,34 @@ +#include +// binary_search function +int binary_search(int a[], int l, int r, int key) { + while (l <= r) { + int m = l + (r - l) / 2; + if (key == a[m]) + return m; + else if (key < a[m]) + r = m - 1; + else + l = m + 1; + } + return -1; + } +int main(int argc, char const* argv[]) { + int n, key; + std::cout << "Enter size of array: "; + std::cin >> n; + std::cout << "Enter array elements: "; + int* a = new int[n]; +// this loop use for store value in Array + for (int i = 0; i < n; i++) { + std::cin >> a[i]; + } + std::cout << "Enter search key: "; + std::cin >> key; +// this is use for find value in given array + int res = binary_search(a, 0, n - 1, key); + if (res != -1) + std::cout << key << " found at index " << res << std::endl; + else + std::cout << key << " not found" << std::endl; + return 0; +} diff --git a/search/jump_search.cpp b/search/jump_search.cpp new file mode 100644 index 000000000..0ee7e4e00 --- /dev/null +++ b/search/jump_search.cpp @@ -0,0 +1,54 @@ +// C++ program to implement Jump Search + +#include +using namespace std; + +int jumpSearch(int arr[], int x, int n) +{ + // Finding block size to be jumped + int step = sqrt(n); + + // Finding the block where element is + // present (if it is present) + int prev = 0; + while (arr[min(step, n)-1] < x) + { + prev = step; + step += sqrt(n); + if (prev >= n) + return -1; + } + + // Doing a linear search for x in block + // beginning with prev. + while (arr[prev] < x) + { + prev++; + + // If we reached next block or end of + // array, element is not present. + if (prev == min(step, n)) + return -1; + } + // If element is found + if (arr[prev] == x) + return prev; + + return -1; +} + +// Driver program to test function +int main() +{ + int arr[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, + 34, 55, 89, 144, 233, 377, 610 }; + int x = 55; + int n = sizeof(arr) / sizeof(arr[0]); + + // Find the index of 'x' using Jump Search + int index = jumpSearch(arr, x, n); + + // Print the index where 'x' is located + cout << "\nNumber " << x << " is at index " << index; + return 0; +} diff --git a/sorting/swap_sort.cpp b/sorting/swap_sort.cpp new file mode 100644 index 000000000..a4ab1e57b --- /dev/null +++ b/sorting/swap_sort.cpp @@ -0,0 +1,66 @@ +// C++ program to find minimum number of swaps required to sort an array +#include +#include +#include +#include + +// Function returns the minimum number of swaps +// required to sort the array +int minSwaps(int arr[], int n) { + // Create an array of pairs where first + // element is array element and second element + // is position of first element + std::pair arrPos[n]; + for (int i = 0; i < n; i++) { + arrPos[i].first = arr[i]; + arrPos[i].second = i; + } + + // Sort the array by array element values to + // get right position of every element as second + // element of pair. + std::sort(arrPos, arrPos + n); + + // To keep track of visited elements. Initialize + // all elements as not visited or false. + std::vector vis(n, false); + + // Initialize result + int ans = 0; + + // Traverse array elements + for (int i = 0; i < n; i++) { + // already swapped and corrected or + // already present at correct pos + if (vis[i] || arrPos[i].second == i) + continue; + + // find out the number of node in + // this cycle and add in ans + int cycle_size = 0; + int j = i; + while (!vis[j]) { + vis[j] = 1; + + // move to next node + j = arrPos[j].second; + cycle_size++; + } + + // Update answer by adding current cycle. + if (cycle_size > 0) { + ans += (cycle_size - 1); + } + } + + // Return result + return ans; +} + +// program to test +int main() { + int arr[] = {6, 7, 8, 1, 2, 3, 9, 12}; + int n = (sizeof(arr) / sizeof(int)); + std::cout << minSwaps(arr, n); + return 0; +} diff --git a/strings/rabin_karp.cpp b/strings/rabin_karp.cpp new file mode 100644 index 000000000..62e3691c1 --- /dev/null +++ b/strings/rabin_karp.cpp @@ -0,0 +1,78 @@ +/* + * file name : rabin_karp.cpp + * author : Amit Kumar + * Copyright : 2020 , Amit Kumar + * version : 1.0 + */ +#include +#include +#include +#include + +using std::string; +using std::pow; + +#define PRIME 5 + +int64_t create_hash(string s , int n) { + int64_t result = 0; + for ( int i = 0; i < n; ++i ) { + result += (int64_t)(s[i] * (int64_t)pow(PRIME , i)); + } + return result; +} + +int64_t recalculate_hash(string s , int old_index , + int new_index , int64_t old_hash , int patLength) { + int64_t new_hash = old_hash - s[old_index]; + new_hash /= PRIME; + new_hash += (int64_t)(s[new_index]*(int64_t)pow(PRIME, patLength-1)); + return new_hash; +} + +bool check_if_equal(string str1 , string str2 , + int start1 , int end1 , + int start2 , int end2) { + if (end1-start1 != end2-start2) { + return false; + } + while (start1 <= end1 && start2 <= end2) { + if (str1[start1] != str2[start2]) { + return false; + } + start1++; + start2++; + } + return true; +} + +/* + * @description : search pattern in the given text + * @param : string str + * @param : string pat + * @return index of first occurrence of pattern or -1 if pattern not found + */ + +int rabin_karp(const string &str , const string& pat) { + int64_t pat_hash = create_hash(pat , pat.size()); + int64_t str_hash = create_hash(str , pat.size()); + for (int i=0; i <= str.size()-pat.size(); ++i) { + if (pat_hash == str_hash && + check_if_equal(str , pat , i , i+pat.size()-1 , 0 , pat.size()-1)) { + return i; + } + if (i < str.size()-pat.size()) { + str_hash = + recalculate_hash(str, i, i+pat.size(), str_hash, pat.size()); + } + } + return -1; // return -1 if given pattern not found +} + +int main(void) { + assert(rabin_karp("helloWorld", "world") == -1); + assert(rabin_karp("helloWorld", "World") == 5); + assert(rabin_karp("this_is_c++" , "c++") == 8); + assert(rabin_karp("happy_coding", "happy") == 0); + return 0; +}