mirror of
https://github.com/TheAlgorithms/C-Plus-Plus.git
synced 2026-04-01 17:52:40 +08:00
Merge branch 'master' into cstdint
This commit is contained in:
@@ -119,6 +119,7 @@
|
||||
* [Searching Of Element In Dynamic Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/searching_of_element_in_dynamic_array.cpp)
|
||||
* [Shortest Common Supersequence](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/shortest_common_supersequence.cpp)
|
||||
* [Subset Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/subset_sum.cpp)
|
||||
* [Trapped Rainwater](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/trapped_rainwater.cpp)
|
||||
* [Tree Height](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/tree_height.cpp)
|
||||
* [Word Break](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/dynamic_programming/word_break.cpp)
|
||||
|
||||
@@ -161,7 +162,7 @@
|
||||
* [Boruvkas Minimum Spanning Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/boruvkas_minimum_spanning_tree.cpp)
|
||||
* [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/dijkstra.cpp)
|
||||
* [Huffman](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/huffman.cpp)
|
||||
* [Jumpgame](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/jumpgame.cpp)
|
||||
* [Jump Game](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/jump_game.cpp)
|
||||
* [Knapsack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/knapsack.cpp)
|
||||
* [Kruskals Minimum Spanning Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/kruskals_minimum_spanning_tree.cpp)
|
||||
* [Prims Minimum Spanning Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/greedy_algorithms/prims_minimum_spanning_tree.cpp)
|
||||
|
||||
@@ -1,62 +1,179 @@
|
||||
#include <iostream>
|
||||
#include <cassert> /// For std::assert
|
||||
#include <iostream> /// For std::cout
|
||||
#include <memory> /// For std::unique_ptr
|
||||
#include <stdexcept> /// For std::out_of_range
|
||||
|
||||
int *stack;
|
||||
int stack_idx = 0, stack_size;
|
||||
/**
|
||||
* @namespace
|
||||
* @brief data_structures
|
||||
*/
|
||||
namespace data_structures {
|
||||
/**
|
||||
* @brief Class representation of a stack
|
||||
* @tparam T The type of the elements in the stack
|
||||
*/
|
||||
template <typename T>
|
||||
class Stack {
|
||||
private:
|
||||
std::unique_ptr<T[]> stack; ///< Smart pointer to the stack array
|
||||
int stackSize; ///< Maximum size of the stack
|
||||
int stackIndex; ///< Index pointing to the top element of the stack
|
||||
|
||||
void push(int x) {
|
||||
if (stack_idx == stack_size) {
|
||||
std::cout << "\nOverflow";
|
||||
} else {
|
||||
stack[stack_idx++] = x;
|
||||
}
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new Stack object
|
||||
*
|
||||
* @param size Maximum size of the stack
|
||||
*/
|
||||
Stack(int size) : stackSize(size), stackIndex(-1), stack(new T[size]) {}
|
||||
|
||||
void pop() {
|
||||
if (stack_idx == 0) {
|
||||
std::cout << "\nUnderflow";
|
||||
} else {
|
||||
std::cout << "\n" << stack[--stack_idx] << " deleted";
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Checks if the stack is full
|
||||
*
|
||||
* @return true if the stack is full, false otherwise
|
||||
*/
|
||||
bool full() const { return stackIndex == stackSize - 1; }
|
||||
|
||||
void show() {
|
||||
for (int i = 0; i < stack_idx; i++) {
|
||||
std::cout << stack[i] << "\n";
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Checks if the stack is empty
|
||||
* @return true if the stack is empty, false otherwise
|
||||
*/
|
||||
bool empty() const { return stackIndex == -1; }
|
||||
|
||||
void topmost() { std::cout << "\nTopmost element: " << stack[stack_idx - 1]; }
|
||||
void bottom() { std::cout << "\nBottom element: " << stack[0]; } // If we need access to first element without using pop command
|
||||
int main() {
|
||||
std::cout << "\nEnter stack_size of stack : ";
|
||||
std::cin >> stack_size;
|
||||
stack = new int[stack_size];
|
||||
int ch, x;
|
||||
do {
|
||||
std::cout << "\n0. Exit";
|
||||
std::cout << "\n1. Push";
|
||||
std::cout << "\n2. Pop";
|
||||
std::cout << "\n3. Print";
|
||||
std::cout << "\n4. Print topmost element:";
|
||||
std::cout << "\n5. Print Bottom element:";
|
||||
std::cout << "\nEnter Your Choice : ";
|
||||
std::cin >> ch;
|
||||
if (ch == 1) {
|
||||
std::cout << "\nInsert : ";
|
||||
std::cin >> x;
|
||||
push(x);
|
||||
} else if (ch == 2) {
|
||||
pop();
|
||||
} else if (ch == 3) {
|
||||
show();
|
||||
} else if (ch == 4) {
|
||||
topmost();
|
||||
} else if(ch == 5) {
|
||||
bottom();
|
||||
/**
|
||||
* @brief Pushes an element onto the stack
|
||||
*
|
||||
* @param element Element to push onto the stack
|
||||
*/
|
||||
void push(T element) {
|
||||
if (full()) {
|
||||
throw std::out_of_range("Stack overflow");
|
||||
} else {
|
||||
stack[++stackIndex] = element;
|
||||
}
|
||||
} while (ch != 0);
|
||||
}
|
||||
|
||||
delete[] stack;
|
||||
/**
|
||||
* @brief Pops an element from the stack
|
||||
*
|
||||
* @return The popped element
|
||||
* @throws std::out_of_range if the stack is empty
|
||||
*/
|
||||
T pop() {
|
||||
if (empty()) {
|
||||
throw std::out_of_range("Stack underflow");
|
||||
}
|
||||
return stack[stackIndex--];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays all elements in the stack
|
||||
*/
|
||||
void show() const {
|
||||
for (int i = 0; i <= stackIndex; i++) {
|
||||
std::cout << stack[i] << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays the topmost element of the stack
|
||||
*
|
||||
* @return The topmost element of the stack
|
||||
* @throws std::out_of_range if the stack is empty
|
||||
*/
|
||||
T topmost() const {
|
||||
if (empty()) {
|
||||
throw std::out_of_range("Stack underflow");
|
||||
}
|
||||
return stack[stackIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays the bottom element of the stack
|
||||
*
|
||||
* @return The bottom element of the stack
|
||||
* @throws std::out_of_range if the stack is empty
|
||||
*/
|
||||
T bottom() const {
|
||||
if (empty()) {
|
||||
throw std::out_of_range("Stack underflow");
|
||||
}
|
||||
return stack[0];
|
||||
}
|
||||
};
|
||||
} // namespace data_structures
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @returns void
|
||||
*/
|
||||
static void test() {
|
||||
data_structures::Stack<int> stack(5);
|
||||
|
||||
// Test empty and full operations
|
||||
assert(stack.empty());
|
||||
assert(!stack.full());
|
||||
|
||||
// Test pushing elements and checking topmost
|
||||
stack.push(10);
|
||||
assert(stack.topmost() == 10);
|
||||
|
||||
stack.push(20);
|
||||
assert(stack.topmost() == 20);
|
||||
|
||||
stack.push(30);
|
||||
stack.push(40);
|
||||
stack.push(50);
|
||||
assert(stack.full());
|
||||
|
||||
// Test stack overflow
|
||||
try {
|
||||
stack.push(60);
|
||||
} catch (const std::out_of_range& e) {
|
||||
assert(std::string(e.what()) == "Stack overflow");
|
||||
}
|
||||
|
||||
// Test popping elements
|
||||
assert(stack.pop() == 50);
|
||||
assert(stack.pop() == 40);
|
||||
assert(stack.pop() == 30);
|
||||
|
||||
// Check topmost and bottom elements
|
||||
assert(stack.topmost() == 20);
|
||||
assert(stack.bottom() == 10);
|
||||
|
||||
assert(stack.pop() == 20);
|
||||
assert(stack.pop() == 10);
|
||||
|
||||
assert(stack.empty());
|
||||
assert(!stack.full());
|
||||
|
||||
// Test stack underflow
|
||||
try {
|
||||
stack.pop();
|
||||
} catch (const std::out_of_range& e) {
|
||||
assert(std::string(e.what()) == "Stack underflow");
|
||||
}
|
||||
|
||||
try {
|
||||
stack.topmost();
|
||||
} catch (const std::out_of_range& e) {
|
||||
assert(std::string(e.what()) == "Stack underflow");
|
||||
}
|
||||
|
||||
try {
|
||||
stack.bottom();
|
||||
} catch (const std::out_of_range& e) {
|
||||
assert(std::string(e.what()) == "Stack underflow");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main() {
|
||||
test(); // run self-test implementations
|
||||
std::cout << "All tests passed!" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -180,6 +180,25 @@ std::vector<int64_t> BinaryTree::inOrderIterative(Node *root) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void deleteAll(Node *root) {
|
||||
if (root) {
|
||||
std::stack<Node *> stack;
|
||||
stack.push(root);
|
||||
|
||||
while (!stack.empty()) {
|
||||
const Node *current = stack.top();
|
||||
stack.pop();
|
||||
|
||||
if (current->right) {
|
||||
stack.push(current->right);
|
||||
}
|
||||
if (current->left) {
|
||||
stack.push(current->left);
|
||||
}
|
||||
delete current;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace iterative_tree_traversals
|
||||
} // namespace others
|
||||
|
||||
@@ -396,5 +415,7 @@ int main() {
|
||||
test6(binaryTree, root); // run inorder-iterative test on negative values
|
||||
std::cout << "\nIn-order test on-negative value Passed!" << std::endl;
|
||||
|
||||
deleteAll(root);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// C++ program to perform TimSort.
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
|
||||
const int RUN = 32;
|
||||
|
||||
@@ -8,7 +10,7 @@ const int RUN = 32;
|
||||
// atmost RUN
|
||||
void insertionSort(int arr[], int left, int right) {
|
||||
for (int i = left + 1; i <= right; i++) {
|
||||
int temp = arr[i];
|
||||
const int temp = arr[i];
|
||||
int j = i - 1;
|
||||
while (arr[j] > temp && j >= left) {
|
||||
arr[j + 1] = arr[j];
|
||||
@@ -21,7 +23,7 @@ void insertionSort(int arr[], int left, int right) {
|
||||
// merge function merges the sorted runs
|
||||
void merge(int arr[], int l, int m, int r) {
|
||||
// original array is broken in two parts, left and right array
|
||||
int len1 = m - l + 1, len2 = r - m;
|
||||
const int len1 = m - l + 1, len2 = r - m;
|
||||
int *left = new int[len1], *right = new int[len2];
|
||||
for (int i = 0; i < len1; i++) left[i] = arr[l + i];
|
||||
for (int i = 0; i < len2; i++) right[i] = arr[m + 1 + i];
|
||||
@@ -74,8 +76,8 @@ void timSort(int arr[], int n) {
|
||||
for (int left = 0; left < n; left += 2 * size) {
|
||||
// find ending point of left sub array
|
||||
// mid+1 is starting point of right sub array
|
||||
int mid = left + size - 1;
|
||||
int right = std::min((left + 2 * size - 1), (n - 1));
|
||||
const int mid = std::min((left + size - 1), (n - 1));
|
||||
const int right = std::min((left + 2 * size - 1), (n - 1));
|
||||
|
||||
// merge sub array arr[left.....mid] & arr[mid+1....right]
|
||||
merge(arr, left, mid, right);
|
||||
@@ -89,10 +91,29 @@ void printArray(int arr[], int n) {
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief self-test implementation
|
||||
* @returns void
|
||||
*/
|
||||
void tests() {
|
||||
// Case: array of length 65
|
||||
constexpr int N = 65;
|
||||
int arr[N];
|
||||
|
||||
std::iota(arr, arr + N, 0);
|
||||
std::reverse(arr, arr + N);
|
||||
assert(!std::is_sorted(arr, arr + N));
|
||||
|
||||
timSort(arr, N);
|
||||
assert(std::is_sorted(arr, arr + N));
|
||||
}
|
||||
|
||||
// Driver program to test above function
|
||||
int main() {
|
||||
tests(); // run self test implementations
|
||||
|
||||
int arr[] = {5, 21, 7, 23, 19};
|
||||
int n = sizeof(arr) / sizeof(arr[0]);
|
||||
const int n = sizeof(arr) / sizeof(arr[0]);
|
||||
printf("Given Array is\n");
|
||||
printArray(arr, n);
|
||||
|
||||
|
||||
@@ -1,95 +1,98 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief The [Knuth-Morris-Pratt
|
||||
* @file
|
||||
* @brief The [Knuth-Morris-Pratt
|
||||
* Algorithm](https://en.wikipedia.org/wiki/Knuth–Morris–Pratt_algorithm) for
|
||||
* finding a pattern within a piece of text with complexity O(n + m)
|
||||
*
|
||||
* @details
|
||||
* 1. Preprocess pattern to identify any suffixes that are identical to
|
||||
* prefixes. This tells us where to continue from if we get a mismatch between a
|
||||
* character in our pattern and the text.
|
||||
* 2. Step through the text one character at a time and compare it to a
|
||||
* character in the pattern updating our location within the pattern if
|
||||
* necessary
|
||||
* @author [Yancey](https://github.com/Yancey2023)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#ifdef _MSC_VER
|
||||
#include <string> // use this for MS Visual C++
|
||||
#else
|
||||
#include <cstring>
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <cassert> /// for assert
|
||||
#include <iostream> /// for IO operations
|
||||
#include <string> /// for std::string
|
||||
#include <vector> /// for std::vector
|
||||
|
||||
/** \namespace string_search
|
||||
* \brief String search algorithms
|
||||
/**
|
||||
* @namespace string_search
|
||||
* @brief String search algorithms
|
||||
*/
|
||||
namespace string_search {
|
||||
/**
|
||||
* Generate the partial match table aka failure function for a pattern to
|
||||
* @brief Generate the partial match table aka failure function for a pattern to
|
||||
* search.
|
||||
* \param[in] pattern text for which to create the partial match table
|
||||
* \returns the partial match table as a vector array
|
||||
* @param pattern text for which to create the partial match table
|
||||
* @returns the partial match table as a vector array
|
||||
*/
|
||||
std::vector<int> getFailureArray(const std::string &pattern) {
|
||||
int pattern_length = pattern.size();
|
||||
std::vector<int> failure(pattern_length + 1);
|
||||
failure[0] = -1;
|
||||
int j = -1;
|
||||
|
||||
std::vector<size_t> getFailureArray(const std::string &pattern) {
|
||||
size_t pattern_length = pattern.size();
|
||||
std::vector<size_t> failure(pattern_length + 1);
|
||||
failure[0] = std::string::npos;
|
||||
size_t j = std::string::npos;
|
||||
for (int i = 0; i < pattern_length; i++) {
|
||||
while (j != -1 && pattern[j] != pattern[i]) {
|
||||
while (j != std::string::npos && pattern[j] != pattern[i]) {
|
||||
j = failure[j];
|
||||
}
|
||||
j++;
|
||||
failure[i + 1] = j;
|
||||
failure[i + 1] = ++j;
|
||||
}
|
||||
return failure;
|
||||
}
|
||||
|
||||
/**
|
||||
* KMP algorithm to find a pattern in a text
|
||||
* \param[in] pattern string pattern to search
|
||||
* \param[in] text text in which to search
|
||||
* \returns `true` if pattern was found
|
||||
* \returns `false` if pattern was not found
|
||||
* @brief KMP algorithm to find a pattern in a text
|
||||
* @param pattern string pattern to search
|
||||
* @param text text in which to search
|
||||
* @returns the starting index of the pattern if found
|
||||
* @returns `std::string::npos` if not found
|
||||
*/
|
||||
bool kmp(const std::string &pattern, const std::string &text) {
|
||||
int text_length = text.size(), pattern_length = pattern.size();
|
||||
std::vector<int> failure = getFailureArray(pattern);
|
||||
|
||||
int k = 0;
|
||||
for (int j = 0; j < text_length; j++) {
|
||||
while (k != -1 && pattern[k] != text[j]) {
|
||||
size_t kmp(const std::string &pattern, const std::string &text) {
|
||||
if (pattern.empty()) {
|
||||
return 0;
|
||||
}
|
||||
std::vector<size_t> failure = getFailureArray(pattern);
|
||||
size_t text_length = text.size();
|
||||
size_t pattern_length = pattern.size();
|
||||
size_t k = 0;
|
||||
for (size_t j = 0; j < text_length; j++) {
|
||||
while (k != std::string::npos && pattern[k] != text[j]) {
|
||||
k = failure[k];
|
||||
}
|
||||
k++;
|
||||
if (k == pattern_length)
|
||||
return true;
|
||||
if (++k == pattern_length) {
|
||||
return j - k + 1;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return std::string::npos;
|
||||
}
|
||||
} // namespace string_search
|
||||
|
||||
using string_search::kmp;
|
||||
|
||||
/** Main function */
|
||||
/**
|
||||
* @brief self-test implementations
|
||||
* @returns void
|
||||
*/
|
||||
static void tests() {
|
||||
assert(kmp("abc1abc12l", "alskfjaldsabc1abc1abc12k2") == std::string::npos);
|
||||
assert(kmp("bca", "abcabc") == 1);
|
||||
assert(kmp("World", "helloWorld") == 5);
|
||||
assert(kmp("c++", "his_is_c++") == 7);
|
||||
assert(kmp("happy", "happy_coding") == 0);
|
||||
assert(kmp("", "pattern is empty") == 0);
|
||||
|
||||
// this lets the user know that the tests have passed
|
||||
std::cout << "All KMP algorithm tests have successfully passed!\n";
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Main function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main() {
|
||||
std::string text = "alskfjaldsabc1abc1abc12k23adsfabcabc";
|
||||
std::string pattern = "abc1abc12l";
|
||||
|
||||
if (kmp(pattern, text) == true) {
|
||||
std::cout << "Found" << std::endl;
|
||||
} else {
|
||||
std::cout << "Not Found" << std::endl;
|
||||
}
|
||||
|
||||
text = "abcabc";
|
||||
pattern = "bca";
|
||||
if (kmp(pattern, text) == true) {
|
||||
std::cout << "Found" << std::endl;
|
||||
} else {
|
||||
std::cout << "Not Found" << std::endl;
|
||||
}
|
||||
|
||||
tests();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user