mirror of
https://github.com/TheAlgorithms/C-Plus-Plus.git
synced 2026-10-31 04:45:46 +08:00
clang-format and clang-tidy fixes for 537cd7e8
This commit is contained in:
@@ -1,22 +1,24 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief prints the assigned colors
|
||||
* using [Graph Coloring](https://en.wikipedia.org/wiki/Graph_coloring) algorithm
|
||||
* using [Graph Coloring](https://en.wikipedia.org/wiki/Graph_coloring)
|
||||
* algorithm
|
||||
*
|
||||
* @details
|
||||
* In graph theory, graph coloring is a special case of graph labeling;
|
||||
* it is an assignment of labels traditionally called "colors" to elements of a graph subject to certain constraints.
|
||||
* In its simplest form, it is a way of coloring the vertices of a graph such that no two adjacent vertices are of the same color;
|
||||
* this is called a vertex coloring. Similarly, an edge coloring assigns
|
||||
* a color to each edge so that no two adjacent edges are of the same color,
|
||||
* and a face coloring of a planar graph assigns a color to each face or
|
||||
* In graph theory, graph coloring is a special case of graph labeling;
|
||||
* it is an assignment of labels traditionally called "colors" to elements of a
|
||||
* graph subject to certain constraints. In its simplest form, it is a way of
|
||||
* coloring the vertices of a graph such that no two adjacent vertices are of
|
||||
* the same color; this is called a vertex coloring. Similarly, an edge coloring
|
||||
* assigns a color to each edge so that no two adjacent edges are of the same
|
||||
* color, and a face coloring of a planar graph assigns a color to each face or
|
||||
* region so that no two faces that share a boundary have the same color.
|
||||
*
|
||||
* @author [Anup Kumar Panwar](https://github.com/AnupKumarPanwar)
|
||||
* @author [David Leal](https://github.com/Panquesito7)
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
@@ -24,70 +26,72 @@
|
||||
* @brief Backtracking algorithms
|
||||
*/
|
||||
namespace backtracking {
|
||||
/** A utility function to print solution
|
||||
* @tparam V number of vertices in the graph
|
||||
* @param color array of colors assigned to the nodes
|
||||
*/
|
||||
template <size_t V>
|
||||
void printSolution(const std::array <int, V>& color) {
|
||||
std::cout << "Following are the assigned colors" << std::endl;
|
||||
for (auto &col : color) {
|
||||
std::cout << col;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
/** A utility function to print solution
|
||||
* @tparam V number of vertices in the graph
|
||||
* @param color array of colors assigned to the nodes
|
||||
*/
|
||||
template <size_t V>
|
||||
void printSolution(const std::array<int, V>& color) {
|
||||
std::cout << "Following are the assigned colors" << std::endl;
|
||||
for (auto& col : color) {
|
||||
std::cout << col;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/** A utility function to check if the current color assignment is safe for
|
||||
* vertex v
|
||||
* @tparam V number of vertices in the graph
|
||||
* @param v index of graph vertex to check
|
||||
* @param graph matrix of graph nonnectivity
|
||||
* @param color vector of colors assigned to the graph nodes/vertices
|
||||
* @param c color value to check for the node `v`
|
||||
* @returns `true` if the color is safe to be assigned to the node
|
||||
* @returns `false` if the color is not safe to be assigned to the node
|
||||
*/
|
||||
template <size_t V>
|
||||
bool isSafe(int v, const std::array<std::array <int, V>, V>& graph, const std::array <int, V>& color, int c) {
|
||||
for (int i = 0; i < V; i++) {
|
||||
if (graph[v][i] && c == color[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** A recursive utility function to solve m coloring problem
|
||||
* @tparam V number of vertices in the graph
|
||||
* @param graph matrix of graph nonnectivity
|
||||
* @param m number of colors
|
||||
* @param [in,out] color description // used in,out to notify in documentation
|
||||
* that this parameter gets modified by the function
|
||||
* @param v index of graph vertex to check
|
||||
*/
|
||||
template <size_t V>
|
||||
void graphColoring(const std::array<std::array <int, V>, V>& graph, int m, std::array <int, V> color, int v) {
|
||||
// base case:
|
||||
// If all vertices are assigned a color then return true
|
||||
if (v == V) {
|
||||
backtracking::printSolution<V>(color);
|
||||
return;
|
||||
}
|
||||
|
||||
// Consider this vertex v and try different colors
|
||||
for (int c = 1; c <= m; c++) {
|
||||
// Check if assignment of color c to v is fine
|
||||
if (backtracking::isSafe<V>(v, graph, color, c)) {
|
||||
color[v] = c;
|
||||
|
||||
// recur to assign colors to rest of the vertices
|
||||
backtracking::graphColoring<V>(graph, m, color, v + 1);
|
||||
|
||||
// If assigning color c doesn't lead to a solution then remove it
|
||||
color[v] = 0;
|
||||
}
|
||||
/** A utility function to check if the current color assignment is safe for
|
||||
* vertex v
|
||||
* @tparam V number of vertices in the graph
|
||||
* @param v index of graph vertex to check
|
||||
* @param graph matrix of graph nonnectivity
|
||||
* @param color vector of colors assigned to the graph nodes/vertices
|
||||
* @param c color value to check for the node `v`
|
||||
* @returns `true` if the color is safe to be assigned to the node
|
||||
* @returns `false` if the color is not safe to be assigned to the node
|
||||
*/
|
||||
template <size_t V>
|
||||
bool isSafe(int v, const std::array<std::array<int, V>, V>& graph,
|
||||
const std::array<int, V>& color, int c) {
|
||||
for (int i = 0; i < V; i++) {
|
||||
if (graph[v][i] && c == color[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** A recursive utility function to solve m coloring problem
|
||||
* @tparam V number of vertices in the graph
|
||||
* @param graph matrix of graph nonnectivity
|
||||
* @param m number of colors
|
||||
* @param [in,out] color description // used in,out to notify in documentation
|
||||
* that this parameter gets modified by the function
|
||||
* @param v index of graph vertex to check
|
||||
*/
|
||||
template <size_t V>
|
||||
void graphColoring(const std::array<std::array<int, V>, V>& graph, int m,
|
||||
std::array<int, V> color, int v) {
|
||||
// base case:
|
||||
// If all vertices are assigned a color then return true
|
||||
if (v == V) {
|
||||
backtracking::printSolution<V>(color);
|
||||
return;
|
||||
}
|
||||
|
||||
// Consider this vertex v and try different colors
|
||||
for (int c = 1; c <= m; c++) {
|
||||
// Check if assignment of color c to v is fine
|
||||
if (backtracking::isSafe<V>(v, graph, color, c)) {
|
||||
color[v] = c;
|
||||
|
||||
// recur to assign colors to rest of the vertices
|
||||
backtracking::graphColoring<V>(graph, m, color, v + 1);
|
||||
|
||||
// If assigning color c doesn't lead to a solution then remove it
|
||||
color[v] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace backtracking
|
||||
|
||||
/**
|
||||
@@ -102,15 +106,12 @@ int main() {
|
||||
// (0)---(1)
|
||||
|
||||
const int V = 4; // number of vertices in the graph
|
||||
std::array <std::array <int, V>, V> graph = {
|
||||
std::array <int, V>({0, 1, 1, 1}),
|
||||
std::array <int, V>({1, 0, 1, 0}),
|
||||
std::array <int, V>({1, 1, 0, 1}),
|
||||
std::array <int, V>({1, 0, 1, 0})
|
||||
};
|
||||
std::array<std::array<int, V>, V> graph = {
|
||||
std::array<int, V>({0, 1, 1, 1}), std::array<int, V>({1, 0, 1, 0}),
|
||||
std::array<int, V>({1, 1, 0, 1}), std::array<int, V>({1, 0, 1, 0})};
|
||||
|
||||
int m = 3; // Number of colors
|
||||
std::array <int, V> color{};
|
||||
std::array<int, V> color{};
|
||||
|
||||
backtracking::graphColoring<V>(graph, m, color, 0);
|
||||
return 0;
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief [Count the number of ciphers](https://www.tutorialspoint.com/count-trailing-zeros-in-factorial-of-a-number-in-cplusplus) in `n!` implementation
|
||||
* @brief [Count the number of
|
||||
ciphers](https://www.tutorialspoint.com/count-trailing-zeros-in-factorial-of-a-number-in-cplusplus)
|
||||
in `n!` implementation
|
||||
* @details
|
||||
* Given an integer number as input. The goal is to find the number of trailing zeroes in the factorial calculated for
|
||||
* that number. A factorial of a number N is a product of all numbers in the range [1, N].
|
||||
* Given an integer number as input. The goal is to find the number of trailing
|
||||
zeroes in the factorial calculated for
|
||||
* that number. A factorial of a number N is a product of all numbers in the
|
||||
range [1, N].
|
||||
|
||||
* We know that we get a trailing zero only if the number is multiple of 10 or has a factor pair (2,5). In all factorials of
|
||||
* any number greater than 5, we have many 2s more than 5s in the prime factorization of that number. Dividing a
|
||||
* number by powers of 5 will give us the count of 5s in its factors. So, the number of 5s will tell us the number of trailing zeroes.
|
||||
* We know that we get a trailing zero only if the number is multiple of 10 or
|
||||
has a factor pair (2,5). In all factorials of
|
||||
* any number greater than 5, we have many 2s more than 5s in the prime
|
||||
factorization of that number. Dividing a
|
||||
* number by powers of 5 will give us the count of 5s in its factors. So, the
|
||||
number of 5s will tell us the number of trailing zeroes.
|
||||
* @author [Swastika Gupta](https://github.com/Swastyy)
|
||||
*/
|
||||
|
||||
@@ -21,10 +28,12 @@
|
||||
namespace bit_manipulation {
|
||||
/**
|
||||
* @namespace numberOfCiphersInFactorialN
|
||||
* @brief Functions for the [Count the number of ciphers](https://www.tutorialspoint.com/count-trailing-zeros-in-factorial-of-a-number-in-cplusplus) in `n!` implementation
|
||||
* @brief Functions for the [Count the number of
|
||||
* ciphers](https://www.tutorialspoint.com/count-trailing-zeros-in-factorial-of-a-number-in-cplusplus)
|
||||
* in `n!` implementation
|
||||
*/
|
||||
namespace numberOfCiphersInFactorialN {
|
||||
/**
|
||||
/**
|
||||
* @brief Function to count the number of trailing ciphers.
|
||||
* @param n, Number for which `n!` ciphers are returned
|
||||
* @return count, Number of ciphers in `n!`.
|
||||
@@ -51,27 +60,32 @@ uint64_t numberOfCiphersInFactorialN(uint64_t n) {
|
||||
static void test() {
|
||||
// Test 1
|
||||
std::cout << "1st test ";
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::numberOfCiphersInFactorialN(395) == 97);
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::
|
||||
numberOfCiphersInFactorialN(395) == 97);
|
||||
std::cout << "passed" << std::endl;
|
||||
|
||||
// Test 2
|
||||
std::cout << "2nd test ";
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::numberOfCiphersInFactorialN(977) == 242);
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::
|
||||
numberOfCiphersInFactorialN(977) == 242);
|
||||
std::cout << "passed" << std::endl;
|
||||
|
||||
// Test 3
|
||||
std::cout << "3rd test ";
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::numberOfCiphersInFactorialN(871) == 215);
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::
|
||||
numberOfCiphersInFactorialN(871) == 215);
|
||||
std::cout << "passed" << std::endl;
|
||||
|
||||
// Test 4
|
||||
std::cout << "4th test ";
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::numberOfCiphersInFactorialN(239) == 57);
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::
|
||||
numberOfCiphersInFactorialN(239) == 57);
|
||||
std::cout << "passed" << std::endl;
|
||||
|
||||
// Test 5
|
||||
std::cout << "5th test ";
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::numberOfCiphersInFactorialN(0) == 0);
|
||||
assert(bit_manipulation::numberOfCiphersInFactorialN::
|
||||
numberOfCiphersInFactorialN(0) == 0);
|
||||
std::cout << "passed" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +1,45 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Iterative version of Preorder, Postorder, and preorder [Traversal of the Tree]
|
||||
* (https://en.wikipedia.org/wiki/Tree_traversal)
|
||||
* @brief Iterative version of Preorder, Postorder, and preorder [Traversal of
|
||||
* the Tree] (https://en.wikipedia.org/wiki/Tree_traversal)
|
||||
* @author [Motasim](https://github.com/motasimmakki)
|
||||
* @details
|
||||
*
|
||||
*
|
||||
* ### Iterative Preorder Traversal of a tree
|
||||
* Create a Stack that will store the Node of Tree.
|
||||
* Push the root node into the stack.
|
||||
* Save the root into the variabe named as current, and pop and elemnt from the stack.
|
||||
* Store the data of current into the result array, and start traversing from it.
|
||||
* Push both the child node of the current node into the stack, first right child then left child.
|
||||
* Repeat the same set of steps untill the Stack becomes empty.
|
||||
* And return the result array as the preorder traversal of a tree.
|
||||
*
|
||||
* Save the root into the variabe named as current, and pop and elemnt from the
|
||||
* stack. Store the data of current into the result array, and start traversing
|
||||
* from it. Push both the child node of the current node into the stack, first
|
||||
* right child then left child. Repeat the same set of steps untill the Stack
|
||||
* becomes empty. And return the result array as the preorder traversal of a
|
||||
* tree.
|
||||
*
|
||||
* ### Iterative Postorder Traversal of a tree
|
||||
* Create a Stack that will store the Node of Tree.
|
||||
* Push the root node into the stack.
|
||||
* Save the root into the variabe named as current, and pop and elemnt from the stack.
|
||||
* Store the data of current into the result array, and start traversing from it.
|
||||
* Push both the child node of the current node into the stack, first left child then right child.
|
||||
* Repeat the same set of steps untill the Stack becomes empty.
|
||||
* Now reverse the result array and then return it to the calling function as a postorder traversal of a tree.
|
||||
*
|
||||
* Save the root into the variabe named as current, and pop and elemnt from the
|
||||
* stack. Store the data of current into the result array, and start traversing
|
||||
* from it. Push both the child node of the current node into the stack, first
|
||||
* left child then right child. Repeat the same set of steps untill the Stack
|
||||
* becomes empty. Now reverse the result array and then return it to the calling
|
||||
* function as a postorder traversal of a tree.
|
||||
*
|
||||
* ### Iterative Inorder Traversal of a tree
|
||||
* Create a Stack that will store the Node of Tree.
|
||||
* Push the root node into the stack.
|
||||
* Save the root into the variabe named as current.
|
||||
* Now iterate and take the current to the extreme left of the tree by traversing only to its left.
|
||||
* Pop the elemnt from the stack and assign it to the current.
|
||||
* Store the data of current into the result array.
|
||||
* Repeat the same set of steps until the Stack becomes empty or the current becomes NULL.
|
||||
* And return the result array as the inorder traversal of a tree.
|
||||
* Now iterate and take the current to the extreme left of the tree by
|
||||
* traversing only to its left. Pop the elemnt from the stack and assign it to
|
||||
* the current. Store the data of current into the result array. Repeat the same
|
||||
* set of steps until the Stack becomes empty or the current becomes NULL. And
|
||||
* return the result array as the inorder traversal of a tree.
|
||||
*/
|
||||
#include <algorithm> /// for `reverse`
|
||||
#include <cassert> /// for `assert`
|
||||
#include <iostream> /// for I/O operations
|
||||
#include <stack> /// for `stack`
|
||||
#include <vector> /// for `vector`
|
||||
#include <algorithm> /// for `reverse`
|
||||
#include <cassert> /// for `assert`
|
||||
|
||||
/**
|
||||
* @namespace others
|
||||
@@ -46,35 +48,44 @@
|
||||
namespace others {
|
||||
/**
|
||||
* @namespace iterative_tree_traversals
|
||||
* @brief Functions for the [Traversal of the Tree](https://en.wikipedia.org/wiki/Tree_traversal) algorithm
|
||||
* @brief Functions for the [Traversal of the
|
||||
* Tree](https://en.wikipedia.org/wiki/Tree_traversal) algorithm
|
||||
*/
|
||||
namespace iterative_tree_traversals {
|
||||
/**
|
||||
* @brief defines the structure of a node of the tree
|
||||
*/
|
||||
struct Node {
|
||||
int64_t data = 0; ///< The value/key of the node.
|
||||
struct Node *left; ///< struct pointer to left subtree.
|
||||
struct Node *right; ///< struct pointer to right subtree.
|
||||
int64_t data = 0; ///< The value/key of the node.
|
||||
struct Node *left{}; ///< struct pointer to left subtree.
|
||||
struct Node *right{}; ///< struct pointer to right subtree.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief defines the functions associated with the binary tree
|
||||
*/
|
||||
class BinaryTree {
|
||||
public:
|
||||
Node *createNewNode(int64_t); ///< function that will create new node for insertion.
|
||||
std::vector<int64_t> preOrderIterative(Node *); ///< function that takes root of the tree as an argument, and returns its preorder traversal.
|
||||
std::vector<int64_t> postOrderIterative(Node *); ///< function that takes root of the tree as an argument, and returns its postorder traversal.
|
||||
std::vector<int64_t> inOrderIterative(Node *); ///< function that takes root of the tree as an argument, and returns its inorder traversal.
|
||||
public:
|
||||
Node *createNewNode(
|
||||
int64_t); ///< function that will create new node for insertion.
|
||||
std::vector<int64_t> preOrderIterative(
|
||||
Node *); ///< function that takes root of the tree as an argument, and
|
||||
///< returns its preorder traversal.
|
||||
std::vector<int64_t> postOrderIterative(
|
||||
Node *); ///< function that takes root of the tree as an argument, and
|
||||
///< returns its postorder traversal.
|
||||
std::vector<int64_t> inOrderIterative(
|
||||
Node *); ///< function that takes root of the tree as an argument, and
|
||||
///< returns its inorder traversal.
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief will allocate the memory for a node and, along the data and return the node.
|
||||
* @brief will allocate the memory for a node and, along the data and return the
|
||||
* node.
|
||||
* @param data value that a particular node will contain.
|
||||
* @return pointer to the newly created node with assigned data.
|
||||
* @return pointer to the newly created node with assigned data.
|
||||
*/
|
||||
Node * BinaryTree::createNewNode(int64_t data) {
|
||||
Node *BinaryTree::createNewNode(int64_t data) {
|
||||
Node *node = new Node();
|
||||
node->data = data;
|
||||
node->left = node->right = nullptr;
|
||||
@@ -82,85 +93,91 @@ Node * BinaryTree::createNewNode(int64_t data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief preOrderIterative() function that will perform the preorder traversal iteratively,
|
||||
* and return the result array that contain the preorder traversal of a tree.
|
||||
* @brief preOrderIterative() function that will perform the preorder traversal
|
||||
* iteratively, and return the result array that contain the preorder traversal
|
||||
* of a tree.
|
||||
* @param root head/root node of a tree
|
||||
* @return result that is containing the preorder traversal of a tree
|
||||
*/
|
||||
std::vector<int64_t> BinaryTree::preOrderIterative(Node *root) {
|
||||
std::stack<Node *> stack; ///< is used to find and traverse the child nodes.
|
||||
std::vector<int64_t> BinaryTree::preOrderIterative(Node *root) {
|
||||
std::stack<Node *>
|
||||
stack; ///< is used to find and traverse the child nodes.
|
||||
std::vector<int64_t> result; ///< list of values, sorted in pre-order.
|
||||
|
||||
|
||||
stack.push(root);
|
||||
|
||||
while(!stack.empty()) {
|
||||
|
||||
while (!stack.empty()) {
|
||||
result.push_back(stack.top()->data);
|
||||
Node *current = stack.top();
|
||||
stack.pop();
|
||||
|
||||
if(current->right) {
|
||||
|
||||
if (current->right) {
|
||||
stack.push(current->right);
|
||||
}
|
||||
if(current->left) {
|
||||
if (current->left) {
|
||||
stack.push(current->left);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief postOrderIterative() function that will perform the postorder traversal iteratively,
|
||||
* and return the result array that contain the postorder traversal of a tree.
|
||||
* @brief postOrderIterative() function that will perform the postorder
|
||||
* traversal iteratively, and return the result array that contain the postorder
|
||||
* traversal of a tree.
|
||||
* @param root head/root node of a tree
|
||||
* @return result that is containing the postorder traversal of a tree
|
||||
*/
|
||||
std::vector<int64_t> BinaryTree::postOrderIterative(Node *root) {
|
||||
std::stack<Node *> stack; ///< is used to find and traverse the child nodes.
|
||||
std::vector<int64_t> BinaryTree::postOrderIterative(Node *root) {
|
||||
std::stack<Node *>
|
||||
stack; ///< is used to find and traverse the child nodes.
|
||||
std::vector<int64_t> result; ///< List of values, sorted in post-order.
|
||||
|
||||
|
||||
stack.push(root);
|
||||
|
||||
while(!stack.empty()) {
|
||||
|
||||
while (!stack.empty()) {
|
||||
result.push_back(stack.top()->data);
|
||||
Node *current = stack.top();
|
||||
stack.pop();
|
||||
|
||||
if(current->left) {
|
||||
|
||||
if (current->left) {
|
||||
stack.push(current->left);
|
||||
}
|
||||
if(current->right) {
|
||||
if (current->right) {
|
||||
stack.push(current->right);
|
||||
}
|
||||
}
|
||||
|
||||
reverse(result.begin(), result.end());
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief inOrderIterative() function that will perform the inorder traversal iteratively,
|
||||
* and return the result array that contain the inorder traversal of a tree.
|
||||
* @brief inOrderIterative() function that will perform the inorder traversal
|
||||
* iteratively, and return the result array that contain the inorder traversal
|
||||
* of a tree.
|
||||
* @param root head/root node of a tree
|
||||
* @return result that is containing the inorder traversal of a tree
|
||||
*/
|
||||
std::vector<int64_t> BinaryTree::inOrderIterative(Node *root) {
|
||||
std::stack<Node *> stack; ///< is used to find and traverse the child nodes.
|
||||
std::stack<Node *>
|
||||
stack; ///< is used to find and traverse the child nodes.
|
||||
std::vector<int64_t> result; ///< List of values, sorted in in-order.
|
||||
|
||||
Node *current = root;
|
||||
|
||||
while(!stack.empty() || current) {
|
||||
while(current) {
|
||||
|
||||
while (!stack.empty() || current) {
|
||||
while (current) {
|
||||
stack.push(current);
|
||||
current = current->left;
|
||||
}
|
||||
current = stack.top();
|
||||
stack.pop();
|
||||
result.push_back(current->data);
|
||||
stack.pop();
|
||||
result.push_back(current->data);
|
||||
current = current->right;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace iterative_tree_traversals
|
||||
@@ -171,22 +188,25 @@ std::vector<int64_t> BinaryTree::inOrderIterative(Node *root) {
|
||||
* @param binaryTree instance of the BinaryTree class
|
||||
* @param root head/root node of a tree
|
||||
*/
|
||||
static void test1(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
|
||||
static void test1(others::iterative_tree_traversals::BinaryTree binaryTree,
|
||||
others::iterative_tree_traversals::Node *root) {
|
||||
std::vector<int64_t> actual_result{1, 2, 4, 5, 3};
|
||||
std::vector<int64_t> result; ///< result stores the preorder traversal of the binary tree
|
||||
std::vector<int64_t>
|
||||
result; ///< result stores the preorder traversal of the binary tree
|
||||
|
||||
// Calling preOrderIterative() function by passing a root node,
|
||||
// and storing the preorder traversal in result.
|
||||
result = binaryTree.preOrderIterative(root);
|
||||
result = binaryTree.preOrderIterative(root);
|
||||
|
||||
// Self-testing the result using `assert`
|
||||
for(int i = 0; i < result.size(); i++)
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
assert(actual_result[i] == result[i]);
|
||||
}
|
||||
|
||||
// Printing the result storing preorder.
|
||||
std::cout<< "\nPreOrder Traversal Is : "<< std::endl;
|
||||
for(auto i: result) {
|
||||
std::cout<< i<< " ";
|
||||
std::cout << "\nPreOrder Traversal Is : " << std::endl;
|
||||
for (auto i : result) {
|
||||
std::cout << i << " ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,22 +215,25 @@ static void test1(others::iterative_tree_traversals::BinaryTree binaryTree, othe
|
||||
* @param binaryTree instance of BinaryTree class
|
||||
* @param root head/root node of a tree
|
||||
*/
|
||||
static void test2(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
|
||||
static void test2(others::iterative_tree_traversals::BinaryTree binaryTree,
|
||||
others::iterative_tree_traversals::Node *root) {
|
||||
std::vector<int64_t> actual_result{4, 5, 2, 3, 1};
|
||||
std::vector<int64_t> result; ///< result stores the postorder traversal of the binary tree.
|
||||
std::vector<int64_t>
|
||||
result; ///< result stores the postorder traversal of the binary tree.
|
||||
|
||||
// Calling postOrderIterative() function by passing a root node,
|
||||
// and storing the postorder traversal in result.
|
||||
result = binaryTree.postOrderIterative(root);
|
||||
|
||||
// Self-testing the result using `assert`
|
||||
for(int i = 0; i < result.size(); i++)
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
assert(actual_result[i] == result[i]);
|
||||
}
|
||||
|
||||
// Printing the result storing postorder.
|
||||
std::cout<< "\nPostOrder Traversal Is : "<< std::endl;
|
||||
for(auto i: result) {
|
||||
std::cout<< i<< " ";
|
||||
std::cout << "\nPostOrder Traversal Is : " << std::endl;
|
||||
for (auto i : result) {
|
||||
std::cout << i << " ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,22 +242,25 @@ static void test2(others::iterative_tree_traversals::BinaryTree binaryTree, othe
|
||||
* @param binaryTree instance of BinaryTree class
|
||||
* @param root head/root node of a tree
|
||||
*/
|
||||
static void test3(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
|
||||
static void test3(others::iterative_tree_traversals::BinaryTree binaryTree,
|
||||
others::iterative_tree_traversals::Node *root) {
|
||||
std::vector<int64_t> actual_result{4, 2, 5, 1, 3};
|
||||
std::vector<int64_t> result; ///< result stores the inorder traversal of the binary tree.
|
||||
std::vector<int64_t>
|
||||
result; ///< result stores the inorder traversal of the binary tree.
|
||||
|
||||
// Calling inOrderIterative() function by passing a root node,
|
||||
// and storing the inorder traversal in result.
|
||||
result = binaryTree.inOrderIterative(root);
|
||||
|
||||
// Self-testing the result using `assert`
|
||||
for(int i = 0; i < result.size(); i++)
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
assert(actual_result[i] == result[i]);
|
||||
}
|
||||
|
||||
// Printing the result storing inorder.
|
||||
std::cout<< "\nInOrder Traversal Is : "<< std::endl;
|
||||
for(auto i: result) {
|
||||
std::cout<< i<< " ";
|
||||
std::cout << "\nInOrder Traversal Is : " << std::endl;
|
||||
for (auto i : result) {
|
||||
std::cout << i << " ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,46 +269,53 @@ static void test3(others::iterative_tree_traversals::BinaryTree binaryTree, othe
|
||||
* @param binaryTree instance of BinaryTree class
|
||||
* @param root head/root node of a tree
|
||||
*/
|
||||
static void test4(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
|
||||
static void test4(others::iterative_tree_traversals::BinaryTree binaryTree,
|
||||
others::iterative_tree_traversals::Node *root) {
|
||||
std::vector<int64_t> actual_result{-1, -2, -4, -5, -3};
|
||||
std::vector<int64_t> result; ///< result stores the preorder traversal of the binary tree
|
||||
std::vector<int64_t>
|
||||
result; ///< result stores the preorder traversal of the binary tree
|
||||
|
||||
// Calling preOrderIterative() function by passing a root node,
|
||||
// and storing the preorder traversal in result.
|
||||
result = binaryTree.preOrderIterative(root);
|
||||
result = binaryTree.preOrderIterative(root);
|
||||
|
||||
// Self-testing the result using `assert`
|
||||
for(int i = 0; i < result.size(); i++)
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
assert(actual_result[i] == result[i]);
|
||||
}
|
||||
|
||||
// Printing the result storing preorder.
|
||||
std::cout<< "\nPreOrder Traversal Is : "<< std::endl;
|
||||
for(auto i: result) {
|
||||
std::cout<< i<< " ";
|
||||
std::cout << "\nPreOrder Traversal Is : " << std::endl;
|
||||
for (auto i : result) {
|
||||
std::cout << i << " ";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test the computed postorder with the actual postorder on negative value.
|
||||
* @brief Test the computed postorder with the actual postorder on negative
|
||||
* value.
|
||||
* @param binaryTree instance of BinaryTree class
|
||||
* @param root head/root node of a tree
|
||||
*/
|
||||
static void test5(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
|
||||
static void test5(others::iterative_tree_traversals::BinaryTree binaryTree,
|
||||
others::iterative_tree_traversals::Node *root) {
|
||||
std::vector<int64_t> actual_result{-4, -5, -2, -3, -1};
|
||||
std::vector<int64_t> result; ///< result stores the postorder traversal of the binary tree.
|
||||
std::vector<int64_t>
|
||||
result; ///< result stores the postorder traversal of the binary tree.
|
||||
|
||||
// Calling postOrderIterative() function by passing a root node,
|
||||
// and storing the postorder traversal in result.
|
||||
result = binaryTree.postOrderIterative(root);
|
||||
|
||||
// Self-testing the result using `assert`
|
||||
for(int i = 0; i < result.size(); i++)
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
assert(actual_result[i] == result[i]);
|
||||
}
|
||||
|
||||
// Printing the result storing postorder.
|
||||
std::cout<< "\nPostOrder Traversal Is : "<< std::endl;
|
||||
for(auto i: result) {
|
||||
std::cout<< i<< " ";
|
||||
std::cout << "\nPostOrder Traversal Is : " << std::endl;
|
||||
for (auto i : result) {
|
||||
std::cout << i << " ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,22 +324,25 @@ static void test5(others::iterative_tree_traversals::BinaryTree binaryTree, othe
|
||||
* @param binaryTree instance of BinaryTree class
|
||||
* @param root head/root node of a tree
|
||||
*/
|
||||
static void test6(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
|
||||
static void test6(others::iterative_tree_traversals::BinaryTree binaryTree,
|
||||
others::iterative_tree_traversals::Node *root) {
|
||||
std::vector<int64_t> actual_result{-4, -2, -5, -1, -3};
|
||||
std::vector<int64_t> result; ///< result stores the inorder traversal of the binary tree.
|
||||
std::vector<int64_t>
|
||||
result; ///< result stores the inorder traversal of the binary tree.
|
||||
|
||||
// Calling inOrderIterative() function by passing a root node,
|
||||
// and storing the inorder traversal in result.
|
||||
result = binaryTree.inOrderIterative(root);
|
||||
|
||||
// Self-testing the result using `assert`
|
||||
for(int i = 0; i < result.size(); i++)
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
assert(actual_result[i] == result[i]);
|
||||
}
|
||||
|
||||
// Printing the result storing inorder.
|
||||
std::cout<< "\nInOrder Traversal Is : "<< std::endl;
|
||||
for(auto i: result) {
|
||||
std::cout<< i<< " ";
|
||||
std::cout << "\nInOrder Traversal Is : " << std::endl;
|
||||
for (auto i : result) {
|
||||
std::cout << i << " ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,7 +352,7 @@ static void test6(others::iterative_tree_traversals::BinaryTree binaryTree, othe
|
||||
*/
|
||||
int main() {
|
||||
// Creating a tree with the following structure,
|
||||
/*
|
||||
/*
|
||||
1
|
||||
/ \
|
||||
2 3
|
||||
@@ -324,22 +360,24 @@ int main() {
|
||||
4 5
|
||||
*/
|
||||
|
||||
others::iterative_tree_traversals::BinaryTree binaryTree; ///< instace of BinaryTree, used to access its members functions.
|
||||
others::iterative_tree_traversals::BinaryTree
|
||||
binaryTree; ///< instace of BinaryTree, used to access its members
|
||||
///< functions.
|
||||
others::iterative_tree_traversals::Node *root = binaryTree.createNewNode(1);
|
||||
root->left = binaryTree.createNewNode(2);
|
||||
root->right = binaryTree.createNewNode(3);
|
||||
root->left->left = binaryTree.createNewNode(4);
|
||||
root->left->right = binaryTree.createNewNode(5);
|
||||
|
||||
std::cout<< "\n| Tests for positive data value |"<< std::endl;
|
||||
std::cout << "\n| Tests for positive data value |" << std::endl;
|
||||
test1(binaryTree, root); // run preorder-iterative test
|
||||
std::cout<< "\nPre-order test Passed!"<< std::endl;
|
||||
std::cout << "\nPre-order test Passed!" << std::endl;
|
||||
|
||||
test2(binaryTree, root); // run postorder-iterative test
|
||||
std::cout<< "\nPost-order test Passed!"<< std::endl;
|
||||
std::cout << "\nPost-order test Passed!" << std::endl;
|
||||
|
||||
test3(binaryTree, root); // run inorder-iterative test
|
||||
std::cout<< "\nIn-order test Passed!"<< std::endl;
|
||||
std::cout << "\nIn-order test Passed!" << std::endl;
|
||||
|
||||
// Modifying tree for negative values.
|
||||
root->data = -1;
|
||||
@@ -348,15 +386,15 @@ int main() {
|
||||
root->left->left->data = -4;
|
||||
root->left->right->data = -5;
|
||||
|
||||
std::cout<< "\n| Tests for negative data values |"<< std::endl;
|
||||
std::cout << "\n| Tests for negative data values |" << std::endl;
|
||||
test4(binaryTree, root); // run preorder-iterative test on negative values
|
||||
std::cout<< "\nPre-order test on-negative value Passed!"<< std::endl;
|
||||
std::cout << "\nPre-order test on-negative value Passed!" << std::endl;
|
||||
|
||||
test5(binaryTree, root); // run postorder-iterative test on negative values
|
||||
std::cout<< "\nPost-order test on-negative value Passed!"<< std::endl;
|
||||
std::cout << "\nPost-order test on-negative value Passed!" << std::endl;
|
||||
|
||||
test6(binaryTree, root); // run inorder-iterative test on negative values
|
||||
std::cout<< "\nIn-order test on-negative value Passed!"<< std::endl;
|
||||
std::cout << "\nIn-order test on-negative value Passed!" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,44 +1,55 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of the [Random Pivot Quick Sort](https://www.sanfoundry.com/cpp-program-implement-quick-sort-using-randomisation) algorithm.
|
||||
* @brief Implementation of the [Random Pivot Quick
|
||||
* Sort](https://www.sanfoundry.com/cpp-program-implement-quick-sort-using-randomisation)
|
||||
* algorithm.
|
||||
* @details
|
||||
* * A random pivot quick sort algorithm is pretty much same as quick sort with a difference of having a logic of
|
||||
* selecting next pivot element from the input array.
|
||||
* * Where in quick sort is fast, but still can give you the time complexity of O(n^2) in worst case.
|
||||
* * To avoid hitting the time complexity of O(n^2), we use the logic of randomize the selection process of pivot
|
||||
* element.
|
||||
* * A random pivot quick sort algorithm is pretty much same as quick
|
||||
* sort with a difference of having a logic of selecting next pivot element from
|
||||
* the input array.
|
||||
* * Where in quick sort is fast, but still can give you the time
|
||||
* complexity of O(n^2) in worst case.
|
||||
* * To avoid hitting the time complexity of O(n^2), we use the logic
|
||||
* of randomize the selection process of pivot element.
|
||||
*
|
||||
* ### Logic
|
||||
* * The logic is pretty simple, the only change is in the partitioning algorithm, which is selecting the
|
||||
* pivot element.
|
||||
* * Instead of selecting the last or the first element from array for pivot we use a random index to select
|
||||
* pivot element.
|
||||
* * This avoids hitting the O(n^2) time complexity in practical use cases.
|
||||
* * The logic is pretty simple, the only change is in the
|
||||
* partitioning algorithm, which is selecting the pivot element.
|
||||
* * Instead of selecting the last or the first element from array
|
||||
* for pivot we use a random index to select pivot element.
|
||||
* * This avoids hitting the O(n^2) time complexity in practical
|
||||
* use cases.
|
||||
*
|
||||
* ### Partition Logic
|
||||
* * Partitions are done such as numbers lower than the "pivot" element is arranged on the left side of the "pivot",
|
||||
* and number larger than the "pivot" element are arranged on the right part of the array.
|
||||
* * Partitions are done such as numbers lower than the "pivot"
|
||||
* element is arranged on the left side of the "pivot", and number larger than
|
||||
* the "pivot" element are arranged on the right part of the array.
|
||||
*
|
||||
* ### Algorithm
|
||||
* * Select the pivot element randomly using getRandomIndex() function from this namespace.
|
||||
* * Initialize the pInd (partition index) from the start of the array.
|
||||
* * Loop through the array from start to less than end. (from start to < end).
|
||||
* (Inside the loop) :-
|
||||
* * Check if the current element (arr[i]) is less than the pivot element in each iteration.
|
||||
* * If current element in the iteration is less than the pivot element,
|
||||
* then swap the elements at current index (i) and partition index (pInd) and increment the partition index by one.
|
||||
* * At the end of the loop, swap the pivot element with partition index element.
|
||||
* * Select the pivot element randomly using getRandomIndex() function
|
||||
* from this namespace.
|
||||
* * Initialize the pInd (partition index) from the start of the
|
||||
* array.
|
||||
* * Loop through the array from start to less than end. (from start
|
||||
* to < end). (Inside the loop) :-
|
||||
* * Check if the current element (arr[i]) is less than the
|
||||
* pivot element in each iteration.
|
||||
* * If current element in the iteration is less than the
|
||||
* pivot element, then swap the elements at current index (i) and partition
|
||||
* index (pInd) and increment the partition index by one.
|
||||
* * At the end of the loop, swap the pivot element with partition
|
||||
* index element.
|
||||
* * Return the partition index from the function.
|
||||
*
|
||||
* @author [Nitin Sharma](https://github.com/foo290)
|
||||
*/
|
||||
|
||||
#include <iostream> /// for IO operations
|
||||
#include <ctime> /// for initializing random number generator
|
||||
#include <cassert> /// for assert
|
||||
#include <algorithm> /// for std::is_sorted(), std::swap()
|
||||
#include <algorithm> /// for std::is_sorted(), std::swap()
|
||||
#include <array> /// for std::array
|
||||
#include <tuple> /// for returning multiple values form a function at once
|
||||
#include <cassert> /// for assert
|
||||
#include <ctime> /// for initializing random number generator
|
||||
#include <iostream> /// for IO operations
|
||||
#include <tuple> /// for returning multiple values form a function at once
|
||||
|
||||
/**
|
||||
* @namespace sorting
|
||||
@@ -46,111 +57,120 @@
|
||||
*/
|
||||
namespace sorting {
|
||||
/**
|
||||
* @brief Functions for the [Random Pivot Quick Sort](https://www.sanfoundry.com/cpp-program-implement-quick-sort-using-randomisation) implementation
|
||||
* @brief Functions for the [Random Pivot Quick
|
||||
* Sort](https://www.sanfoundry.com/cpp-program-implement-quick-sort-using-randomisation)
|
||||
* implementation
|
||||
* @namespace random_pivot_quick_sort
|
||||
*/
|
||||
namespace random_pivot_quick_sort {
|
||||
/**
|
||||
* @brief Utility function to print the array
|
||||
* @tparam T size of the array
|
||||
* @param arr array used to print its content
|
||||
* @returns void
|
||||
* */
|
||||
template<size_t T>
|
||||
void showArray(std::array<int64_t , T> arr) {
|
||||
for (int64_t i = 0; i < arr.size(); i++) {
|
||||
std::cout << arr[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
namespace random_pivot_quick_sort {
|
||||
/**
|
||||
* @brief Utility function to print the array
|
||||
* @tparam T size of the array
|
||||
* @param arr array used to print its content
|
||||
* @returns void
|
||||
* */
|
||||
template <size_t T>
|
||||
void showArray(std::array<int64_t, T> arr) {
|
||||
for (int64_t i = 0; i < arr.size(); i++) {
|
||||
std::cout << arr[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Takes the start and end indices of an array and returns a random
|
||||
* int64_teger between the range of those two for selecting pivot element.
|
||||
*
|
||||
* @param start The starting index.
|
||||
* @param end The ending index.
|
||||
* @returns int64_t A random number between start and end index.
|
||||
* */
|
||||
int64_t getRandomIndex(int64_t start, int64_t end) {
|
||||
srand(time(nullptr)); // Initialize random number generator.
|
||||
int64_t randomPivotIndex = start + rand() % (end - start + 1);
|
||||
return randomPivotIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A partition function which handles the partition logic of quick sort.
|
||||
* @tparam size size of the array to be passed as argument.
|
||||
* @param start The start index of the passed array
|
||||
* @param end The ending index of the passed array
|
||||
* @returns std::tuple<int64_t , std::array<int64_t , size>> A tuple of pivot
|
||||
* index and pivot sorted array.
|
||||
*/
|
||||
template <size_t size>
|
||||
std::tuple<int64_t, std::array<int64_t, size>> partition(
|
||||
std::array<int64_t, size> arr, int64_t start, int64_t end) {
|
||||
int64_t pivot = arr[end]; // Randomly selected element will be here from
|
||||
// caller function (quickSortRP()).
|
||||
int64_t pInd = start;
|
||||
|
||||
for (int64_t i = start; i < end; i++) {
|
||||
if (arr[i] <= pivot) {
|
||||
std::swap(arr[i], arr[pInd]); // swapping the elements from current
|
||||
// index to pInd.
|
||||
pInd++;
|
||||
}
|
||||
}
|
||||
std::swap(arr[pInd],
|
||||
arr[end]); // swapping the pivot element to its sorted position
|
||||
return std::make_tuple(pInd, arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Takes the start and end indices of an array and returns a random int64_teger between the range of those two
|
||||
* for selecting pivot element.
|
||||
*
|
||||
* @param start The starting index.
|
||||
* @param end The ending index.
|
||||
* @returns int64_t A random number between start and end index.
|
||||
* */
|
||||
int64_t getRandomIndex(int64_t start, int64_t end) {
|
||||
srand(time(nullptr)); // Initialize random number generator.
|
||||
int64_t randomPivotIndex = start + rand() % (end - start + 1);
|
||||
return randomPivotIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A partition function which handles the partition logic of quick sort.
|
||||
* @tparam size size of the array to be passed as argument.
|
||||
* @param start The start index of the passed array
|
||||
* @param end The ending index of the passed array
|
||||
* @returns std::tuple<int64_t , std::array<int64_t , size>> A tuple of pivot index and pivot sorted array.
|
||||
*/
|
||||
template<size_t size>
|
||||
std::tuple<int64_t , std::array<int64_t , size>> partition(std::array<int64_t , size> arr, int64_t start, int64_t end) {
|
||||
|
||||
int64_t pivot = arr[end]; // Randomly selected element will be here from caller function (quickSortRP()).
|
||||
int64_t pInd = start;
|
||||
|
||||
for (int64_t i = start; i < end; i++) {
|
||||
if (arr[i] <= pivot) {
|
||||
std::swap(arr[i], arr[pInd]); // swapping the elements from current index to pInd.
|
||||
pInd++;
|
||||
}
|
||||
}
|
||||
std::swap(arr[pInd], arr[end]); // swapping the pivot element to its sorted position
|
||||
return std::make_tuple(pInd, arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Random pivot quick sort function. This function is the starting point of the algorithm.
|
||||
* @tparam size size of the array to be passed as argument.
|
||||
* @param start The start index of the passed array
|
||||
* @param end The ending index of the passed array
|
||||
* @returns std::array<int64_t , size> A fully sorted array in ascending order.
|
||||
*/
|
||||
template<size_t size>
|
||||
std::array<int64_t , size> quickSortRP(std::array<int64_t , size> arr, int64_t start, int64_t end) {
|
||||
if (start < end) {
|
||||
|
||||
int64_t randomIndex = getRandomIndex(start, end);
|
||||
|
||||
// switching the pivot with right most bound.
|
||||
std::swap(arr[end], arr[randomIndex]);
|
||||
|
||||
int64_t pivotIndex = 0;
|
||||
// getting pivot index and pivot sorted array.
|
||||
std::tie(pivotIndex, arr) = partition(arr, start, end);
|
||||
|
||||
// Recursively calling
|
||||
std::array<int64_t , arr.size()> rightSortingLeft = quickSortRP(arr, start, pivotIndex - 1);
|
||||
std::array<int64_t , arr.size()> full_sorted = quickSortRP(rightSortingLeft, pivotIndex + 1, end);
|
||||
arr = full_sorted;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A function utility to generate unsorted array of given size and range.
|
||||
* @tparam size Size of the output array.
|
||||
* @param from Stating of the range.
|
||||
* @param to Ending of the range.
|
||||
* @returns std::array<int64_t , size> Unsorted array of specified size.
|
||||
* */
|
||||
template<size_t size>
|
||||
std::array<int64_t , size> generateUnsortedArray(int64_t from, int64_t to) {
|
||||
srand(time(nullptr));
|
||||
std::array<int64_t , size> unsortedArray{};
|
||||
assert(from < to);
|
||||
int64_t i = 0;
|
||||
while (i < size) {
|
||||
int64_t randomNum = from + rand() % (to - from + 1);
|
||||
if (randomNum) {
|
||||
unsortedArray[i] = randomNum;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return unsortedArray;
|
||||
/**
|
||||
* @brief Random pivot quick sort function. This function is the starting point
|
||||
* of the algorithm.
|
||||
* @tparam size size of the array to be passed as argument.
|
||||
* @param start The start index of the passed array
|
||||
* @param end The ending index of the passed array
|
||||
* @returns std::array<int64_t , size> A fully sorted array in ascending order.
|
||||
*/
|
||||
template <size_t size>
|
||||
std::array<int64_t, size> quickSortRP(std::array<int64_t, size> arr,
|
||||
int64_t start, int64_t end) {
|
||||
if (start < end) {
|
||||
int64_t randomIndex = getRandomIndex(start, end);
|
||||
|
||||
// switching the pivot with right most bound.
|
||||
std::swap(arr[end], arr[randomIndex]);
|
||||
|
||||
int64_t pivotIndex = 0;
|
||||
// getting pivot index and pivot sorted array.
|
||||
std::tie(pivotIndex, arr) = partition(arr, start, end);
|
||||
|
||||
// Recursively calling
|
||||
std::array<int64_t, arr.size()> rightSortingLeft =
|
||||
quickSortRP(arr, start, pivotIndex - 1);
|
||||
std::array<int64_t, arr.size()> full_sorted =
|
||||
quickSortRP(rightSortingLeft, pivotIndex + 1, end);
|
||||
arr = full_sorted;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A function utility to generate unsorted array of given size and range.
|
||||
* @tparam size Size of the output array.
|
||||
* @param from Stating of the range.
|
||||
* @param to Ending of the range.
|
||||
* @returns std::array<int64_t , size> Unsorted array of specified size.
|
||||
* */
|
||||
template <size_t size>
|
||||
std::array<int64_t, size> generateUnsortedArray(int64_t from, int64_t to) {
|
||||
srand(time(nullptr));
|
||||
std::array<int64_t, size> unsortedArray{};
|
||||
assert(from < to);
|
||||
int64_t i = 0;
|
||||
while (i < size) {
|
||||
int64_t randomNum = from + rand() % (to - from + 1);
|
||||
if (randomNum) {
|
||||
unsortedArray[i] = randomNum;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return unsortedArray;
|
||||
}
|
||||
|
||||
} // namespace random_pivot_quick_sort
|
||||
} // namespace sorting
|
||||
@@ -159,23 +179,23 @@ namespace sorting {
|
||||
* @brief a class containing the necessary test cases
|
||||
*/
|
||||
class TestCases {
|
||||
private:
|
||||
private:
|
||||
/**
|
||||
* @brief A function to print64_t given message on console.
|
||||
* @tparam T Type of the given message.
|
||||
* @returns void
|
||||
* */
|
||||
template<typename T>
|
||||
* @brief A function to print64_t given message on console.
|
||||
* @tparam T Type of the given message.
|
||||
* @returns void
|
||||
* */
|
||||
template <typename T>
|
||||
void log(T msg) {
|
||||
// It's just to avoid writing cout and endl
|
||||
std::cout << "[TESTS] : ---> " << msg << std::endl;
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* @brief Executes test cases
|
||||
* @returns void
|
||||
* */
|
||||
* @brief Executes test cases
|
||||
* @returns void
|
||||
* */
|
||||
void runTests() {
|
||||
log("Running Tests...");
|
||||
|
||||
@@ -188,24 +208,25 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A test case with single input
|
||||
* @returns void
|
||||
* */
|
||||
* @brief A test case with single input
|
||||
* @returns void
|
||||
* */
|
||||
void testCase_1() {
|
||||
const int64_t inputSize = 1;
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
"~");
|
||||
log("This is test case 1 for Random Pivot Quick Sort Algorithm : ");
|
||||
log("Description:");
|
||||
log(" EDGE CASE : Only contains one element");
|
||||
std::array<int64_t , inputSize> unsorted_arr{2};
|
||||
std::array<int64_t, inputSize> unsorted_arr{2};
|
||||
|
||||
int64_t start = 0;
|
||||
int64_t end = unsorted_arr.size() - 1; // length - 1
|
||||
int64_t end = unsorted_arr.size() - 1; // length - 1
|
||||
|
||||
log("Running algorithm of data of length 50 ...");
|
||||
std::array<int64_t , unsorted_arr.size()> sorted_arr = sorting::random_pivot_quick_sort::quickSortRP(
|
||||
unsorted_arr, start, end
|
||||
);
|
||||
std::array<int64_t, unsorted_arr.size()> sorted_arr =
|
||||
sorting::random_pivot_quick_sort::quickSortRP(unsorted_arr, start,
|
||||
end);
|
||||
log("Algorithm finished!");
|
||||
|
||||
log("Checking assert expression...");
|
||||
@@ -213,28 +234,32 @@ public:
|
||||
log("Assertion check passed!");
|
||||
|
||||
log("[PASS] : TEST CASE 1 PASS!");
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
"~");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A test case with input array of length 500
|
||||
* @returns void
|
||||
* */
|
||||
* @brief A test case with input array of length 500
|
||||
* @returns void
|
||||
* */
|
||||
void testCase_2() {
|
||||
const int64_t inputSize = 500;
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
"~");
|
||||
log("Description:");
|
||||
log(" BIG INPUT : Contains 500 elements and repeated elements");
|
||||
log("This is test case 2 for Random Pivot Quick Sort Algorithm : ");
|
||||
std::array<int64_t , inputSize> unsorted_arr = sorting::random_pivot_quick_sort::generateUnsortedArray<inputSize>(1, 10000);
|
||||
std::array<int64_t, inputSize> unsorted_arr =
|
||||
sorting::random_pivot_quick_sort::generateUnsortedArray<inputSize>(
|
||||
1, 10000);
|
||||
|
||||
int64_t start = 0;
|
||||
int64_t end = unsorted_arr.size() - 1; // length - 1
|
||||
int64_t end = unsorted_arr.size() - 1; // length - 1
|
||||
|
||||
log("Running algorithm of data of length 500 ...");
|
||||
std::array<int64_t , unsorted_arr.size()> sorted_arr = sorting::random_pivot_quick_sort::quickSortRP(
|
||||
unsorted_arr, start, end
|
||||
);
|
||||
std::array<int64_t, unsorted_arr.size()> sorted_arr =
|
||||
sorting::random_pivot_quick_sort::quickSortRP(unsorted_arr, start,
|
||||
end);
|
||||
log("Algorithm finished!");
|
||||
|
||||
log("Checking assert expression...");
|
||||
@@ -242,28 +267,32 @@ public:
|
||||
log("Assertion check passed!");
|
||||
|
||||
log("[PASS] : TEST CASE 2 PASS!");
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
"~");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A test case with array of length 1000.
|
||||
* @returns void
|
||||
* */
|
||||
* @brief A test case with array of length 1000.
|
||||
* @returns void
|
||||
* */
|
||||
void testCase_3() {
|
||||
const int64_t inputSize = 1000;
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
"~");
|
||||
log("This is test case 3 for Random Pivot Quick Sort Algorithm : ");
|
||||
log("Description:");
|
||||
log(" LARGE INPUT : Contains 1000 elements and repeated elements");
|
||||
std::array<int64_t , inputSize> unsorted_arr = sorting::random_pivot_quick_sort::generateUnsortedArray<inputSize>(1, 10000);
|
||||
std::array<int64_t, inputSize> unsorted_arr =
|
||||
sorting::random_pivot_quick_sort::generateUnsortedArray<inputSize>(
|
||||
1, 10000);
|
||||
|
||||
int64_t start = 0;
|
||||
int64_t end = unsorted_arr.size() - 1; // length - 1
|
||||
int64_t end = unsorted_arr.size() - 1; // length - 1
|
||||
|
||||
log("Running algorithm...");
|
||||
std::array<int64_t , unsorted_arr.size()> sorted_arr = sorting::random_pivot_quick_sort::quickSortRP(
|
||||
unsorted_arr, start, end
|
||||
);
|
||||
std::array<int64_t, unsorted_arr.size()> sorted_arr =
|
||||
sorting::random_pivot_quick_sort::quickSortRP(unsorted_arr, start,
|
||||
end);
|
||||
log("Algorithm finished!");
|
||||
|
||||
log("Checking assert expression...");
|
||||
@@ -271,11 +300,11 @@ public:
|
||||
log("Assertion check passed!");
|
||||
|
||||
log("[PASS] : TEST CASE 3 PASS!");
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
|
||||
"~");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @returns void
|
||||
@@ -292,17 +321,18 @@ static void test() {
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main(int argc, char *argv[]) {
|
||||
test(); // Executes various test cases.
|
||||
test(); // Executes various test cases.
|
||||
|
||||
const int64_t inputSize = 10;
|
||||
std::array<int64_t , inputSize> unsorted_array = sorting::random_pivot_quick_sort::generateUnsortedArray<inputSize>(50, 1000);
|
||||
std::array<int64_t, inputSize> unsorted_array =
|
||||
sorting::random_pivot_quick_sort::generateUnsortedArray<inputSize>(
|
||||
50, 1000);
|
||||
std::cout << "Unsorted array is : " << std::endl;
|
||||
sorting::random_pivot_quick_sort::showArray(unsorted_array);
|
||||
|
||||
std::array<int64_t , inputSize> sorted_array = sorting::random_pivot_quick_sort::quickSortRP(
|
||||
unsorted_array, 0,
|
||||
unsorted_array.size() - 1
|
||||
);
|
||||
std::array<int64_t, inputSize> sorted_array =
|
||||
sorting::random_pivot_quick_sort::quickSortRP(
|
||||
unsorted_array, 0, unsorted_array.size() - 1);
|
||||
std::cout << "Sorted array is : " << std::endl;
|
||||
sorting::random_pivot_quick_sort::showArray(sorted_array);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user