mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
Merge branch 'master' into fixgraph
This commit is contained in:
commit
c107f99db9
@ -5,5 +5,7 @@ RUN sudo apt-get update \
|
||||
doxygen \
|
||||
graphviz \
|
||||
ninja-build \
|
||||
freeglut3 \
|
||||
freeglut3-dev \
|
||||
&& pip install cpplint \
|
||||
&& sudo rm -rf /var/lib/apt/lists/*
|
||||
|
@ -11,7 +11,10 @@
|
||||
* [Sudoku Solve](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/backtracking/sudoku_solve.cpp)
|
||||
|
||||
## Ciphers
|
||||
* [Caesar Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/caesar_cipher.cpp)
|
||||
* [Hill Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/hill_cipher.cpp)
|
||||
* [Vigenere Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/vigenere_cipher.cpp)
|
||||
* [Xor Cipher](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/ciphers/xor_cipher.cpp)
|
||||
|
||||
## Data Structures
|
||||
* [Avltree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/avltree.cpp)
|
||||
@ -33,6 +36,7 @@
|
||||
* [Queue Using Array2](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_array2.cpp)
|
||||
* [Queue Using Linked List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_linked_list.cpp)
|
||||
* [Queue Using Linkedlist](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_linkedlist.cpp)
|
||||
* [Queue Using Two Stacks](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/queue_using_two_stacks.cpp)
|
||||
* [Skip List](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/skip_list.cpp)
|
||||
* [Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/stack.h)
|
||||
* [Stack Using Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/stack_using_array.cpp)
|
||||
@ -215,12 +219,14 @@
|
||||
## Sorting
|
||||
* [Bead Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bead_sort.cpp)
|
||||
* [Bitonic Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bitonic_sort.cpp)
|
||||
* [Bogo Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bogo_sort.cpp)
|
||||
* [Bubble Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bubble_sort.cpp)
|
||||
* [Bucket Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/bucket_sort.cpp)
|
||||
* [Cocktail Selection Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/cocktail_selection_sort.cpp)
|
||||
* [Comb Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/comb_sort.cpp)
|
||||
* [Counting Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/counting_sort.cpp)
|
||||
* [Counting Sort String](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/counting_sort_string.cpp)
|
||||
* [Gnome Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/gnome_sort.cpp)
|
||||
* [Heap Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/heap_sort.cpp)
|
||||
* [Insertion Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/insertion_sort.cpp)
|
||||
* [Library Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/library_sort.cpp)
|
||||
@ -229,6 +235,7 @@
|
||||
* [Numeric String Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/numeric_string_sort.cpp)
|
||||
* [Odd Even Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/odd_even_sort.cpp)
|
||||
* [Quick Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/quick_sort.cpp)
|
||||
* [Quick Sort 3](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/quick_sort_3.cpp)
|
||||
* [Radix Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/radix_sort.cpp)
|
||||
* [Selection Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/selection_sort.cpp)
|
||||
* [Shell Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/shell_sort.cpp)
|
||||
|
124
ciphers/caesar_cipher.cpp
Normal file
124
ciphers/caesar_cipher.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* @file caesar_cipher.cpp
|
||||
* @brief Implementation of [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) algorithm.
|
||||
*
|
||||
* @details
|
||||
* In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher,
|
||||
* Caesar's code or Caesar shift, is one of the simplest and most widely known encryption
|
||||
* techniques. It is a type of substitution cipher in which each letter in the plaintext
|
||||
* is replaced by a letter some fixed number of positions down the alphabet. For example,
|
||||
* with a left shift of 3, D would be replaced by A, E would become B, and so on.
|
||||
* The method is named after Julius Caesar, who used it in his private correspondence.
|
||||
*
|
||||
* ### Algorithm
|
||||
* The encryption can also be represented using modular arithmetic by first transforming
|
||||
* the letters into numbers, according to the scheme, A → 0, B → 1, ..., Z → 25.
|
||||
* Encryption of a letter x by a shift n can be described mathematically as,
|
||||
* \f[ E(x) = (x + n)\;\mbox{mod}\; 26\f]
|
||||
* while decryption can be described as,
|
||||
* \f[ D(x) = (x - n) \;\mbox{mod}\; 26\f]
|
||||
*
|
||||
* \note This program implements caesar cipher for only uppercase English alphabet characters (i.e. A-Z).
|
||||
*
|
||||
* @author [Deep Raval](https://github.com/imdeep2905)
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
/** \namespace ciphers
|
||||
* \brief Algorithms for encryption and decryption
|
||||
*/
|
||||
namespace ciphers {
|
||||
/** \namespace caesar
|
||||
* \brief Functions for [Caesar cipher](https://en.wikipedia.org/wiki/Caesar_cipher) algorithm.
|
||||
*/
|
||||
namespace caesar {
|
||||
namespace {
|
||||
/**
|
||||
* This function finds character for given value (i.e.A-Z)
|
||||
* @param x value for which we want character
|
||||
* @returns corresponding character for perticular value
|
||||
*/
|
||||
inline char get_char(const int x) {
|
||||
// By adding 65 we are scaling 0-25 to 65-90.
|
||||
// Which are in fact ASCII values of A-Z.
|
||||
return char(x + 65);
|
||||
}
|
||||
/**
|
||||
* This function finds value for given character (i.e.0-25)
|
||||
* @param c character for which we want value
|
||||
* @returns returns corresponding value for perticular character
|
||||
*/
|
||||
inline int get_value(const char c) {
|
||||
// A-Z have ASCII values in range 65-90.
|
||||
// Hence subtracting 65 will scale them to 0-25.
|
||||
return int(c - 65);
|
||||
}
|
||||
} // Unnamed namespace
|
||||
/**
|
||||
* Encrypt given text using caesar cipher.
|
||||
* @param text text to be encrypted
|
||||
* @param shift number of shifts to be applied
|
||||
* @returns new encrypted text
|
||||
*/
|
||||
std::string encrypt (const std::string &text, const int &shift) {
|
||||
std::string encrypted_text = ""; // Empty string to store encrypted text
|
||||
for (char c : text) { // Going through each character
|
||||
int place_value = get_value(c); // Getting value of character (i.e. 0-25)
|
||||
place_value = (place_value + shift) % 26; // Applying encryption formula
|
||||
char new_char = get_char(place_value); // Getting new character from new value (i.e. A-Z)
|
||||
encrypted_text += new_char; // Appending encrypted character
|
||||
}
|
||||
return encrypted_text; // Returning encrypted text
|
||||
}
|
||||
/**
|
||||
* Decrypt given text using caesar cipher.
|
||||
* @param text text to be decrypted
|
||||
* @param shift number of shifts to be applied
|
||||
* @returns new decrypted text
|
||||
*/
|
||||
std::string decrypt (const std::string &text, const int &shift) {
|
||||
std::string decrypted_text = ""; // Empty string to store decrypted text
|
||||
for (char c : text) { // Going through each character
|
||||
int place_value = get_value(c); // Getting value of character (i.e. 0-25)
|
||||
place_value = (place_value - shift) % 26;// Applying decryption formula
|
||||
if(place_value < 0) { // Handling case where remainder is negative
|
||||
place_value = place_value + 26;
|
||||
}
|
||||
char new_char = get_char(place_value); // Getting original character from decrypted value (i.e. A-Z)
|
||||
decrypted_text += new_char; // Appending decrypted character
|
||||
}
|
||||
return decrypted_text; // Returning decrypted text
|
||||
}
|
||||
} // namespace caesar
|
||||
} // namespace ciphers
|
||||
|
||||
/**
|
||||
* Function to test above algorithm
|
||||
*/
|
||||
void test() {
|
||||
// Test 1
|
||||
std::string text1 = "ALANTURING";
|
||||
std::string encrypted1 = ciphers::caesar::encrypt(text1, 17);
|
||||
std::string decrypted1 = ciphers::caesar::decrypt(encrypted1, 17);
|
||||
assert(text1 == decrypted1);
|
||||
std::cout << "Original text : " << text1;
|
||||
std::cout << " , Encrypted text (with shift = 21) : " << encrypted1;
|
||||
std::cout << " , Decrypted text : "<< decrypted1 << std::endl;
|
||||
// Test 2
|
||||
std::string text2 = "HELLOWORLD";
|
||||
std::string encrypted2 = ciphers::caesar::encrypt(text2, 1729);
|
||||
std::string decrypted2 = ciphers::caesar::decrypt(encrypted2, 1729);
|
||||
assert(text2 == decrypted2);
|
||||
std::cout << "Original text : " << text2;
|
||||
std::cout << " , Encrypted text (with shift = 1729) : " << encrypted2;
|
||||
std::cout << " , Decrypted text : "<< decrypted2 << std::endl;
|
||||
}
|
||||
|
||||
/** Driver Code */
|
||||
int main() {
|
||||
// Testing
|
||||
test();
|
||||
return 0;
|
||||
}
|
135
ciphers/vigenere_cipher.cpp
Normal file
135
ciphers/vigenere_cipher.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/**
|
||||
* @file vigenere_cipher.cpp
|
||||
* @brief Implementation of [Vigenère cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) algorithm.
|
||||
*
|
||||
* @details
|
||||
* The Vigenère cipher is a method of encrypting alphabetic text by using a series of interwoven vigenere
|
||||
* ciphers, based on the letters of a keyword. It employs a form of polyalphabetic substitution.
|
||||
*
|
||||
* ### Algorithm
|
||||
* The encryption can also be represented using modular arithmetic by first transforming
|
||||
* the letters into numbers, according to the scheme, A → 0, B → 1, ..., Z → 25.
|
||||
* Encryption of \f$i^{th}\f$ character in Message M by key K can be described mathematically as,
|
||||
*
|
||||
* \f[ E_{K}(M_{i}) = (M_{i} + K_{i})\;\mbox{mod}\; 26\f]
|
||||
*
|
||||
* while decryption of \f$i^{th}\f$ character in Cipher C by key K can be described mathematically as,
|
||||
*
|
||||
* \f[ D_{k}(C_{i}) = (C_{i} - K_{i} + 26)\;\mbox{mod}\; 26\f]
|
||||
*
|
||||
* Where \f$K_{i}\f$ denotes corresponding character in key. If \f$|key| < |text|\f$ than
|
||||
* same key is repeated untill their lengths are equal.
|
||||
*
|
||||
* For Example,
|
||||
* If M = "ATTACKATDAWN" and K = "LEMON" than K becomes "LEMONLEMONLE".
|
||||
*
|
||||
* \note Rather than creating new key of equal length this program does this by using modular index for key
|
||||
* (i.e. \f$(j + 1) \;\mbox{mod}\; |\mbox{key}|\f$)
|
||||
*
|
||||
* \note This program implements Vigenère cipher for only uppercase English alphabet characters (i.e. A-Z).
|
||||
*
|
||||
* @author [Deep Raval](https://github.com/imdeep2905)
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
/** \namespace ciphers
|
||||
* \brief Algorithms for encryption and decryption
|
||||
*/
|
||||
namespace ciphers {
|
||||
/** \namespace vigenere
|
||||
* \brief Functions for [vigenère cipher](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) algorithm.
|
||||
*/
|
||||
namespace vigenere {
|
||||
namespace {
|
||||
/**
|
||||
* This function finds character for given value (i.e.A-Z)
|
||||
* @param x value for which we want character
|
||||
* @return corresponding character for perticular value
|
||||
*/
|
||||
inline char get_char(const int x) {
|
||||
// By adding 65 we are scaling 0-25 to 65-90.
|
||||
// Which are in fact ASCII values of A-Z.
|
||||
return char(x + 65);
|
||||
}
|
||||
/**
|
||||
* This function finds value for given character (i.e.0-25)
|
||||
* @param c character for which we want value
|
||||
* @return returns corresponding value for perticular character
|
||||
*/
|
||||
inline int get_value(const char c) {
|
||||
// A-Z have ASCII values in range 65-90.
|
||||
// Hence subtracting 65 will scale them to 0-25.
|
||||
return int(c - 65);
|
||||
}
|
||||
} // Unnamed namespace
|
||||
/**
|
||||
* Encrypt given text using vigenere cipher.
|
||||
* @param text text to be encrypted
|
||||
* @param key to be used for encryption
|
||||
* @return new encrypted text
|
||||
*/
|
||||
std::string encrypt (const std::string &text, const std::string &key) {
|
||||
std::string encrypted_text = ""; // Empty string to store encrypted text
|
||||
// Going through each character of text and key
|
||||
// Note that key is visited in circular way hence j = (j + 1) % |key|
|
||||
for(size_t i = 0, j = 0; i < text.length(); i++, j = (j + 1) % key.length()) {
|
||||
int place_value_text = get_value(text[i]); // Getting value of character in text
|
||||
int place_value_key = get_value(key[j]); // Getting value of character in key
|
||||
place_value_text = (place_value_text + place_value_key) % 26; // Applying encryption
|
||||
char encrypted_char = get_char(place_value_text); // Getting new character from encrypted value
|
||||
encrypted_text += encrypted_char; // Appending encrypted character
|
||||
}
|
||||
return encrypted_text; // Returning encrypted text
|
||||
}
|
||||
/**
|
||||
* Decrypt given text using vigenere cipher.
|
||||
* @param text text to be decrypted
|
||||
* @param key key to be used for decryption
|
||||
* @return new decrypted text
|
||||
*/
|
||||
std::string decrypt (const std::string &text, const std::string &key) {
|
||||
// Going through each character of text and key
|
||||
// Note that key is visited in circular way hence j = (j + 1) % |key|
|
||||
std::string decrypted_text = ""; // Empty string to store decrypted text
|
||||
for(size_t i = 0, j = 0; i < text.length(); i++, j = (j + 1) % key.length()) {
|
||||
int place_value_text = get_value(text[i]); // Getting value of character in text
|
||||
int place_value_key = get_value(key[j]); // Getting value of character in key
|
||||
place_value_text = (place_value_text - place_value_key + 26) % 26; // Applying decryption
|
||||
char decrypted_char = get_char(place_value_text); // Getting new character from decrypted value
|
||||
decrypted_text += decrypted_char; // Appending decrypted character
|
||||
}
|
||||
return decrypted_text; // Returning decrypted text
|
||||
}
|
||||
} // namespace vigenere
|
||||
} // namespace ciphers
|
||||
|
||||
/**
|
||||
* Function to test above algorithm
|
||||
*/
|
||||
void test() {
|
||||
// Test 1
|
||||
std::string text1 = "NIKOLATESLA";
|
||||
std::string encrypted1 = ciphers::vigenere::encrypt(text1, "TESLA");
|
||||
std::string decrypted1 = ciphers::vigenere::decrypt(encrypted1, "TESLA");
|
||||
assert(text1 == decrypted1);
|
||||
std::cout << "Original text : " << text1;
|
||||
std::cout << " , Encrypted text (with key = TESLA) : " << encrypted1;
|
||||
std::cout << " , Decrypted text : "<< decrypted1 << std::endl;
|
||||
// Test 2
|
||||
std::string text2 = "GOOGLEIT";
|
||||
std::string encrypted2 = ciphers::vigenere::encrypt(text2, "REALLY");
|
||||
std::string decrypted2 = ciphers::vigenere::decrypt(encrypted2, "REALLY");
|
||||
assert(text2 == decrypted2);
|
||||
std::cout << "Original text : " << text2;
|
||||
std::cout << " , Encrypted text (with key = REALLY) : " << encrypted2;
|
||||
std::cout << " , Decrypted text : "<< decrypted2 << std::endl;
|
||||
}
|
||||
|
||||
/** Driver Code */
|
||||
int main() {
|
||||
// Testing
|
||||
test();
|
||||
return 0;
|
||||
}
|
99
ciphers/xor_cipher.cpp
Normal file
99
ciphers/xor_cipher.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @file xor_cipher.cpp
|
||||
* @brief Implementation of [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher) algorithm.
|
||||
*
|
||||
* @details
|
||||
* In cryptography, the simple XOR cipher is a type of additive cipher, an encryption
|
||||
* algorithm that operates according to the principles:
|
||||
*
|
||||
* * \f$A {\oplus} 0 = A\f$
|
||||
* * \f$A {\oplus} A = 0\f$
|
||||
* * \f$ (A {\oplus} B) {\oplus} C = A {\oplus} (B {\oplus} C)\f$
|
||||
* * \f$ (B {\oplus} A) {\oplus} B = B {\oplus} 0 = B \f$
|
||||
*
|
||||
*
|
||||
* where \f$\oplus\f$ symbol denotes the exclusive disjunction (XOR) operation.
|
||||
* This operation is sometimes called modulus 2 addition (or subtraction, which is identical).
|
||||
* With this logic, a string of text can be encrypted by applying the bitwise XOR operator to
|
||||
* every character using a given key. To decrypt the output, merely reapplying the XOR function
|
||||
* with the key will remove the cipher.
|
||||
*
|
||||
* ### Algorithm
|
||||
* Choose the key for encryption and apply XOR operation to each character of a string.
|
||||
* Reapplying XOR operation to each character of encrypted string will give original string back.
|
||||
*
|
||||
* \note This program implements XOR Cipher for string with ASCII characters.
|
||||
*
|
||||
* @author [Deep Raval](https://github.com/imdeep2905)
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
/** \namespace ciphers
|
||||
* \brief Algorithms for encryption and decryption
|
||||
*/
|
||||
namespace ciphers {
|
||||
/** \namespace XOR
|
||||
* \brief Functions for [XOR cipher](https://en.wikipedia.org/wiki/XOR_cipher) algorithm.
|
||||
*/
|
||||
namespace XOR {
|
||||
/**
|
||||
* Encrypt given text using XOR cipher.
|
||||
* @param text text to be encrypted
|
||||
* @param key to be used for encyption
|
||||
* @return new encrypted text
|
||||
*/
|
||||
std::string encrypt (const std::string &text, const int &key) {
|
||||
std::string encrypted_text = ""; // Empty string to store encrypted text
|
||||
for (auto &c: text) { // Going through each character
|
||||
char encrypted_char = char(c ^ key); // Applying encyption
|
||||
encrypted_text += encrypted_char; // Appending encrypted character
|
||||
}
|
||||
return encrypted_text; // Returning encrypted text
|
||||
}
|
||||
/**
|
||||
* Decrypt given text using XOR cipher.
|
||||
* @param text text to be encrypted
|
||||
* @param key to be used for decryption
|
||||
* @return new decrypted text
|
||||
*/
|
||||
std::string decrypt (const std::string &text, const int &key) {
|
||||
std::string decrypted_text = ""; // Empty string to store decrypted text
|
||||
for (auto &c : text) { // Going through each character
|
||||
char decrypted_char = char(c ^ key); // Applying decryption
|
||||
decrypted_text += decrypted_char; // Appending decrypted character
|
||||
}
|
||||
return decrypted_text; // Returning decrypted text
|
||||
}
|
||||
} // namespace XOR
|
||||
} // namespace ciphers
|
||||
|
||||
/**
|
||||
* Function to test above algorithm
|
||||
*/
|
||||
void test() {
|
||||
// Test 1
|
||||
std::string text1 = "Whipalsh! : Do watch this movie...";
|
||||
std::string encrypted1 = ciphers::XOR::encrypt(text1, 17);
|
||||
std::string decrypted1 = ciphers::XOR::decrypt(encrypted1, 17);
|
||||
assert(text1 == decrypted1);
|
||||
std::cout << "Original text : " << text1;
|
||||
std::cout << " , Encrypted text (with key = 17) : " << encrypted1;
|
||||
std::cout << " , Decrypted text : "<< decrypted1 << std::endl;
|
||||
// Test 2
|
||||
std::string text2 = "->Valar M0rghulis<-";
|
||||
std::string encrypted2 = ciphers::XOR::encrypt(text2, 29);
|
||||
std::string decrypted2 = ciphers::XOR::decrypt(encrypted2, 29);
|
||||
assert(text2 == decrypted2);
|
||||
std::cout << "Original text : " << text2;
|
||||
std::cout << " , Encrypted text (with key = 29) : " << encrypted2;
|
||||
std::cout << " , Decrypted text : "<< decrypted2 << std::endl;
|
||||
}
|
||||
|
||||
/** Driver Code */
|
||||
int main() {
|
||||
// Testing
|
||||
test();
|
||||
return 0;
|
||||
}
|
144
data_structures/queue_using_two_stacks.cpp
Normal file
144
data_structures/queue_using_two_stacks.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @author [shoniavika](https://github.com/shoniavika)
|
||||
* @file
|
||||
*
|
||||
* Implementation of a Queue using two Stacks.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <stack>
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* @brief Queue data structure. Stores elements in FIFO
|
||||
* (first-in-first-out) manner.
|
||||
* @tparam T datatype to store in the queue
|
||||
*/
|
||||
template <typename T>
|
||||
class MyQueue {
|
||||
private:
|
||||
std::stack<T> s1, s2;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor for queue.
|
||||
*/
|
||||
MyQueue() = default;
|
||||
|
||||
/**
|
||||
* Pushes x to the back of queue.
|
||||
*/
|
||||
void push(T x);
|
||||
|
||||
/**
|
||||
* Removes an element from the front of the queue.
|
||||
*/
|
||||
const T& pop();
|
||||
|
||||
/**
|
||||
* Returns first element, without removing it.
|
||||
*/
|
||||
const T& peek() const;
|
||||
|
||||
/**
|
||||
* Returns whether the queue is empty.
|
||||
*/
|
||||
bool empty() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends element to the end of the queue
|
||||
*/
|
||||
template <typename T>
|
||||
void MyQueue<T>::push(T x) {
|
||||
while (!s2.empty()) {
|
||||
s1.push(s2.top());
|
||||
s2.pop();
|
||||
}
|
||||
s2.push(x);
|
||||
while (!s1.empty()) {
|
||||
s2.push(s1.top());
|
||||
s1.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes element from the front of the queue
|
||||
*/
|
||||
template <typename T>
|
||||
const T& MyQueue<T>::pop() {
|
||||
const T& temp = MyQueue::peek();
|
||||
s2.pop();
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns element in the front.
|
||||
* Does not remove it.
|
||||
*/
|
||||
template <typename T>
|
||||
const T& MyQueue<T>::peek() const {
|
||||
if (!empty()) {
|
||||
return s2.top();
|
||||
}
|
||||
std::cerr << "Queue is empty" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a queue is empty
|
||||
*/
|
||||
template <typename T>
|
||||
bool MyQueue<T>::empty() const {
|
||||
return s2.empty() && s1.empty();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* Testing function
|
||||
*/
|
||||
void queue_test() {
|
||||
MyQueue<int> que;
|
||||
std::cout << "Test #1\n";
|
||||
que.push(2);
|
||||
que.push(5);
|
||||
que.push(0);
|
||||
assert(que.peek() == 2);
|
||||
assert(que.pop() == 2);
|
||||
assert(que.peek() == 5);
|
||||
assert(que.pop() == 5);
|
||||
assert(que.peek() == 0);
|
||||
assert(que.pop() == 0);
|
||||
assert(que.empty() == true);
|
||||
std::cout << "PASSED\n";
|
||||
|
||||
std::cout << "Test #2\n";
|
||||
que.push(-1);
|
||||
assert(que.empty() == false);
|
||||
assert(que.peek() == -1);
|
||||
assert(que.pop() == -1);
|
||||
std::cout << "PASSED\n";
|
||||
|
||||
MyQueue<double> que2;
|
||||
std::cout << "Test #3\n";
|
||||
que2.push(2.31223);
|
||||
que2.push(3.1415926);
|
||||
que2.push(2.92);
|
||||
|
||||
assert(que2.peek() == 2.31223);
|
||||
assert(que2.pop() == 2.31223);
|
||||
assert(que2.peek() == 3.1415926);
|
||||
assert(que2.pop() == 3.1415926);
|
||||
assert(que2.peek() == 2.92);
|
||||
assert(que2.pop() == 2.92);
|
||||
std::cout << "PASSED\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function, calls testing function
|
||||
*/
|
||||
int main() {
|
||||
queue_test();
|
||||
return 0;
|
||||
}
|
@ -26,12 +26,12 @@ unsigned int gcd(unsigned int x, unsigned int y) {
|
||||
if (x > y) {
|
||||
// The following is valid because we have checked whether y == 0
|
||||
|
||||
int temp = x / y;
|
||||
unsigned int temp = x / y;
|
||||
return gcd(y, x - temp * y);
|
||||
}
|
||||
// Again the following is valid because we have checked whether x == 0
|
||||
|
||||
int temp = y / x;
|
||||
unsigned int temp = y / x;
|
||||
return gcd(x, y - temp * x);
|
||||
}
|
||||
|
||||
@ -40,7 +40,9 @@ unsigned int gcd(unsigned int x, unsigned int y) {
|
||||
* @params integer x and y whose lcm we want to find.
|
||||
* @return lcm of x and y using the relation x * y = gcd(x, y) * lcm(x, y)
|
||||
*/
|
||||
unsigned int lcm(unsigned int x, unsigned int y) { return x * y / gcd(x, y); }
|
||||
unsigned int lcm(unsigned int x, unsigned int y) {
|
||||
return x / gcd(x, y) * y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for testing the lcm() functions with some assert statements.
|
||||
@ -59,6 +61,15 @@ void tests() {
|
||||
lcm(2, 3) == 6));
|
||||
std::cout << "Second assertion passes: LCM of 2 and 3 is " << lcm(2, 3)
|
||||
<< std::endl;
|
||||
|
||||
// Testing an integer overflow.
|
||||
// The algorithm should work as long as the result fits into integer.
|
||||
assert(((void)"LCM of 987654321 and 987654321 is 987654321 but lcm function"
|
||||
" gives a different result.\n",
|
||||
lcm(987654321, 987654321) == 987654321));
|
||||
std::cout << "Third assertion passes: LCM of 987654321 and 987654321 is "
|
||||
<< lcm(987654321, 987654321)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,58 +1,72 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Get list of prime numbers using Sieve of Eratosthenes
|
||||
* Sieve of Eratosthenes is an algorithm to find the primes
|
||||
* that is between 2 to N (as defined in main).
|
||||
* @details
|
||||
* Sieve of Eratosthenes is an algorithm that finds all the primes
|
||||
* between 2 and N.
|
||||
*
|
||||
* Time Complexity : \f$O(N \cdot\log N)\f$
|
||||
* Time Complexity : \f$O(N \cdot\log \log N)\f$
|
||||
* <br/>Space Complexity : \f$O(N)\f$
|
||||
*
|
||||
* @see primes_up_to_billion.cpp prime_numbers.cpp
|
||||
*/
|
||||
|
||||
#include <iostream> // for io operations
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* This is the function that finds the primes and eliminates
|
||||
* the multiples.
|
||||
* This is the function that finds the primes and eliminates the multiples.
|
||||
* Contains a common optimization to start eliminating multiples of
|
||||
* a prime p starting from p * p since all of the lower multiples
|
||||
* have been already eliminated.
|
||||
* @param N number of primes to check
|
||||
* @param [out] isprime a boolean array of size `N` identifying if `i`^th number is prime or not
|
||||
* @return is_prime a vector of `N + 1` booleans identifying if `i`^th number is a prime or not
|
||||
*/
|
||||
void sieve(uint32_t N, bool *isprime) {
|
||||
isprime[0] = true;
|
||||
isprime[1] = true;
|
||||
std::vector<bool> sieve(uint32_t N) {
|
||||
std::vector<bool> is_prime(N + 1, true);
|
||||
is_prime[0] = is_prime[1] = false;
|
||||
for (uint32_t i = 2; i * i <= N; i++) {
|
||||
if (!isprime[i]) {
|
||||
for (uint32_t j = (i << 1); j <= N; j = j + i) {
|
||||
isprime[j] = true;
|
||||
if (is_prime[i]) {
|
||||
for (uint32_t j = i * i; j <= N; j += i) {
|
||||
is_prime[j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return is_prime;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function prints out the primes to STDOUT
|
||||
* @param N number of primes to check
|
||||
* @param [in] isprime a boolean array of size `N` identifying if `i`^th number is prime or not
|
||||
* @param is_prime a vector of `N + 1` booleans identifying if `i`^th number is a prime or not
|
||||
*/
|
||||
void print(uint32_t N, const bool *isprime) {
|
||||
void print(uint32_t N, const std::vector<bool> &is_prime) {
|
||||
for (uint32_t i = 2; i <= N; i++) {
|
||||
if (!isprime[i]) {
|
||||
if (is_prime[i]) {
|
||||
std::cout << i << ' ';
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test implementations
|
||||
*/
|
||||
void tests() {
|
||||
// 0 1 2 3 4 5 6 7 8 9 10
|
||||
std::vector<bool> ans{false, false, true, true, false, true, false, true, false, false, false};
|
||||
assert(sieve(10) == ans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*/
|
||||
int main() {
|
||||
uint32_t N = 100;
|
||||
bool *isprime = new bool[N];
|
||||
sieve(N, isprime);
|
||||
print(N, isprime);
|
||||
delete[] isprime;
|
||||
tests();
|
||||
|
||||
uint32_t N = 100;
|
||||
std::vector<bool> is_prime = sieve(N);
|
||||
print(N, is_prime);
|
||||
return 0;
|
||||
}
|
||||
|
115
sorting/bogo_sort.cpp
Normal file
115
sorting/bogo_sort.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of [Bogosort algorithm](https://en.wikipedia.org/wiki/Bogosort)
|
||||
*
|
||||
* @details
|
||||
* In computer science, bogosort (also known as permutation sort, stupid sort, slowsort,
|
||||
* shotgun sort, random sort, monkey sort, bobosort or shuffle sort) is a highly inefficient
|
||||
* sorting algorithm based on the generate and test paradigm. Two versions of this algorithm
|
||||
* exist: a deterministic version that enumerates all permutations until it hits a sorted one,
|
||||
* and a randomized version that randomly permutes its input.Randomized version is implemented here.
|
||||
*
|
||||
* ### Algorithm
|
||||
* Shuffle the array untill array is sorted.
|
||||
*
|
||||
* @author [Deep Raval](https://github.com/imdeep2905)
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
/**
|
||||
* @namespace sorting
|
||||
* @brief Sorting algorithms
|
||||
*/
|
||||
namespace sorting {
|
||||
/**
|
||||
* Function to shuffle the elements of an array. (for reference)
|
||||
* @tparam T typename of the array
|
||||
* @tparam N length of array
|
||||
* @param arr array to shuffle
|
||||
* @returns new array with elements shuffled from a given array
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
std::array <T, N> shuffle (std::array <T, N> arr) {
|
||||
for (int i = 0; i < N; i++) {
|
||||
// Swaps i'th index with random index (less than array size)
|
||||
std::swap(arr[i], arr[std::rand() % N]);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
/**
|
||||
* Implement randomized Bogosort algorithm and sort the elements of a given array.
|
||||
* @tparam T typename of the array
|
||||
* @tparam N length of array
|
||||
* @param arr array to sort
|
||||
* @returns new array with elements sorted from a given array
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
std::array <T, N> randomized_bogosort (std::array <T, N> arr) {
|
||||
// Untill array is not sorted
|
||||
while (!std::is_sorted(arr.begin(), arr.end())) {
|
||||
std::random_shuffle(arr.begin(), arr.end());// Shuffle the array
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
} // namespace sorting
|
||||
|
||||
/**
|
||||
* Function to display array on screen
|
||||
* @tparam T typename of the array
|
||||
* @tparam N length of array
|
||||
* @param arr array to display
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
void show_array (const std::array <T, N> &arr) {
|
||||
for (int x : arr) {
|
||||
std::cout << x << ' ';
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to test above algorithm
|
||||
*/
|
||||
void test() {
|
||||
// Test 1
|
||||
std::array <int, 5> arr1;
|
||||
for (int &x : arr1) {
|
||||
x = std::rand() % 100;
|
||||
}
|
||||
std::cout << "Original Array : ";
|
||||
show_array(arr1);
|
||||
arr1 = sorting::randomized_bogosort(arr1);
|
||||
std::cout << "Sorted Array : ";
|
||||
show_array(arr1);
|
||||
assert(std::is_sorted(arr1.begin(), arr1.end()));
|
||||
// Test 2
|
||||
std::array <int, 5> arr2;
|
||||
for (int &x : arr2) {
|
||||
x = std::rand() % 100;
|
||||
}
|
||||
std::cout << "Original Array : ";
|
||||
show_array(arr2);
|
||||
arr2 = sorting::randomized_bogosort(arr2);
|
||||
std::cout << "Sorted Array : ";
|
||||
show_array(arr2);
|
||||
assert(std::is_sorted(arr2.begin(), arr2.end()));
|
||||
}
|
||||
|
||||
/** Driver Code */
|
||||
int main() {
|
||||
// Testing
|
||||
test();
|
||||
// Example Usage
|
||||
std::array <int, 5> arr = {3, 7, 10, 4, 1}; // Defining array which we want to sort
|
||||
std::cout << "Original Array : ";
|
||||
show_array(arr);
|
||||
arr = sorting::randomized_bogosort(arr); // Callling bogo sort on it
|
||||
std::cout << "Sorted Array : ";
|
||||
show_array(arr); // Printing sorted array
|
||||
return 0;
|
||||
}
|
133
sorting/gnome_sort.cpp
Normal file
133
sorting/gnome_sort.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation of [gnome
|
||||
* sort](https://en.wikipedia.org/wiki/Gnome_sort) algorithm.
|
||||
* @author [beqakd](https://github.com/beqakd)
|
||||
* @author [Krishna Vedala](https://github.com/kvedala)
|
||||
* @details
|
||||
* Gnome sort algorithm is not the best one but it is widely used.
|
||||
* The algorithm iteratively checks the order of pairs in the array. If they are
|
||||
* on right order it moves to the next successive pair, otherwise it swaps
|
||||
* elements. This operation is repeated until no more swaps are made thus
|
||||
* indicating the values to be in ascending order.
|
||||
*
|
||||
* The time Complexity of the algorithm is \f$O(n^2)\f$ and in some cases it
|
||||
* can be \f$O(n)\f$.
|
||||
*/
|
||||
|
||||
#include <algorithm> // for std::swap
|
||||
#include <array> // for std::array
|
||||
#include <cassert> // for assertions
|
||||
#include <iostream> // for io operations
|
||||
|
||||
/**
|
||||
* @namespace sorting
|
||||
* Sorting algorithms
|
||||
*/
|
||||
namespace sorting {
|
||||
/**
|
||||
* This implementation is for a C-style array input that gets modified in place.
|
||||
* @param [in,out] arr our array of elements.
|
||||
* @param size size of given array
|
||||
*/
|
||||
template <typename T>
|
||||
void gnomeSort(T *arr, int size) {
|
||||
// few easy cases
|
||||
if (size <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int index = 0; // initialize some variables.
|
||||
while (index < size) {
|
||||
// check for swap
|
||||
if ((index == 0) || (arr[index] >= arr[index - 1])) {
|
||||
index++;
|
||||
} else {
|
||||
std::swap(arr[index], arr[index - 1]); // swap
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation is for a C++-style array input. The function argument is
|
||||
* a pass-by-value and hence a copy of the array gets created which is then
|
||||
* modified by the function and returned.
|
||||
* @tparam T type of data variables in the array
|
||||
* @tparam size size of the array
|
||||
* @param [in] arr our array of elements.
|
||||
* @return array with elements sorted
|
||||
*/
|
||||
template <typename T, size_t size>
|
||||
std::array<T, size> gnomeSort(std::array<T, size> arr) {
|
||||
// few easy cases
|
||||
if (size <= 1) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
int index = 0; // initialize loop index
|
||||
while (index < size) {
|
||||
// check for swap
|
||||
if ((index == 0) || (arr[index] >= arr[index - 1])) {
|
||||
index++;
|
||||
} else {
|
||||
std::swap(arr[index], arr[index - 1]); // swap
|
||||
index--;
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
} // namespace sorting
|
||||
|
||||
/**
|
||||
* Test function
|
||||
*/
|
||||
static void test() {
|
||||
// Example 1. Creating array of int,
|
||||
std::cout << "Test 1 - as a C-array...";
|
||||
const int size = 6;
|
||||
std::array<int, size> arr = {-22, 100, 150, 35, -10, 99};
|
||||
sorting::gnomeSort(arr.data(),
|
||||
size); // pass array data as a C-style array pointer
|
||||
assert(std::is_sorted(std::begin(arr), std::end(arr)));
|
||||
std::cout << " Passed\n";
|
||||
for (int i = 0; i < size; i++) {
|
||||
std::cout << arr[i] << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example 2. Creating array of doubles.
|
||||
std::cout << "\nTest 2 - as a std::array...";
|
||||
std::array<double, size> double_arr = {-100.2, 10.2, 20.0, 9.0, 7.5, 7.2};
|
||||
std::array<double, size> sorted_arr = sorting::gnomeSort(double_arr);
|
||||
assert(std::is_sorted(std::begin(sorted_arr), std::end(sorted_arr)));
|
||||
std::cout << " Passed\n";
|
||||
for (int i = 0; i < size; i++) {
|
||||
std::cout << double_arr[i] << ", ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example 3. Creating random array of float.
|
||||
std::cout << "\nTest 3 - 200 random numbers as a std::array...";
|
||||
const int size2 = 200;
|
||||
std::array<float, size2> rand_arr{};
|
||||
|
||||
for (auto &a : rand_arr) {
|
||||
// generate random numbers between -5.0 and 4.99
|
||||
a = float(std::rand() % 1000 - 500) / 100.f;
|
||||
}
|
||||
|
||||
std::array<float, size2> float_arr = sorting::gnomeSort(rand_arr);
|
||||
assert(std::is_sorted(std::begin(float_arr), std::end(float_arr)));
|
||||
std::cout << " Passed\n";
|
||||
// for (int i = 0; i < size; i++) std::cout << double_arr[i] << ", ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Our main function with example of sort method.
|
||||
*/
|
||||
int main() {
|
||||
test();
|
||||
return 0;
|
||||
}
|
188
sorting/quick_sort_3.cpp
Normal file
188
sorting/quick_sort_3.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Implementation Details
|
||||
* @details Quick sort 3 works on Dutch National Flag Algorithm
|
||||
* The major difference between simple quicksort and quick sort 3 comes in the
|
||||
* function partition3 In quick_sort_partition3 we divide the vector/array into
|
||||
* 3 parts. quick sort 3 works faster in some cases as compared to simple
|
||||
* quicksort.
|
||||
* @author immortal-j
|
||||
* @author [Krishna Vedala](https://github/kvedala)
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* Operator to print the array.
|
||||
* @param out std::ostream object to write to
|
||||
* @param arr array to write
|
||||
*/
|
||||
template <typename T>
|
||||
std::ostream &operator<<(std::ostream &out, const std::vector<T> &arr) {
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
out << arr[i];
|
||||
if (i < arr.size() - 1) {
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* @namespace sorting
|
||||
* @brief Sorting Algorithms
|
||||
*/
|
||||
namespace sorting {
|
||||
namespace { // using un-named namespace here to prevent partition function
|
||||
// being visible to end-users
|
||||
/** This function partitions `arr[]` in three parts
|
||||
* 1. \f$arr[l\ldots i]\f$ contains all elements smaller than pivot
|
||||
* 2. \f$arr[(i+1)\ldots (j-1)]\f$ contains all occurrences of pivot
|
||||
* 3. \f$arr[j\ldots r]\f$ contains all elements greater than pivot
|
||||
* @tparam T type of data in the vector array
|
||||
* @param [in,out] arr vector array being partitioned
|
||||
* @param [in] low lower limit of window to partition
|
||||
* @param [in] high upper limit of window to partition
|
||||
* @param [out] i updated lower limit of partition
|
||||
* @param [out] j updated upper limit of partition
|
||||
*/
|
||||
template <typename T>
|
||||
void partition3(std::vector<T> *arr, int32_t low, int32_t high, int32_t *i,
|
||||
int32_t *j) {
|
||||
// To handle 2 elements
|
||||
if (high - low <= 1) {
|
||||
if ((*arr)[high] < (*arr)[low]) {
|
||||
std::swap((*arr)[high], (*arr)[low]);
|
||||
}
|
||||
*i = low;
|
||||
*j = high;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t mid = low;
|
||||
T pivot = (*arr)[high];
|
||||
while (mid <= high) {
|
||||
if ((*arr)[mid] < pivot) {
|
||||
std::swap((*arr)[low++], (*arr)[mid++]);
|
||||
} else if ((*arr)[mid] == pivot) {
|
||||
mid++;
|
||||
} else if ((*arr)[mid] > pivot) {
|
||||
std::swap((*arr)[mid], (*arr)[high--]);
|
||||
}
|
||||
}
|
||||
|
||||
// update i and j
|
||||
*i = low - 1;
|
||||
*j = mid; // or high-1
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/** 3-way partition based quick sort. This function accepts array pointer and
|
||||
* modified the input array.
|
||||
* @tparam T type of data in the vector array
|
||||
* @param [in,out] arr vector array to sort
|
||||
* @param [in] low lower limit of window to partition
|
||||
* @param [in] high upper limit of window to partition
|
||||
*/
|
||||
template <typename T>
|
||||
void quicksort(std::vector<T> *arr, int32_t low, int32_t high) {
|
||||
if (low >= high) { // 1 or 0 elements
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t i = 0, j = 0;
|
||||
|
||||
// i and j are passed as reference
|
||||
partition3(arr, low, high, &i, &j);
|
||||
|
||||
// Recur two halves
|
||||
quicksort(arr, low, i);
|
||||
quicksort(arr, j, high);
|
||||
}
|
||||
|
||||
/** 3-way partition based quick sort. This function accepts array by value and
|
||||
* creates a copy of it. The array copy gets sorted and returned by the
|
||||
* function.
|
||||
* @tparam T type of data in the vector array
|
||||
* @param [in] arr vector array to sort
|
||||
* @param [in] low lower limit of window to partition
|
||||
* @param [in] high upper limit of window to partition
|
||||
* @returns sorted array vector
|
||||
*/
|
||||
template <typename T>
|
||||
std::vector<T> quicksort(std::vector<T> arr, int32_t low, int32_t high) {
|
||||
if (low >= high) { // 1 or 0 elements
|
||||
return arr;
|
||||
}
|
||||
|
||||
int32_t i = 0, j = 0;
|
||||
|
||||
// i and j are passed as reference
|
||||
partition3(&arr, low, high, &i, &j);
|
||||
|
||||
// Recur two halves
|
||||
quicksort(&arr, low, i);
|
||||
quicksort(&arr, j, high);
|
||||
|
||||
return arr;
|
||||
}
|
||||
} // namespace sorting
|
||||
|
||||
/** Test function for integer type arrays */
|
||||
static void test_int() {
|
||||
std::cout << "\nTesting integer type arrays\n";
|
||||
|
||||
for (int num_tests = 1; num_tests < 21; num_tests++) {
|
||||
size_t size = std::rand() % 500;
|
||||
std::vector<int> arr(size);
|
||||
for (auto &a : arr) {
|
||||
a = std::rand() % 500 - 250; // random numbers between -250, 249
|
||||
}
|
||||
|
||||
std::cout << "Test " << num_tests << "\t Array size:" << size << "\t ";
|
||||
std::vector<int> sorted = sorting::quicksort(arr, 0, size - 1);
|
||||
if (size < 20) {
|
||||
std::cout << "\t Sorted Array is:\n\t";
|
||||
std::cout << sorted << "\n";
|
||||
}
|
||||
assert(std::is_sorted(std::begin(sorted), std::end(sorted)));
|
||||
std::cout << "\t Passed\n";
|
||||
}
|
||||
}
|
||||
|
||||
/** Test function for double type arrays */
|
||||
static void test_double() {
|
||||
std::cout << "\nTesting Double type arrays\n";
|
||||
for (int num_tests = 1; num_tests < 21; num_tests++) {
|
||||
size_t size = std::rand() % 500;
|
||||
std::vector<double> arr(size);
|
||||
for (auto &a : arr) {
|
||||
a = double(std::rand() % 500) -
|
||||
250.f; // random numbers between -250, 249
|
||||
a /= 100.f; // convert to -2.5 to 2.49
|
||||
}
|
||||
|
||||
std::cout << "Test " << num_tests << "\t Array size:" << size << "\t ";
|
||||
std::vector<double> sorted = sorting::quicksort(arr, 0, size - 1);
|
||||
if (size < 20) {
|
||||
std::cout << "\t Sorted Array is:\n\t";
|
||||
std::cout << sorted << "\n";
|
||||
}
|
||||
assert(std::is_sorted(std::begin(sorted), std::end(sorted)));
|
||||
std::cout << "\t Passed\n";
|
||||
}
|
||||
}
|
||||
|
||||
/** Driver program for above functions */
|
||||
int main() {
|
||||
std::srand(std::time(nullptr));
|
||||
test_int();
|
||||
test_double();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user