mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
Merge branch 'master' into master
This commit is contained in:
commit
20274510c4
@ -32,7 +32,7 @@ You can add new algorithms or data structures which are **not present in the rep
|
||||
- Please use the directory structure of the repository.
|
||||
- Make sure the file extensions should be `*.hpp`, `*.h` or `*.cpp`.
|
||||
- Don't use **`bits/stdc++.h`** because this is quite Linux-specific and slows down the compilation process.
|
||||
- Organize your code using **`struct`**, **`class`**, and/or **`namespace`** keywords
|
||||
- Organize your code using **`struct`**, **`class`**, and/or **`namespace`** keywords.
|
||||
- If an implementation of the algorithm already exists, please refer to the [file-name section below](#new-file-name-guidelines).
|
||||
- You can suggest reasonable changes to existing algorithms.
|
||||
- Strictly use snake_case (underscore_separated) in filenames.
|
||||
|
@ -19,6 +19,7 @@
|
||||
* [Hamming Distance](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/bit_manipulation/hamming_distance.cpp)
|
||||
|
||||
## Ciphers
|
||||
* [Atbash Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/atbash_cipher.cpp)
|
||||
* [Base64 Encoding](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/base64_encoding.cpp)
|
||||
* [Caesar Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/caesar_cipher.cpp)
|
||||
* [Elliptic Curve Key Exchange](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/elliptic_curve_key_exchange.cpp)
|
||||
@ -242,6 +243,7 @@
|
||||
* [Inorder Successor Of Bst](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/inorder_successor_of_bst.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_a_linked_list_using_recusion.cpp)
|
||||
* [Reverse Binary Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/reverse_binary_tree.cpp)
|
||||
* [Selectionsortlinkedlist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/selectionsortlinkedlist.cpp)
|
||||
* [Trie Multiple Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/trie_multiple_search.cpp)
|
||||
* [Union Of 2 Arrays](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/operations_on_datastructures/union_of_2_arrays.cpp)
|
||||
|
83
ciphers/atbash_cipher.cpp
Normal file
83
ciphers/atbash_cipher.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief [Atbash Cipher](https://en.wikipedia.org/wiki/Atbash) implementation
|
||||
* @details The Atbash cipher is a subsitution cipher where the letters of the
|
||||
* alphabet are in reverse. For example, A is replaced with Z, B is replaced
|
||||
* with Y, etc.
|
||||
*
|
||||
* ### Algorithm
|
||||
* The algorithm takes a string, and looks up the corresponding reversed letter
|
||||
* for each letter in the word and replaces it. Spaces are ignored and case is
|
||||
* preserved.
|
||||
*
|
||||
* @author [Focusucof](https://github.com/Focusucof)
|
||||
*/
|
||||
#include <cassert> /// for assert
|
||||
#include <iostream> /// for IO operations
|
||||
#include <map> /// for std::map
|
||||
#include <string> /// for std::string
|
||||
|
||||
/** \namespace ciphers
|
||||
* \brief Algorithms for encryption and decryption
|
||||
*/
|
||||
namespace ciphers {
|
||||
/** \namespace atbash
|
||||
* \brief Functions for the [Atbash Cipher](https://en.wikipedia.org/wiki/Atbash) implementation
|
||||
*/
|
||||
namespace atbash {
|
||||
std::map<char, char> atbash_cipher_map = {
|
||||
{'a', 'z'}, {'b', 'y'}, {'c', 'x'}, {'d', 'w'}, {'e', 'v'}, {'f', 'u'},
|
||||
{'g', 't'}, {'h', 's'}, {'i', 'r'}, {'j', 'q'}, {'k', 'p'}, {'l', 'o'},
|
||||
{'m', 'n'}, {'n', 'm'}, {'o', 'l'}, {'p', 'k'}, {'q', 'j'}, {'r', 'i'},
|
||||
{'s', 'h'}, {'t', 'g'}, {'u', 'f'}, {'v', 'e'}, {'w', 'd'}, {'x', 'c'},
|
||||
{'y', 'b'}, {'z', 'a'}, {'A', 'Z'}, {'B', 'Y'}, {'C', 'X'}, {'D', 'W'},
|
||||
{'E', 'V'}, {'F', 'U'}, {'G', 'T'}, {'H', 'S'}, {'I', 'R'}, {'J', 'Q'},
|
||||
{'K', 'P'}, {'L', 'O'}, {'M', 'N'}, {'N', 'M'}, {'O', 'L'}, {'P', 'K'},
|
||||
{'Q', 'J'}, {'R', 'I'}, {'S', 'H'}, {'T', 'G'}, {'U', 'F'}, {'V', 'E'},
|
||||
{'W', 'D'}, {'X', 'C'}, {'Y', 'B'}, {'Z', 'A'}, {' ', ' '}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief atbash cipher encryption and decryption
|
||||
* @param text Plaintext to be encrypted
|
||||
* @returns encoded or decoded string
|
||||
*/
|
||||
std::string atbash_cipher(std::string text) {
|
||||
std::string result;
|
||||
for (char letter : text) {
|
||||
result += atbash_cipher_map[letter];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace atbash
|
||||
} // namespace ciphers
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @returns void
|
||||
*/
|
||||
static void test() {
|
||||
// 1st test
|
||||
std::string text = "Hello World";
|
||||
std::string expected = "Svool Dliow";
|
||||
std::string encrypted_text = ciphers::atbash::atbash_cipher(text);
|
||||
std::string decrypted_text = ciphers::atbash::atbash_cipher(encrypted_text);
|
||||
assert(expected == encrypted_text);
|
||||
assert(text == decrypted_text);
|
||||
std::cout << "Original text: " << text << std::endl;
|
||||
std::cout << ", Expected text: " << expected << std::endl;
|
||||
std::cout << ", Encrypted text: " << encrypted_text << std::endl;
|
||||
std::cout << ", Decrypted text: " << decrypted_text << std::endl;
|
||||
std::cout << "\nAll tests have successfully passed!\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main() {
|
||||
test(); // run self-test implementations
|
||||
return 0;
|
||||
}
|
255
operations_on_datastructures/reverse_binary_tree.cpp
Normal file
255
operations_on_datastructures/reverse_binary_tree.cpp
Normal file
@ -0,0 +1,255 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation for the [Reversing a Binary
|
||||
* Tree](https://www.geeksforgeeks.org/reverse-tree-path/) recursively
|
||||
* algorithm.
|
||||
* @details A binary tree can be reversed by swapping the left and
|
||||
* right child of a node at each node, starting from the root, and
|
||||
* cascading below. This solution aims to provide an implementation of
|
||||
* a recursive reversal of a binary tree.
|
||||
* @author [Alvin](https://github.com/polarvoid)
|
||||
*/
|
||||
|
||||
#include <cassert> /// For assert
|
||||
#include <iostream> /// For IO operations
|
||||
#include <queue> /// For std::queue
|
||||
#include <vector> /// For std::vector
|
||||
|
||||
/**
|
||||
* @namespace operations_on_datastructures
|
||||
* @brief Operations on Data Structures
|
||||
*/
|
||||
namespace operations_on_datastructures {
|
||||
|
||||
/**
|
||||
* @namespace reverse_binary_tree
|
||||
* @brief Functions for the [Reverse a Binary
|
||||
* Tree](https://www.geeksforgeeks.org/reverse-tree-path/) implementation
|
||||
*/
|
||||
namespace reverse_binary_tree {
|
||||
|
||||
/**
|
||||
* @brief A Node struct that represents a single node in a Binary Tree
|
||||
*/
|
||||
struct Node {
|
||||
int64_t data; ///< The value of the Node
|
||||
Node* left; ///< The Node's left child
|
||||
Node* right; ///< The Node's right child
|
||||
/**
|
||||
* @brief Creates a new Node with some initial data
|
||||
*/
|
||||
explicit Node(int64_t _data) {
|
||||
data = _data; ///< Set value of Node data
|
||||
left = nullptr; ///< Initialize left child to NULL
|
||||
right = nullptr; ///< Initialize right child to NULL
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A Binary Tree class that implements a Binary Search Tree
|
||||
*(BST) by default.
|
||||
*/
|
||||
class BinaryTree {
|
||||
private:
|
||||
Node* root; ///< Pointer to root node of Binary Tree
|
||||
/**
|
||||
* @brief inserts a node in the Binary Tree, with the behaviouur of
|
||||
* a Binary Search Tree.
|
||||
* @details Nodes with smaller values are inserted in the left
|
||||
* subtree, and Nodes with larger values are inserted into the
|
||||
* right subtree recursively. Time Complexity: O(log(n))
|
||||
* @param data The data/value of the Node to be inserted
|
||||
* @param pivot A pointer to the root node of the (sub)tree
|
||||
* @returns Node pointer to the root
|
||||
*/
|
||||
Node* insert(int64_t data, Node* pivot) {
|
||||
if (pivot == nullptr) {
|
||||
return new Node(data); ///< Create new node
|
||||
}
|
||||
if (data <= pivot->data) {
|
||||
pivot->left =
|
||||
insert(data, pivot->left); ///< Insert Node to the left
|
||||
} else {
|
||||
pivot->right =
|
||||
insert(data, pivot->right); ///< Insert node to the right
|
||||
}
|
||||
return pivot;
|
||||
}
|
||||
/**
|
||||
* @brief Reverses a Binary Tree recursively by swapping the left and
|
||||
* right subtrees and their children.
|
||||
* @param pivot A reference to the root of the (sub)tree
|
||||
* @returns Node pointer to root node
|
||||
*/
|
||||
Node* reverseBinaryTree(Node* pivot) {
|
||||
if (pivot == nullptr) {
|
||||
return pivot; ///< Base case
|
||||
}
|
||||
Node* temp = pivot->left; ///< pointer to the left subtree
|
||||
pivot->left = reverseBinaryTree(pivot->right); ///< Swap
|
||||
pivot->right = reverseBinaryTree(temp); ///< Swap
|
||||
return pivot;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a BinaryTree with a root pointing to NULL.
|
||||
*/
|
||||
BinaryTree() { root = nullptr; }
|
||||
/**
|
||||
* @brief Creates a BinaryTree with a root with an initial value.
|
||||
*/
|
||||
explicit BinaryTree(int64_t data) { root = new Node(data); }
|
||||
/**
|
||||
* @brief Adds a new Node to the Binary Tree
|
||||
*/
|
||||
void add(int64_t data) { root = insert(data, root); }
|
||||
/**
|
||||
* Reverses the Binary Tree
|
||||
*/
|
||||
void reverse() { root = reverseBinaryTree(root); }
|
||||
/**
|
||||
* @brief Level order traversal of a tree consists of visiting its
|
||||
* elements, top to bottom, left to right. This function performs
|
||||
* level order traversal and returns the node datas as a vector.
|
||||
* @details The function uses a queue to append and remove elements
|
||||
* as they are visited, and then adds their children, if any. This
|
||||
* ensures that the elements are visited layer-by-layer, starting
|
||||
* from the root of the Tree.
|
||||
* @returns vector<int64_t> of nodes of the tree.
|
||||
*/
|
||||
std::vector<int64_t> get_level_order() {
|
||||
std::vector<int64_t> data; ///< Result vector of int
|
||||
if (root == nullptr) {
|
||||
return data; ///< Return empty vector if root is Invalid
|
||||
}
|
||||
std::queue<Node*> nodes; ///< Queue of the nodes in the tree
|
||||
nodes.push(root); ///< Insert root into the queue
|
||||
while (!nodes.empty()) {
|
||||
Node* temp = nodes.front(); ///< Copy the first element
|
||||
data.push_back(temp->data); ///< Add the element to the data
|
||||
nodes.pop(); ///< Remove element
|
||||
if (temp->left != nullptr) {
|
||||
nodes.push(temp->left); ///< Insert left node
|
||||
}
|
||||
if (temp->right != nullptr) {
|
||||
nodes.push(temp->right); ///< Insert right node
|
||||
}
|
||||
} /// Add nodes while Tree is not empty
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* @brief Prints all of the elements in the tree to stdout
|
||||
* level-by-level, using the get_level_order() function.
|
||||
* @returns void
|
||||
*/
|
||||
void print() {
|
||||
for (int i : get_level_order()) {
|
||||
std::cout << i << " "; /// Print each element in the tree
|
||||
}
|
||||
std::cout << "\n"; /// Print newline
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace reverse_binary_tree
|
||||
} // namespace operations_on_datastructures
|
||||
|
||||
/**
|
||||
* @namespace tests
|
||||
* @brief Testcases to check Reversal of Binary Tree.
|
||||
*/
|
||||
namespace tests {
|
||||
using operations_on_datastructures::reverse_binary_tree::
|
||||
BinaryTree; ///< Use the BinaryTree
|
||||
/**
|
||||
* @brief A Test to check an edge case (single element reversal)
|
||||
*/
|
||||
void test1() {
|
||||
BinaryTree bst;
|
||||
std::vector<int64_t> pre_reversal, post_reversal;
|
||||
std::cout << "TEST CASE 1\n";
|
||||
std::cout << "Initializing tree with a single element (5)\n";
|
||||
bst.add(5);
|
||||
pre_reversal = bst.get_level_order();
|
||||
std::cout << "Before reversal: ";
|
||||
bst.print();
|
||||
std::cout << "After reversal: ";
|
||||
bst.reverse();
|
||||
post_reversal = bst.get_level_order();
|
||||
assert(pre_reversal.size() ==
|
||||
post_reversal.size()); ///< Check for equal sizes
|
||||
assert(pre_reversal.size() ==
|
||||
1); ///< Ensure that there is only one element
|
||||
assert(pre_reversal[0] ==
|
||||
post_reversal[0]); ///< Check if both elements are same
|
||||
bst.print();
|
||||
std::cout << "TEST PASSED!\n\n";
|
||||
}
|
||||
/**
|
||||
* @brief A Test to check an edge case (NULL root element)
|
||||
*/
|
||||
void test2() {
|
||||
BinaryTree bst;
|
||||
std::vector<int64_t> pre_reversal, post_reversal;
|
||||
std::cout << "TEST CASE 2\n";
|
||||
std::cout << "Creating empty tree (root points to NULL)\n";
|
||||
pre_reversal = bst.get_level_order();
|
||||
std::cout << "Before reversal: ";
|
||||
bst.print();
|
||||
std::cout << "After reversal: ";
|
||||
bst.reverse();
|
||||
post_reversal = bst.get_level_order();
|
||||
assert(pre_reversal.size() ==
|
||||
post_reversal.size()); ///< Check for equal sizes
|
||||
assert(pre_reversal.size() ==
|
||||
0); ///< Ensure that there is only one element
|
||||
bst.print();
|
||||
std::cout << "TEST PASSED!\n\n";
|
||||
}
|
||||
/**
|
||||
* @brief A Test to check correct reversal of a Binary Tree
|
||||
*/
|
||||
void test3() {
|
||||
BinaryTree bst;
|
||||
std::vector<int64_t> pre_reversal, post_reversal;
|
||||
std::vector<int64_t> pre_res = {4, 3, 6, 2, 5, 7, 1};
|
||||
std::vector<int64_t> post_res = {4, 6, 3, 7, 5, 2, 1};
|
||||
std::cout << "TEST CASE 3\n";
|
||||
std::cout << "Creating tree with elements (4, 6, 3, 2, 5, 7, 1)\n";
|
||||
bst.add(4);
|
||||
bst.add(6);
|
||||
bst.add(3);
|
||||
bst.add(2);
|
||||
bst.add(5);
|
||||
bst.add(7);
|
||||
bst.add(1);
|
||||
pre_reversal = bst.get_level_order();
|
||||
assert(pre_reversal == pre_res); ///< Check for equality
|
||||
std::cout << "Before reversal: ";
|
||||
bst.print();
|
||||
std::cout << "After reversal: ";
|
||||
bst.reverse();
|
||||
post_reversal = bst.get_level_order();
|
||||
assert(post_reversal == post_res); ///< Check for equality
|
||||
bst.print();
|
||||
std::cout << "TEST PASSED!\n\n";
|
||||
}
|
||||
} // namespace tests
|
||||
|
||||
/**
|
||||
* @brief Function to test the correctness of the Tree Reversal
|
||||
*/
|
||||
static void test() {
|
||||
tests::test1(); ///< Single element test
|
||||
tests::test2(); ///< No element test
|
||||
tests::test3(); ///< Correct reversal test
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief main function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main() {
|
||||
test(); // run self-test implementations
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user