chore: import upstream snapshot with attribution
Awesome CI Workflow / Code Formatter (push) Waiting to run
Awesome CI Workflow / Compile checks (macOS-latest) (push) Blocked by required conditions
Awesome CI Workflow / Compile checks (ubuntu-latest) (push) Blocked by required conditions
Awesome CI Workflow / Compile checks (windows-latest) (push) Blocked by required conditions

This commit is contained in:
wehub-resource-sync
2026-07-13 12:37:28 +08:00
commit 29cfe479ab
432 changed files with 68491 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
# If necessary, use the RELATIVE flag, otherwise each source file may be listed
# with full pathname. RELATIVE may makes it easier to extract an executable name
# automatically.
file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp )
# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c )
# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES)
foreach( testsourcefile ${APP_SOURCES} )
# I used a simple string replace, to cut off .cpp.
string( REPLACE ".cpp" "" testname ${testsourcefile} )
add_executable( ${testname} ${testsourcefile} )
set_target_properties(${testname} PROPERTIES
LINKER_LANGUAGE CXX
CXX_STANDARD 14)
if(OpenMP_CXX_FOUND)
target_link_libraries(${testname} OpenMP::OpenMP_CXX)
endif()
install(TARGETS ${testname} DESTINATION "bin/sorting")
endforeach( testsourcefile ${APP_SOURCES} )
+56
View File
@@ -0,0 +1,56 @@
// C++ program to implement gravity/bead sort
#include <cstdio>
#include <cstring>
#define BEAD(i, j) beads[i * max + j]
// function to perform the above algorithm
void beadSort(int *a, int len) {
// Find the maximum element
int max = a[0];
for (int i = 1; i < len; i++)
if (a[i] > max)
max = a[i];
// allocating memory
unsigned char *beads = new unsigned char[max * len];
memset(beads, 0, static_cast<size_t>(max) * len);
// mark the beads
for (int i = 0; i < len; i++)
for (int j = 0; j < a[i]; j++) BEAD(i, j) = 1;
for (int j = 0; j < max; j++) {
// count how many beads are on each post
int sum = 0;
for (int i = 0; i < len; i++) {
sum += BEAD(i, j);
BEAD(i, j) = 0;
}
// Move beads down
for (int i = len - sum; i < len; i++) BEAD(i, j) = 1;
}
// Put sorted values in array using beads
for (int i = 0; i < len; i++) {
int j;
for (j = 0; j < max && BEAD(i, j); j++) {
}
a[i] = j;
}
delete[] beads;
}
// driver function to test the algorithm
int main() {
int a[] = {5, 3, 1, 7, 4, 1, 1, 20};
int len = sizeof(a) / sizeof(a[0]);
beadSort(a, len);
for (int i = 0; i < len; i++) printf("%d ", a[i]);
return 0;
}
+146
View File
@@ -0,0 +1,146 @@
/**
* \file
* \brief [Binary Insertion Sort Algorithm
* (Insertion Sort)](https://en.wikipedia.org/wiki/Insertion_sort)
*
* \details
* If the cost of comparisons exceeds the cost of swaps, as is the case for
* example with string keys stored by reference or with human interaction (such
* as choosing one of a pair displayed side-by-side), then using binary
* insertion sort may yield better performance. Binary insertion sort employs a
* binary search to determine the correct location to insert new elements, and
* therefore performs ⌈log2 n⌉ comparisons in the worst case. When each element
* in the array is searched for and inserted this is O(n log n). The algorithm
* as a whole still has a running time of O(n2) on average because of the series
* * of swaps required for each insertion. However it has several advantages
* such as
* 1. Easy to implement
* 2. For small set of data it is quite efficient
* 3. More efficient that other Quadratic complexity algorithms like
* Selection sort or bubble sort.
* 4. It is efficient to use it when the cost of comparison is high.
* 5. It's stable that is it does not change the relative order of
* elements with equal keys.
* 6. It can sort the array or list as it receives.
*
* Example execution steps:
* 1. Suppose initially we have
* \f{bmatrix}{40 &30 &20 &50 &10\f}
* 2. We start traversing from 40 till we reach 10
* when we reach at 30 we find that it is not at it's correct place so we take
* 30 and place it at a correct position thus the array will become
* \f{bmatrix}{30 &40 &20 &50 &10\f}
* 3. In the next iteration we are at 20 we find that this is also misplaced so
* we place it at the correct sorted position thus the array in this iteration
* becomes
* \f{bmatrix}{20 &30 &40 &50 &10\f}
* 4. We do not do anything with 50 and move on to the next iteration and
* select 10 which is misplaced and place it at correct position. Thus, we have
* \f{bmatrix}{10 &20 &30 &40 &50\f}
*/
#include <algorithm> /// for algorithm functions
#include <cassert> /// for assert
#include <iostream> /// for IO operations
#include <vector> /// for working with vectors
/**
* \namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* \brief Binary search function to find the most suitable pace for an element.
* \tparam T The generic data type.
* \param arr The actual vector in which we are searching a suitable place for
* the element. \param val The value for which suitable place is to be found.
* \param low The lower bound of the range we are searching in.
* \param high The upper bound of the range we are searching in.
* \returns the index of most suitable position of val.
*/
template <class T>
int64_t binary_search(std::vector<T> &arr, T val, int64_t low, int64_t high) {
if (high <= low) {
return (val > arr[low]) ? (low + 1) : low;
}
int64_t mid = low + (high - low) / 2;
if (arr[mid] > val) {
return binary_search(arr, val, low, mid - 1);
} else if (arr[mid] < val) {
return binary_search(arr, val, mid + 1, high);
} else {
return mid + 1;
}
}
/**
* \brief Insertion sort function to sort the vector.
* \tparam T The generic data type.
* \param arr The actual vector to sort.
* \returns Void.
*/
template <typename T>
void insertionSort_binsrch(std::vector<T> &arr) {
int64_t n = arr.size();
for (int64_t i = 1; i < n; i++) {
T key = arr[i];
int64_t j = i - 1;
int64_t loc = sorting::binary_search(arr, key, 0, j);
while (j >= loc) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}
} // namespace sorting
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
/* descriptions of the following test */
/* 1st test:
[5, -3, -1, -2, 7] returns [-3, -2, -1, 5, 7] */
std::vector<int64_t> arr1({5, -3, -1, -2, 7});
std::cout << "1st test... ";
sorting::insertionSort_binsrch(arr1);
assert(std::is_sorted(std::begin(arr1), std::end(arr1)));
std::cout << "passed" << std::endl;
/* 2nd test:
[12, 26, 15, 91, 32, 54, 41] returns [12, 15, 26, 32, 41, 54, 91] */
std::vector<int64_t> arr2({12, 26, 15, 91, 32, 54, 41});
std::cout << "2nd test... ";
sorting::insertionSort_binsrch(arr2);
assert(std::is_sorted(std::begin(arr2), std::end(arr2)));
std::cout << "passed" << std::endl;
/* 3rd test:
[7.1, -2.5, -4.0, -2.1, 5.7] returns [-4.0, -2.5, -2.1, 5.7, 7.1] */
std::vector<float> arr3({7.1, -2.5, -4.0, -2.1, 5.7});
std::cout << "3rd test... ";
sorting::insertionSort_binsrch(arr3);
assert(std::is_sorted(std::begin(arr3), std::end(arr3)));
std::cout << "passed" << std::endl;
/* 4th test:
[12.8, -3.7, -20.7, -7.1, 2.2] returns [-20.7, -7.1, -3.7, 2.2, 12.8] */
std::vector<float> arr4({12.8, -3.7, -20.7, -7.1, 2.2});
std::cout << "4th test... ";
sorting::insertionSort_binsrch(arr4);
assert(std::is_sorted(std::begin(arr4), std::end(arr4)));
std::cout << "passed" << std::endl;
}
/**
* @brief Main function
* @return 0 on exit.
*/
int main() {
test(); // run self-test implementations
return 0;
}
+64
View File
@@ -0,0 +1,64 @@
// Source : https://www.geeksforgeeks.org/bitonic-sort/
/* C++ Program for Bitonic Sort. Note that this program
works only when size of input is a power of 2. */
#include <algorithm>
#include <iostream>
/*The parameter dir indicates the sorting direction, ASCENDING
or DESCENDING; if (a[i] > a[j]) agrees with the direction,
then a[i] and a[j] are interchanged.*/
void compAndSwap(int a[], int i, int j, int dir) {
if (dir == (a[i] > a[j]))
std::swap(a[i], a[j]);
}
/*It recursively sorts a bitonic sequence in ascending order,
if dir = 1, and in descending order otherwise (means dir=0).
The sequence to be sorted starts at index position low,
the parameter cnt is the number of elements to be sorted.*/
void bitonicMerge(int a[], int low, int cnt, int dir) {
if (cnt > 1) {
int k = cnt / 2;
for (int i = low; i < low + k; i++) compAndSwap(a, i, i + k, dir);
bitonicMerge(a, low, k, dir);
bitonicMerge(a, low + k, k, dir);
}
}
/* This function first produces a bitonic sequence by recursively
sorting its two halves in opposite sorting orders, and then
calls bitonicMerge to make them in the same order */
void bitonicSort(int a[], int low, int cnt, int dir) {
if (cnt > 1) {
int k = cnt / 2;
// sort in ascending order since dir here is 1
bitonicSort(a, low, k, 1);
// sort in descending order since dir here is 0
bitonicSort(a, low + k, k, 0);
// Will merge wole sequence in ascending order
// since dir=1.
bitonicMerge(a, low, cnt, dir);
}
}
/* Caller of bitonicSort for sorting the entire array of
length N in ASCENDING order */
void sort(int a[], int N, int up) { bitonicSort(a, 0, N, up); }
// Driver code
int main() {
int a[] = {3, 7, 4, 8, 6, 2, 1, 5};
int N = sizeof(a) / sizeof(a[0]);
int up = 1; // means sort in ascending order
sort(a, N, up);
std::cout << "Sorted array: \n";
for (int i = 0; i < N; i++) std::cout << a[i] << " ";
return 0;
}
+118
View File
@@ -0,0 +1,118 @@
/**
* @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>
#include <random>
/**
* @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
std::random_device random_device;
std::mt19937 generator(random_device());
while (!std::is_sorted(arr.begin(), arr.end())) {
std::shuffle(arr.begin(), arr.end(), generator);// 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;
}
+134
View File
@@ -0,0 +1,134 @@
/**
* @file
* @brief Bubble sort algorithm
*
* @details
* Bubble sort algorithm is the bubble sorting algorithm. The most important reason
* for calling the bubble is that the largest number is thrown at the end of this
* algorithm. This is all about the logic. In each iteration, the largest number is
* expired and when iterations are completed, the sorting takes place.
*
* What is Swap?
*
* Swap in the software means that two variables are displaced.
* An additional variable is required for this operation. x = 5, y = 10.
* We want x = 10, y = 5. Here we create the most variable to do it.
*
* ```cpp
* int z;
* z = x;
* x = y;
* y = z;
* ```
*
* The above process is a typical displacement process.
* When x assigns the value to x, the old value of x is lost.
* That's why we created a variable z to create the first value of the value of x,
* and finally, we have assigned to y.
*
* ## Bubble Sort Algorithm Analysis (Best Case - Worst Case - Average Case)
*
* ### Best Case
* Bubble Sort Best Case Performance. \f$O(n)\f$. However, you
* can't get the best status in the code we shared above. This happens on the
* optimized bubble sort algorithm. It's right down there.
*
* ### Worst Case
* Bubble Sort Worst Case Performance is \f$O(n^{2})\f$. Why is that? Because if you
* remember Big O Notation, we were calculating the complexity of the algorithms in
* the nested loops. The \f$n * (n - 1)\f$ product gives us \f$O(n^{2})\f$ performance. In the
* worst case all the steps of the cycle will occur.
*
* ### Average Case
* Bubble Sort is not an optimal algorithm. In average, \f$O(n^{2})\f$ performance is taken.
*
* @author [Deepak](https://github.com/Deepak-j-p)
* @author [Nguyen Phuc Chuong](https://github.com/hollowcrust)
*/
#include <algorithm> /// for std::is_sorted
#include <cassert> /// for assert
#include <iostream> /// for IO implementations
#include <string> /// for std::string
#include <utility> /// for std::pair, std::swap
#include <vector> /// for std::vector, std::vector::push_back, std::vector::size
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace bubble_sort
* @brief Bubble sort algorithm
*/
namespace bubble_sort {
/**
* @brief Bubble sort algorithm
* @param array An array to be sorted
* @return The array sorted in ascending order
*/
template <typename T>
std::vector<T> bubble_sort(std::vector<T>& array) {
// swap_check flag to terminate the function early
// if there is no swap occurs in one iteration.
bool swap_check = true;
int size = array.size();
for (int i = 0; (i < size) && (swap_check); i++) {
swap_check = false;
for (int j = 0; j < size - 1 - i; j++) {
if (array[j] > array[j + 1]) {
swap_check = true;
std::swap(array[j], array[j + 1]);
}
}
}
return array;
}
} // namespace bubble_sort
} // namespace sorting
/**
* @brief Self-test implementation
* @return void
*/
static void test() {
std::vector<int> vec_1 = {3, 1, -9, 0};
std::vector<int> sorted_1 = sorting::bubble_sort::bubble_sort(vec_1);
std::vector<int> vec_2 = {3};
std::vector<int> sorted_2 = sorting::bubble_sort::bubble_sort(vec_2);
std::vector<int> vec_3 = {10, 10, 10, 10, 10};
std::vector<int> sorted_3 = sorting::bubble_sort::bubble_sort(vec_3);
std::vector<float> vec_4 = {1234, -273.1, 23, 150, 1234, 1555.55, -2000};
std::vector<float> sorted_4 = sorting::bubble_sort::bubble_sort(vec_4);
std::vector<char> vec_5 = {'z', 'Z', 'a', 'B', ' ', 'c', 'a'};
std::vector<char> sorted_5 = sorting::bubble_sort::bubble_sort(vec_5);
std::vector<std::string> vec_6 = {"Hello", "hello", "Helo", "Hi", "hehe"};
std::vector<std::string> sorted_6 = sorting::bubble_sort::bubble_sort(vec_6);
std::vector<std::pair<int, char>> vec_7 = {{10, 'c'}, {2, 'z'}, {10, 'a'}, {0, 'b'}, {-1, 'z'}};
std::vector<std::pair<int, char>> sorted_7 = sorting::bubble_sort::bubble_sort(vec_7);
assert(std::is_sorted(sorted_1.begin(), sorted_1.end()));
assert(std::is_sorted(sorted_2.begin(), sorted_2.end()));
assert(std::is_sorted(sorted_3.begin(), sorted_3.end()));
assert(std::is_sorted(sorted_4.begin(), sorted_4.end()));
assert(std::is_sorted(sorted_5.begin(), sorted_5.end()));
assert(std::is_sorted(sorted_6.begin(), sorted_6.end()));
assert(std::is_sorted(sorted_7.begin(), sorted_7.end()));
}
/**
* @brief Main function
* @return 0 on exit
*/
int main() {
test();
return 0;
}
+36
View File
@@ -0,0 +1,36 @@
// C++ program to sort an array using bucket sort
#include <algorithm>
#include <iostream>
#include <vector>
// Function to sort arr[] of size n using bucket sort
void bucketSort(float arr[], int n) {
// 1) Create n empty buckets
std::vector<float> *b = new std::vector<float>[n];
// 2) Put array elements in different buckets
for (int i = 0; i < n; i++) {
int bi = n * arr[i]; // Index in bucket
b[bi].push_back(arr[i]);
}
// 3) Sort individual buckets
for (int i = 0; i < n; i++) std::sort(b[i].begin(), b[i].end());
// 4) Concatenate all buckets into arr[]
int index = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < b[i].size(); j++) arr[index++] = b[i][j];
delete[] b;
}
/* Driver program to test above funtion */
int main() {
float arr[] = {0.897, 0.565, 0.656, 0.1234, 0.665, 0.3434};
int n = sizeof(arr) / sizeof(arr[0]);
bucketSort(arr, n);
std::cout << "Sorted array is \n";
for (int i = 0; i < n; i++) std::cout << arr[i] << " ";
return 0;
}
+102
View File
@@ -0,0 +1,102 @@
// Returns Sorted elements after performing Cocktail Selection Sort
// It is a Sorting algorithm which chooses the minimum and maximum element in an
// array simultaneously, and swaps it with the lowest and highest available
// position iteratively or recursively
#include <algorithm>
#include <iostream>
#include <vector>
// Iterative Version
void CocktailSelectionSort(std::vector<int> *vec, int low, int high) {
while (low <= high) {
int minimum = (*vec)[low];
int minimumindex = low;
int maximum = (*vec)[high];
int maximumindex = high;
for (int i = low; i <= high; i++) {
if ((*vec)[i] >= maximum) {
maximum = (*vec)[i];
maximumindex = i;
}
if ((*vec)[i] <= minimum) {
minimum = (*vec)[i];
minimumindex = i;
}
}
if (low != maximumindex || high != minimumindex) {
std::swap((*vec)[low], (*vec)[minimumindex]);
std::swap((*vec)[high], (*vec)[maximumindex]);
} else {
std::swap((*vec)[low], (*vec)[high]);
}
low++;
high--;
}
}
// Recursive Version
void CocktailSelectionSort_v2(std::vector<int> *vec, int low, int high) {
if (low >= high)
return;
int minimum = (*vec)[low];
int minimumindex = low;
int maximum = (*vec)[high];
int maximumindex = high;
for (int i = low; i <= high; i++) {
if ((*vec)[i] >= maximum) {
maximum = (*vec)[i];
maximumindex = i;
}
if ((*vec)[i] <= minimum) {
minimum = (*vec)[i];
minimumindex = i;
}
}
if (low != maximumindex || high != minimumindex) {
std::swap((*vec)[low], (*vec)[minimumindex]);
std::swap((*vec)[high], (*vec)[maximumindex]);
} else {
std::swap((*vec)[low], (*vec)[high]);
}
CocktailSelectionSort(vec, low + 1, high - 1);
}
// main function, select any one of iterative or recursive version
int main() {
int n;
std::cout << "Enter number of elements\n";
std::cin >> n;
std::vector<int> v(n);
std::cout << "Enter all the elements\n";
for (int i = 0; i < n; ++i) {
std::cin >> v[i];
}
int method;
std::cout << "Enter method: \n\t0: iterative\n\t1: recursive:\t";
std::cin >> method;
if (method == 0) {
CocktailSelectionSort(&v, 0, n - 1);
} else if (method == 1) {
CocktailSelectionSort_v2(&v, 0, n - 1);
} else {
std::cerr << "Unknown method" << std::endl;
return -1;
}
std::cout << "Sorted elements are\n";
for (int i = 0; i < n; ++i) {
std::cout << v[i] << " ";
}
return 0;
}
+101
View File
@@ -0,0 +1,101 @@
/**
*
* \file
* \brief [Comb Sort Algorithm
* (Comb Sort)](https://en.wikipedia.org/wiki/Comb_sort)
*
* \author
*
* \details
* - A better version of bubble sort algorithm
* - Bubble sort compares adjacent values whereas comb sort uses gap larger
* than 1
* - Best case Time complexity O(n)
* Worst case Time complexity O(n^2)
*
*/
#include <algorithm>
#include <cassert>
#include <iostream>
/**
*
* Find the next gap by shrinking the current gap by shrink factor of 1.3
* @param gap current gap
* @return new gap
*
*/
int FindNextGap(int gap) {
gap = (gap * 10) / 13;
return std::max(1, gap);
}
/** Function to sort array
*
* @param arr array to be sorted
* @param l start index of array
* @param r end index of array
*
*/
void CombSort(int *arr, int l, int r) {
/**
*
* initial gap will be maximum and the maximum possible value is
* the size of the array that is n and which is equal to r in this
* case so to avoid passing an extra parameter n that is the size of
* the array we are using r to initialize the initial gap.
*
*/
int gap = r;
/// Initialize swapped as true to make sure that loop runs
bool swapped = true;
/// Keep running until gap = 1 or none elements were swapped
while (gap != 1 || swapped) {
/// Find next gap
gap = FindNextGap(gap);
swapped = false;
/// Compare all elements with current gap
for (int i = l; i < r - gap; ++i) {
if (arr[i] > arr[i + gap]) {
std::swap(arr[i], arr[i + gap]);
swapped = true;
}
}
}
}
void tests() {
/// Test 1
int arr1[10] = {34, 56, 6, 23, 76, 34, 76, 343, 4, 76};
CombSort(arr1, 0, 10);
assert(std::is_sorted(arr1, arr1 + 10));
std::cout << "Test 1 passed\n";
/// Test 2
int arr2[8] = {-6, 56, -45, 56, 0, -1, 8, 8};
CombSort(arr2, 0, 8);
assert(std::is_sorted(arr2, arr2 + 8));
std::cout << "Test 2 Passed\n";
}
/** Main function */
int main() {
/// Running predefined tests
tests();
/// For user interaction
int n;
std::cin >> n;
int *arr = new int[n];
for (int i = 0; i < n; ++i) std::cin >> arr[i];
CombSort(arr, 0, n);
for (int i = 0; i < n; ++i) std::cout << arr[i] << ' ';
delete[] arr;
return 0;
}
+275
View File
@@ -0,0 +1,275 @@
/**
* @file
* @brief Counting Inversions using [Merge
Sort](https://en.wikipedia.org/wiki/Merge_sort)
*
* @details
* Program to count the number of inversions in an array
* using merge-sort.
*
* The count of inversions help to determine how close the array
* is to be sorted in ASCENDING order.
*
* two elements a[i] and a[j] form an inversion if `a[i]` > `a[j]` and i < j
*
* Time Complexity --> `O(n.log n)`
* Space Complexity --> `O(n)` ; additional array `temp[1..n]`
* ### Algorithm
* 1. The idea is similar to merge sort, divide the array into two equal or
almost
* equal halves in each step until the base case is reached.
* 2. Create a function merge that counts the number of inversions when two
halves of
* the array are merged, create two indices i and j, i is the index for
first half
* and j is an index of the second half. if `a[i]` is greater than `a[j]`,
then there are (mid i)
* inversions, Because left and right subarrays are sorted, so all the
remaining elements
* in left-subarray (a[i+1], a[i+2] … a[mid]) will be greater than a[j].
* 3. Create a recursive function to divide the array into halves and find the
answer by summing
* the number of inversions is the first half, number of inversion in the
second half and
* the number of inversions by merging the two.
* 4. The base case of recursion is when there is only one element in the
given half.
* 5. Print the answer
*
* @author [Rakshit Raj](https://github.com/rakshitraj)
*/
#include <cassert> /// for assert
#include <cstdint> /// for typedef datatype uint64_t
#include <iostream> /// for IO operations
#include <vector> /// for std::vector
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace inversion
* @brief Functions for counting inversions using Merge Sort algorithm
*/
namespace inversion {
// Functions used --->
// int mergeSort(int* arr, int* temp, int left, int right);
// int merge(int* arr, int* temp, int left, int mid, int right);
// int countInversion(int* arr, const int size);
// void show(int* arr, const int size);
/**
* @brief Function to merge two sub-arrays.
*
* @details
* merge() function is called from mergeSort()
* to merge the array after it split for sorting
* by the mergeSort() funtion.
*
* In this case the merge fuction will also count and return
* inversions detected when merging the sub arrays.
*
* @param arr input array, data-menber of vector
* @param temp stores the resultant merged array
* @param left lower bound of `arr[]` and left-sub-array
* @param mid midpoint, upper bound of left sub-array,
* `(mid+1)` gives the lower bound of right-sub-array
* @param right upper bound of `arr[]` and right-sub-array
* @returns number of inversions found in merge step
*/
template <typename T>
uint32_t merge(T* arr, T* temp, uint32_t left, uint32_t mid, uint32_t right) {
uint32_t i = left; /* i --> index of left sub-array */
uint32_t j = mid + 1; /* j --> index for right sub-array */
uint32_t k = left; /* k --> index for resultant array temp */
uint32_t inv_count = 0; // inversion count
while ((i <= mid) && (j <= right)) {
if (arr[i] <= arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
inv_count +=
(mid - i +
1); // tricky; may vary depending on selection of sub-array
}
}
// Add remaining elements from the larger subarray to the end of temp
while (i <= mid) {
temp[k++] = arr[i++];
}
while (j <= right) {
temp[k++] = arr[j++];
}
// Copy temp[] to arr[]
for (k = left; k <= right; k++) {
arr[k] = temp[k];
}
return inv_count;
}
/**
* @brief Implement merge Sort and count inverions while merging
*
* @details
* The mergeSort() function implements Merge Sort, a
* Divide and conquer algorithm, it divides the input
* array into two halves and calls itself for each
* sub-array and then calls the merge() function to
* merge the two halves.
*
* @param arr - array to be sorted
* @param temp - merged resultant array
* @param left - lower bound of array
* @param right - upper bound of array
* @returns number of inversions in array
*/
template <typename T>
uint32_t mergeSort(T* arr, T* temp, uint32_t left, uint32_t right) {
uint32_t mid = 0, inv_count = 0;
if (right > left) {
// midpoint to split the array
mid = (right + left) / 2;
// Add inversions in left and right sub-arrays
inv_count += mergeSort(arr, temp, left, mid); // left sub-array
inv_count += mergeSort(arr, temp, mid + 1, right);
// inversions in the merge step
inv_count += merge(arr, temp, left, mid, right);
}
return inv_count;
}
/**
* @brief Function countInversion() returns the number of inversion
* present in the input array. Inversions are an estimate of
* how close or far off the array is to being sorted.
*
* @details
* Number of inversions in a sorted array is 0.
* Number of inversion in an array[1...n] sorted in
* non-ascending order is n(n-1)/2, since each pair of elements
* contitute an inversion.
*
* @param arr - array, data member of std::vector<int>, input for counting
* inversions
* @param array_size - number of elementa in the array
* @returns number of inversions in input array, sorts the array
*/
template <class T>
uint32_t countInversion(T* arr, const uint32_t size) {
std::vector<T> temp;
temp.reserve(size);
temp.assign(size, 0);
return mergeSort(arr, temp.data(), 0, size - 1);
}
/**
* @brief UTILITY function to print array.
* @param arr[] array to print
* @param array_size size of input array arr[]
* @returns void
*
*/
template <typename T>
void show(T* arr, const uint32_t array_size) {
std::cout << "Printing array: \n";
for (uint32_t i = 0; i < array_size; i++) {
std::cout << " " << arr[i];
}
std::cout << "\n";
}
} // namespace inversion
} // namespace sorting
/**
* @brief Test implementations
* @returns void
*/
static void test() {
// Test 1
std::vector<uint64_t> arr1 = {
100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84,
83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67,
66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50,
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
uint32_t size1 = arr1.size();
uint32_t inv_count1 = 4950;
uint32_t result1 = sorting::inversion::countInversion(arr1.data(), size1);
assert(inv_count1 == result1);
// Test 2
std::vector<int> arr2 = {22, 66, 75, 23, 11, 87, 2, 44, 98, 43};
uint32_t size2 = arr2.size();
uint32_t inv_count2 = 20;
uint32_t result2 = sorting::inversion::countInversion(arr2.data(), size2);
assert(inv_count2 == result2);
// Test 3
std::vector<double> arr3 = {33.1, 45.2, 65.4, 76.5, 1.0,
2.9, 5.4, 7.7, 88.9, 12.4};
uint32_t size3 = arr3.size();
uint32_t inv_count3 = 21;
uint32_t result3 = sorting::inversion::countInversion(arr3.data(), size3);
assert(inv_count3 == result3);
// Test 4
std::vector<char> arr4 = {'a', 'b', 'c', 'd', 'e'};
uint32_t size4 = arr4.size();
uint32_t inv_count4 = 0;
uint32_t result4 = sorting::inversion::countInversion(arr4.data(), size4);
assert(inv_count4 == result4);
}
// /**
// * @brief Program Body contains all main funtionality
// * @returns void
// */
// template <typename T>
// static void body() {
// // Input your own sequence
// uint_t size;
// T input;
// std::cout << "Enter number of elements:";
// std::cin >> size;
//
// std::vector<T> arr;
// arr.reserve(size);
//
// std::cout << "Enter elements -->\n";
// for (uint64_t i=1; i<=size; i++) {
// std::cout << "Element "<< i <<" :";
// std::cin >> input;
// arr.push_back(input);
// }
//
// if (size != arr.size()) {
// size = arr.size();
// }
//
// std::cout << "\n";
// sorting::inversion::show(arr.data(), size);
// std::cout << "\n";
//
// // Counting inversions
// std::cout << "\nThe number of inversions: "<<
// sorting::inversion::countInversion(arr.data(), size) << "\n";
//
// // Output sorted array
// std::cout << "\nSorted array --> \n";
// sorting::inversion::show(arr.data(), size);
// }
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // Run test implementations
// body(); // test your own array
return 0;
}
+62
View File
@@ -0,0 +1,62 @@
#include <iostream>
using namespace std;
int Max(int Arr[], int N) {
int max = Arr[0];
for (int i = 1; i < N; i++)
if (Arr[i] > max)
max = Arr[i];
return max;
}
int Min(int Arr[], int N) {
int min = Arr[0];
for (int i = 1; i < N; i++)
if (Arr[i] < min)
min = Arr[i];
return min;
}
void Print(int Arr[], int N) {
for (int i = 0; i < N; i++) cout << Arr[i] << ", ";
}
int *Counting_Sort(int Arr[], int N) {
int max = Max(Arr, N);
int min = Min(Arr, N);
int *Sorted_Arr = new int[N];
int *Count = new int[max - min + 1];
for (int i = 0; i < max - min + 1; ++i) {
Count[i] = 0;
}
for (int i = 0; i < N; i++) Count[Arr[i] - min]++;
for (int i = 1; i < (max - min + 1); i++) Count[i] += Count[i - 1];
for (int i = N - 1; i >= 0; i--) {
Sorted_Arr[Count[Arr[i] - min] - 1] = Arr[i];
Count[Arr[i] - min]--;
}
delete[] Count;
return Sorted_Arr;
}
int main() {
int Arr[] = {47, 65, 20, 66, 25, 53, 64, 69, 72, 22,
74, 25, 53, 15, 42, 36, 4, 69, 86, 19},
N = 20;
int *Sorted_Arr;
cout << "\n\tOrignal Array = ";
Print(Arr, N);
Sorted_Arr = Counting_Sort(Arr, N);
cout << "\n\t Sorted Array = ";
Print(Sorted_Arr, N);
delete[] Sorted_Arr;
cout << endl;
return 0;
}
+33
View File
@@ -0,0 +1,33 @@
// C++ Program for counting sort
#include <iostream>
using namespace std;
void countSort(string arr) {
string output;
int count[256], i;
for (int i = 0; i < 256; i++) count[i] = 0;
for (i = 0; arr[i]; ++i) ++count[arr[i]];
for (i = 1; i < 256; ++i) count[i] += count[i - 1];
for (i = 0; arr[i]; ++i) {
output[count[arr[i]] - 1] = arr[i];
--count[arr[i]];
}
for (i = 0; arr[i]; ++i) arr[i] = output[i];
cout << "Sorted character array is " << arr;
}
int main() {
string arr;
cin >> arr;
countSort(arr);
return 0;
}
+131
View File
@@ -0,0 +1,131 @@
/**
* @file
* @brief Implementation of [Cycle
* sort](https://en.wikipedia.org/wiki/Cycle_sort) algorithm
* @details
* Cycle Sort is a sorting algorithm that works in \f$O(n^2)\f$ time in the best
* case and works in \f$O(n^2)\f$ in worst case. If a element is already at its
* correct position, do nothing. If a element is not at its correct position,
* we then need to move it to its correct position by computing the correct
* positions.Therefore, we should make sure the duplicate elements.
* @author [TsungHan Ho](https://github.com/dalaoqi)
*/
#include <algorithm> /// for std::is_sorted, std::swap
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for io operations
#include <vector> /// for std::vector
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace cycle_sort
* @brief Functions for [Cycle sort](https://en.wikipedia.org/wiki/Cycle_sort)
* algorithm
*/
namespace cycle_sort {
/**
* @brief The main function implements cycleSort
* @tparam T type of array
* @param in_arr array to be sorted
* @returns void
*/
template <typename T>
std::vector<T> cycleSort(const std::vector<T> &in_arr) {
std::vector<T> arr(in_arr);
for (int cycle_start = 0; cycle_start <= arr.size() - 1; cycle_start++) {
// initialize item
T item = arr[cycle_start];
// Count the number of elements smaller than item, this number is the
// correct index of item.
int pos = cycle_start;
for (int i = cycle_start + 1; i < arr.size(); i++) {
if (arr[i] < item) {
pos++;
}
}
// item is already in correct position
if (pos == cycle_start) {
continue;
}
// duplicate elements
while (item == arr[pos]) pos += 1;
if (pos == cycle_start) {
continue;
} else {
std::swap(item, arr[pos]);
}
// Rest of the elements
while (pos != cycle_start) {
pos = cycle_start;
// Find position where we put the element
for (size_t i = cycle_start + 1; i < arr.size(); i++) {
if (arr[i] < item) {
pos += 1;
}
}
// duplicate elements
while (item == arr[pos]) pos += 1;
if (item == arr[pos]) {
continue;
} else {
std::swap(item, arr[pos]);
}
}
}
return arr;
}
} // namespace cycle_sort
} // namespace sorting
/**
* @brief Test implementations
* @returns void
*/
static void test() {
// Test 1
// [4, 3, 2, 1] return [1, 2, 3, 4]
std::vector<uint32_t> array1 = {4, 3, 2, 1};
std::cout << "Test 1... ";
std::vector<uint32_t> arr1 = sorting::cycle_sort::cycleSort(array1);
assert(std::is_sorted(std::begin(arr1), std::end(arr1)));
std::cout << "passed" << std::endl;
// [4.3, -6.5, -7.4, 0, 2.7, 1.8] return [-7.4, -6.5, 0, 1.8, 2.7, 4.3]
std::vector<double> array2 = {4.3, -6.5, -7.4, 0, 2.7, 1.8};
std::cout << "Test 2... ";
std::vector<double> arr2 = sorting::cycle_sort::cycleSort(array2);
assert(std::is_sorted(std::begin(arr2), std::end(arr2)));
std::cout << "passed" << std::endl;
// Test 3
// [3, 3, 3, 3] return [3, 3, 3, 3]
std::vector<uint32_t> array3 = {3, 3, 3, 3};
std::cout << "Test 3... ";
std::vector<uint32_t> arr3 = sorting::cycle_sort::cycleSort(array3);
assert(std::is_sorted(std::begin(arr3), std::end(arr3)));
std::cout << "passed" << std::endl;
// [9, 4, 6, 8, 14, 3] return [9, 4, 6, 8, 14, 3]
std::vector<uint32_t> array4 = {3, 4, 6, 8, 9, 14};
std::cout << "Test 4... ";
std::vector<uint32_t> arr4 = sorting::cycle_sort::cycleSort(array4);
assert(std::is_sorted(std::begin(arr4), std::end(arr4)));
std::cout << "passed" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the test
return 0;
}
+112
View File
@@ -0,0 +1,112 @@
/**
* @file
* @brief Implementation of the [DNF
* sort](https://www.geeksforgeeks.org/sort-an-array-of-0s-1s-and-2s/)
* implementation
* @details
* C++ program to sort an array with 0, 1 and 2 in a single pass(DNF sort).
* Since one traversal of the array is there hence it works in O(n) time
* complexity.
* @author [Sujal Gupta](https://github.com/heysujal)
*/
#include <algorithm> /// for std::is_sorted
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for std::swap and io operations
#include <vector> /// for std::vector
/**
* @namespace sorting
* @breif Sorting algorithms
*/
namespace sorting {
/**
* @namespace dnf_sort
* @brief Functions for the [DNF
* sort](https://en.wikipedia.org/wiki/Dutch_national_flag_problem)
* implementation
*/
namespace dnf_sort {
/**
* @brief The main function implements DNF sort
* @tparam T type of array
* @param a array to be sorted,
* @param arr_size size of array
* @returns void
*/
template <typename T>
std::vector<T> dnfSort(const std::vector<T> &in_arr) {
std::vector<T> arr(in_arr);
uint64_t lo = 0;
uint64_t hi = arr.size() - 1;
uint64_t mid = 0;
// Iterate till all the elements
// are sorted
while (mid <= hi) {
switch (arr[mid]) {
// If the element is 0
case 0:
std::swap(arr[lo++], arr[mid++]);
break;
// If the element is 1 .
case 1:
mid++;
break;
// If the element is 2
case 2:
std::swap(arr[mid], arr[hi--]);
break;
}
}
return arr;
}
} // namespace dnf_sort
} // namespace sorting
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// 1st test
// [1, 0, 2, 1] return [0, 1, 1, 2]
std::vector<uint64_t> array1 = {0, 1, 1, 2};
std::cout << "Test 1... ";
std::vector<uint64_t> arr1 = sorting::dnf_sort::dnfSort(array1);
assert(std::is_sorted(std::begin(arr1), std::end(arr1)));
std::cout << "passed" << std::endl;
// 2nd test
// [1, 0, 0, 1, 1, 0, 2, 1] return [0, 0, 0, 1, 1, 1, 1, 2]
std::vector<uint64_t> array2 = {1, 0, 0, 1, 1, 0, 2, 1};
std::cout << "Test 2... ";
std::vector<uint64_t> arr2 = sorting::dnf_sort::dnfSort(array2);
assert(std::is_sorted(std::begin(arr2), std::end(arr2)));
std::cout << "passed" << std::endl;
// 3rd test
// [1, 1, 0, 0, 1, 2, 2, 0, 2, 1] return [0, 0, 0, 1, 1, 1, 1, 2, 2, 2]
std::vector<uint64_t> array3 = {1, 1, 0, 0, 1, 2, 2, 0, 2, 1};
std::cout << "Test 3... ";
std::vector<uint64_t> arr3 = sorting::dnf_sort::dnfSort(array3);
assert(std::is_sorted(std::begin(arr3), std::end(arr3)));
std::cout << "passed" << std::endl;
// 4th test
// [2, 2, 2, 0, 0, 1, 1] return [0, 0, 1, 1, 2, 2, 2]
std::vector<uint64_t> array4 = {2, 2, 2, 0, 0, 1, 1};
std::cout << "Test 4... ";
std::vector<uint64_t> arr4 = sorting::dnf_sort::dnfSort(array4);
assert(std::is_sorted(std::begin(arr4), std::end(arr4)));
std::cout << "passed" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // execute the test
return 0;
}
+133
View 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;
}
+123
View File
@@ -0,0 +1,123 @@
/**
* \file
* \brief [Heap Sort Algorithm
* (heap sort)](https://en.wikipedia.org/wiki/Heapsort) implementation
*
* \author [Ayaan Khan](http://github.com/ayaankhan98)
*
* \details
* Heap-sort is a comparison-based sorting algorithm.
* Heap-sort can be thought of as an improved selection sort:
* like selection sort, heap sort divides its input into a sorted
* and an unsorted region, and it iteratively shrinks the unsorted
* region by extracting the largest element from it and inserting
* it into the sorted region. Unlike selection sort,
* heap sort does not waste time with a linear-time scan of the
* unsorted region; rather, heap sort maintains the unsorted region
* in a heap data structure to more quickly find the largest element
* in each step.
*
* Time Complexity - \f$O(n \log(n))\f$
*
*/
#include <algorithm>
#include <cassert>
#include <iostream>
/**
*
* Utility function to print the array after
* sorting.
*
* @param arr array to be printed
* @param sz size of array
*
*/
template <typename T>
void printArray(T *arr, int sz) {
for (int i = 0; i < sz; i++) std::cout << arr[i] << " ";
std::cout << "\n";
}
/**
*
* \addtogroup sorting Sorting Algorithm
* @{
*
* The heapify procedure can be thought of as building a heap from
* the bottom up by successively sifting downward to establish the
* heap property.
*
* @param arr array to be sorted
* @param n size of array
* @param i node position in Binary Tress or element position in
* Array to be compared with it's childern
*
*/
template <typename T>
void heapify(T *arr, int n, int i) {
int largest = i;
int l = 2 * i + 1;
int r = 2 * i + 2;
if (l < n && arr[l] > arr[largest])
largest = l;
if (r < n && arr[r] > arr[largest])
largest = r;
if (largest != i) {
std::swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}
/**
* Utilizes heapify procedure to sort
* the array
*
* @param arr array to be sorted
* @param n size of array
*
*/
template <typename T>
void heapSort(T *arr, int n) {
for (int i = n - 1; i >= 0; i--) heapify(arr, n, i);
for (int i = n - 1; i >= 0; i--) {
std::swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
/**
*
* @}
* Test cases to test the program
*
*/
void test() {
std::cout << "Test 1\n";
int arr[] = {-10, 78, -1, -6, 7, 4, 94, 5, 99, 0};
int sz = sizeof(arr) / sizeof(arr[0]); // sz - size of array
printArray(arr, sz); // displaying the array before sorting
heapSort(arr, sz); // calling heapsort to sort the array
printArray(arr, sz); // display array after sorting
assert(std::is_sorted(arr, arr + sz));
std::cout << "Test 1 Passed\n========================\n";
std::cout << "Test 2\n";
double arr2[] = {4.5, -3.6, 7.6, 0, 12.9};
sz = sizeof(arr2) / sizeof(arr2[0]);
printArray(arr2, sz);
heapSort(arr2, sz);
printArray(arr2, sz);
assert(std::is_sorted(arr2, arr2 + sz));
std::cout << "Test 2 passed\n";
}
/** Main function */
int main() {
test();
return 0;
}
+179
View File
@@ -0,0 +1,179 @@
/**
*
* \file
* \brief [Insertion Sort Algorithm
* (Insertion Sort)](https://en.wikipedia.org/wiki/Insertion_sort)
*
* \details
* Insertion sort is a simple sorting algorithm that builds the final
* sorted array one at a time. It is much less efficient compared to
* other sorting algorithms like heap sort, merge sort or quick sort.
* However it has several advantages such as
* 1. Easy to implement
* 2. For small set of data it is quite efficient
* 3. More efficient that other Quadratic complexity algorithms like
* Selection sort or bubble sort.
* 4. It's stable that is it does not change the relative order of
* elements with equal keys
* 5. Works on hand means it can sort the array or list as it receives.
*
* It is based on the same idea that people use to sort the playing cards in
* their hands.
* the algorithms goes in the manner that we start iterating over the array
* of elements as soon as we find a unsorted element that is a misplaced
* element we place it at a sorted position.
*
* Example execution steps:
* 1. Suppose initially we have
* \f{bmatrix}{4 &3 &2 &5 &1\f}
* 2. We start traversing from 4 till we reach 1
* when we reach at 3 we find that it is misplaced so we take 3 and place
* it at a correct position thus the array will become
* \f{bmatrix}{3 &4 &2 &5 &1\f}
* 3. In the next iteration we are at 2 we find that this is also misplaced so
* we place it at the correct sorted position thus the array in this iteration
* becomes
* \f{bmatrix}{2 &3 &4 &5 &1\f}
* 4. We do not do anything with 5 and move on to the next iteration and
* select 1 which is misplaced and place it at correct position. Thus, we have
* \f{bmatrix}{1 &2 &3 &4 &5\f}
*/
#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>
/** \namespace sorting
* \brief Sorting algorithms
*/
namespace sorting {
/** \brief
* Insertion Sort Function
*
* @tparam T type of array
* @param [in,out] arr Array to be sorted
* @param n Size of Array
*/
template <typename T>
void insertionSort(T *arr, int n) {
for (int i = 1; i < n; i++) {
T temp = arr[i];
int j = i - 1;
while (j >= 0 && temp < arr[j]) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
/** Insertion Sort Function
*
* @tparam T type of array
* @param [in,out] arr pointer to array to be sorted
*/
template <typename T>
void insertionSort(std::vector<T> *arr) {
size_t n = arr->size();
for (size_t i = 1; i < n; i++) {
T temp = arr[0][i];
int32_t j = i - 1;
while (j >= 0 && temp < arr[0][j]) {
arr[0][j + 1] = arr[0][j];
j--;
}
arr[0][j + 1] = temp;
}
}
} // namespace sorting
/**
* @brief Create a random array objecthelper function to create a random array
*
* @tparam T type of array
* @param arr array to fill (must be pre-allocated)
* @param N number of array elements
*/
template <typename T>
static void create_random_array(T *arr, int N) {
while (N--) {
double r = (std::rand() % 10000 - 5000) / 100.f;
arr[N] = static_cast<T>(r);
}
}
/** Test Cases to test algorithm */
void tests() {
int arr1[10] = {78, 34, 35, 6, 34, 56, 3, 56, 2, 4};
std::cout << "Test 1... ";
sorting::insertionSort(arr1, 10);
assert(std::is_sorted(arr1, arr1 + 10));
std::cout << "passed" << std::endl;
int arr2[5] = {5, -3, 7, -2, 1};
std::cout << "Test 2... ";
sorting::insertionSort(arr2, 5);
assert(std::is_sorted(arr2, arr2 + 5));
std::cout << "passed" << std::endl;
float arr3[5] = {5.6, -3.1, -3.0, -2.1, 1.8};
std::cout << "Test 3... ";
sorting::insertionSort(arr3, 5);
assert(std::is_sorted(arr3, arr3 + 5));
std::cout << "passed" << std::endl;
std::vector<float> arr4({5.6, -3.1, -3.0, -2.1, 1.8});
std::cout << "Test 4... ";
sorting::insertionSort(&arr4);
assert(std::is_sorted(std::begin(arr4), std::end(arr4)));
std::cout << "passed" << std::endl;
int arr5[50];
std::cout << "Test 5... ";
create_random_array(arr5, 50);
sorting::insertionSort(arr5, 50);
assert(std::is_sorted(arr5, arr5 + 50));
std::cout << "passed" << std::endl;
float arr6[50];
std::cout << "Test 6... ";
create_random_array(arr6, 50);
sorting::insertionSort(arr6, 50);
assert(std::is_sorted(arr6, arr6 + 50));
std::cout << "passed" << std::endl;
}
/** Main Function */
int main() {
/// Running predefined tests to test algorithm
tests();
/// For user insteraction
size_t n;
std::cout << "Enter the length of your array (0 to exit): ";
std::cin >> n;
if (n == 0) {
return 0;
}
int *arr = new int[n];
std::cout << "Enter any " << n << " Numbers for Unsorted Array : ";
for (int i = 0; i < n; i++) {
std::cin >> arr[i];
}
sorting::insertionSort(arr, n);
std::cout << "\nSorted Array : ";
for (int i = 0; i < n; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
delete[] arr;
return 0;
}
+152
View File
@@ -0,0 +1,152 @@
/**
* @file
* @brief Insertion Sort Algorithm
* @author [Dhanush S](https://github.com/Fandroid745)
*
* @details
* Insertion sort is a simple sorting algorithm that builds the final
* sorted array one element at a time. It is much less efficient compared
* to other sorting algorithms like heap sort, merge sort, or quick sort.
*
* However, it has several advantages:
* - Easy to implement.
* - Efficient for small data sets.
* - More efficient than other O(n²) algorithms like selection sort or bubble sort.
* - Stable: it does not change the relative order of elements with equal keys.
*
* Insertion sort works similarly to how people sort playing cards in their hands.
* The algorithm iterates through the list and inserts each element into its correct
* position in the sorted portion of the array.
*
* The time complexity of the algorithm is \f$O(n^2)\f$, and in some cases, it
* can be \f$O(n)\f$.
*
* Example execution:
* 1. Start with the array [4, 3, 2, 5, 1].
* 2. Insert 3 in its correct position: [3, 4, 2, 5, 1].
* 3. Insert 2: [2, 3, 4, 5, 1].
* 4. Continue this until the array is sorted: [1, 2, 3, 4, 5].
*/
#include <algorithm> /// for std::is_sorted
#include <cassert> /// for assert function in testing
#include <iostream> /// for std::cout and std::endl
#include <vector> /// for using std::vector
/**
* @namespace sorting
* @brief Contains sorting algorithms
*/
namespace sorting {
/**
* @brief Insertion Sort Function
*
* @tparam T Type of the array elements
* @param[in,out] arr Array to be sorted
* @param n Size of the array
*/
template <typename T>
void insertionSort(T *arr, int n) {
for (int i = 1; i < n; i++) {
T temp = arr[i];
int j = i - 1;
while (j >= 0 && temp < arr[j]) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
/**
* @brief Insertion Sort for a vector
*
* @tparam T Type of the vector elements
* @param [in,out] arr Pointer to the vector to be sorted
*/
template <typename T>
void insertionSort(std::vector<T> *arr) {
size_t n = arr->size();
for (size_t i = 1; i < n; i++) {
T temp = arr->at(i);
int32_t j = i - 1;
while (j >= 0 && temp < arr->at(j)) {
arr->at(j + 1) = arr->at(j);
j--;
}
arr->at(j + 1) = temp;
}
}
} // namespace sorting
/**
* @brief Helper function to create a random array
*
* @tparam T Type of the array elements
* @param arr Array to fill (must be pre-allocated)
* @param N Number of elements in the array
*/
template <typename T>
static void create_random_array(T *arr, int N) {
while (N--) {
double r = (std::rand() % 10000 - 5000) / 100.f;
arr[N] = static_cast<T>(r);
}
}
/**
* @brief self test implementation
* @return void
*/
static void tests() {
int arr1[10] = {78, 34, 35, 6, 34, 56, 3, 56, 2, 4};
std::cout << "Test 1... ";
sorting::insertionSort(arr1, 10);
assert(std::is_sorted(arr1, arr1 + 10));
std::cout << "passed" << std::endl;
int arr2[5] = {5, -3, 7, -2, 1};
std::cout << "Test 2... ";
sorting::insertionSort(arr2, 5);
assert(std::is_sorted(arr2, arr2 + 5));
std::cout << "passed" << std::endl;
float arr3[5] = {5.6, -3.1, -3.0, -2.1, 1.8};
std::cout << "Test 3... ";
sorting::insertionSort(arr3, 5);
assert(std::is_sorted(arr3, arr3 + 5));
std::cout << "passed" << std::endl;
std::vector<float> arr4({5.6, -3.1, -3.0, -2.1, 1.8});
std::cout << "Test 4... ";
sorting::insertionSort(&arr4);
assert(std::is_sorted(std::begin(arr4), std::end(arr4)));
std::cout << "passed" << std::endl;
int arr5[50];
std::cout << "Test 5... ";
create_random_array(arr5, 50);
sorting::insertionSort(arr5, 50);
assert(std::is_sorted(arr5, arr5 + 50));
std::cout << "passed" << std::endl;
float arr6[50];
std::cout << "Test 6... ";
create_random_array(arr6, 50);
sorting::insertionSort(arr6, 50);
assert(std::is_sorted(arr6, arr6 + 50));
std::cout << "passed" << std::endl;
}
/**
* @brief Main function
* @return 0 on successful exit.
*/
int main() {
tests(); /// run self test implementations
return 0;
}
+93
View File
@@ -0,0 +1,93 @@
#include <algorithm>
#include <iostream>
void librarySort(int *index, int n) {
int lib_size, index_pos,
*gaps, // gaps
*library[2]; // libraries
bool target_lib, *numbered;
for (int i = 0; i < 2; i++) library[i] = new int[n];
gaps = new int[n + 1];
numbered = new bool[n + 1];
lib_size = 1;
index_pos = 1;
target_lib = 0;
library[target_lib][0] = index[0];
while (index_pos < n) {
// binary search
int insert = std::distance(
library[target_lib],
std::lower_bound(library[target_lib],
library[target_lib] + lib_size, index[index_pos]));
// if there is no gap to insert a new index ...
if (numbered[insert] == true) {
int prov_size = 0, next_target_lib = !target_lib;
// update library and clear gaps
for (int i = 0; i <= n; i++) {
if (numbered[i] == true) {
library[next_target_lib][prov_size] = gaps[i];
prov_size++;
numbered[i] = false;
}
if (i <= lib_size) {
library[next_target_lib][prov_size] =
library[target_lib][i];
prov_size++;
}
}
target_lib = next_target_lib;
lib_size = prov_size - 1;
} else {
numbered[insert] = true;
gaps[insert] = index[index_pos];
index_pos++;
}
}
int index_pos_for_output = 0;
for (int i = 0; index_pos_for_output < n; i++) {
if (numbered[i] == true) {
// std::cout << gaps[i] << std::endl;
index[index_pos_for_output] = gaps[i];
index_pos_for_output++;
}
if (i < lib_size) {
// std::cout << library[target_lib][i] << std::endl;
index[index_pos_for_output] = library[target_lib][i];
index_pos_for_output++;
}
}
delete[] numbered;
delete[] gaps;
for (int i = 0; i < 2; ++i) {
delete[] library[i];
}
}
int main() {
// ---example--
int index_ex[] = {-6, 5, 9, 1, 9, 1, 0, 1, -8, 4, -12};
int n_ex = sizeof(index_ex) / sizeof(index_ex[0]);
librarySort(index_ex, n_ex);
std::cout << "sorted array :" << std::endl;
for (int i = 0; i < n_ex; i++) std::cout << index_ex[i] << " ";
std::cout << std::endl;
/* --output--
sorted array :
-12 -8 -6 0 1 1 1 4 5 9 9
*/
}
+163
View File
@@ -0,0 +1,163 @@
/**
* @file
* @author [@sinkyoungdeok](https://github.com/sinkyoungdeok)
* @author [Krishna Vedala](https://github.com/kvedala)
* @brief Algorithm that combines insertion sort and merge sort. [Wiki
* link](https://en.wikipedia.org/wiki/Merge-insertion_sort)
*
* @see Individual algorithms: insertion_sort.cpp and merge_sort.cpp
*/
#include <algorithm>
#include <array>
#include <cassert>
#include <ctime>
#include <iostream>
#include <memory>
/** \namespace sorting
* \brief Sorting algorithms
*/
namespace sorting {
/** \namespace merge_insertion
* \brief Combined Intersion-Merge sorting algorithm
*/
namespace merge_insertion {
/**
* @brief Insertion merge algorithm
* @see insertion_sort.cpp
*
* @tparam T array data type
* @tparam N length of array
* @param A pointer to array to sort
* @param start start index of sorting window
* @param end end index of sorting window
*/
template <typename T, size_t N>
static void InsertionSort(std::array<T, N> *A, size_t start, size_t end) {
size_t i = 0, j = 0;
T *ptr = A->data();
for (i = start; i < end; i++) {
T temp = ptr[i];
j = i;
while (j > start && temp < ptr[j - 1]) {
ptr[j] = ptr[j - 1];
j--;
}
// for (j = i; j > start && temp < ptr[j - 1]; --j) {
// ptr[j] = ptr[j - 1];
// }
ptr[j] = temp;
}
}
/**
* @brief Perform merge of data in a window
*
* @tparam T array data type
* @tparam N length of array
* @param A pointer to array to sort
* @param min start index of window
* @param max end index of window
* @param mid mid-point of window
*/
template <typename T, size_t N>
static void merge(std::array<T, N> *array, size_t min, size_t max, size_t mid) {
size_t firstIndex = min;
size_t secondIndex = mid + 1;
auto ptr = array->data();
std::array<T, N + 1> tempArray{0};
// While there are elements in the left or right runs
for (size_t index = min; index <= max; index++) {
// If left run head exists and is <= existing right run head.
if (firstIndex <= mid &&
(secondIndex > max || ptr[firstIndex] <= ptr[secondIndex])) {
tempArray[index] = ptr[firstIndex];
firstIndex++;
} else {
tempArray[index] = ptr[secondIndex];
secondIndex++;
}
}
// transfer to the initial array
memcpy(ptr + min, tempArray.data() + min, (max - min) * sizeof(T));
// for (int index = min; index <= max; index++) ptr[index] =
// tempArray[index];
}
/**
* @brief Final combined algorithm.
* Algorithm utilizes ::sorting::merge_insertion::InsertionSort if window length
* is less than threshold, else performs merge sort recursively using
* ::sorting::merge_insertion::mergeSort
*
* @tparam T array data type
* @tparam N length of array
* @param A pointer to array to sort
* @param min start index of sort window
* @param max end index of sort window
* @param threshold window length threshold
*/
template <typename T, size_t N>
void mergeSort(std::array<T, N> *array, size_t min, size_t max,
size_t threshold) {
// prerequisite
if ((max - min) <= threshold) {
InsertionSort(array, min, max);
} else {
// get the middle point
size_t mid = (max + min) >> 1;
// apply merge sort to both parts of this
mergeSort(array, min, mid, threshold);
mergeSort(array, mid, max, threshold);
// and finally merge all that sorted stuff
merge(array, min, max, mid);
}
}
} // namespace merge_insertion
} // namespace sorting
/**
* @brief Function to test code using random arrays
* @returns none
*/
static void test() {
constexpr size_t size = 30;
std::array<int, size> array{0};
// input
for (int i = 0; i < size; i++) {
array[i] = std::rand() % 100 - 50;
std::cout << array[i] << " ";
}
std::cout << std::endl;
sorting::merge_insertion::InsertionSort(&array, 0, size);
// sorting::merge_insertion::mergeSort(&array, 0, size, 10);
// output
for (int i = 0; i < size; ++i) {
std::cout << array[i] << " ";
}
std::cout << std::endl;
assert(std::is_sorted(std::begin(array), std::end(array)));
std::cout << "Test passed\n";
}
/**
* @brief Main function
* @return 0 on exit
*/
int main() {
std::srand(std::time(nullptr));
test();
return 0;
}
+123
View File
@@ -0,0 +1,123 @@
/**
* \addtogroup sorting Sorting Algorithms
* @{
* \file
* \brief [Merge Sort Algorithm
* (MERGE SORT)](https://en.wikipedia.org/wiki/Merge_sort) implementation
*
* \author [Ayaan Khan](http://github.com/ayaankhan98)
*
* \details
* Merge Sort is an efficient, general purpose, comparison
* based sorting algorithm.
* Merge Sort is a divide and conquer algorithm
* Time Complexity: O(n log n)
* It is same for all best case, worst case or average case
* Merge Sort is very efficient when for the small data.
* In built-in sort function merge sort along with quick sort is used.
*/
#include <iostream>
#include <vector>
/**
*
* The merge() function is used for merging two halves.
* The merge(arr, l, m, r) is key process that assumes that
* arr[l..m] and arr[m+1..r] are sorted and merges the two
* sorted sub-arrays into one.
*
* @param arr - array with two halves arr[l...m] and arr[m+1...r]
* @param l - left index or start index of first half array
* @param m - right index or end index of first half array
*
* (The second array starts form m+1 and goes till r)
*
* @param r - end index or right index of second half array
*/
void merge(int *arr, int l, int m, int r) {
int n1 = m - l + 1;
int n2 = r - m;
std::vector<int> L(n1), R(n2);
for (int i = 0; i < n1; i++) L[i] = arr[l + i];
for (int j = 0; j < n2; j++) R[j] = arr[m + 1 + j];
int i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
/**
* Merge sort is a divide and conquer algorithm, it divides the
* input array into two halves and calls itself for the two halves
* and then calls merge() to merge the two halves
*
* @param arr - array to be sorted
* @param l - left index or start index of array
* @param r - right index or end index of array
*
*/
void mergeSort(int *arr, int l, int r) {
if (l < r) {
int m = l + (r - l) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
/**
* Utility function used to print the array after
* sorting
*/
void show(int *arr, int size) {
for (int i = 0; i < size; i++) std::cout << arr[i] << " ";
std::cout << "\n";
}
/** Main function */
int main() {
int size;
std::cout << "Enter the number of elements: ";
std::cin >> size;
if (size <= 0) {
std::cout << "Invalid size.\n";
return 1;
}
int *arr = new int[size];
std::cout << "Enter the unsorted elements: ";
for (int i = 0; i < size; ++i) {
std::cin >> arr[i];
}
mergeSort(arr, 0, size - 1);
std::cout << "Sorted array: ";
show(arr, size);
delete[] arr;
return 0;
}
/** @} */
+109
View File
@@ -0,0 +1,109 @@
/**
* Copyright 2020 @author Albirair
* @file
*
* A generic implementation of non-recursive merge sort.
*/
#include <cstddef> // for size_t
#include <iostream>
#include <utility> // for std::move & std::remove_reference_t
namespace sorting {
template <class Iterator>
void merge(Iterator, Iterator, const Iterator, char[]);
/// bottom-up merge sort which sorts elements in a non-decreasing order
/**
* sorts elements non-recursively by breaking them into small segments,
* merging adjacent segments into larger sorted segments, then increasing
* the sizes of segments by factors of 2 and repeating the same process.
* best-case = worst-case = O(n log(n))
* @param first points to the first element
* @param last points to 1-step past the last element
* @param n the number of elements
*/
template <class Iterator>
void non_recursive_merge_sort(const Iterator first, const Iterator last,
const size_t n) {
// create a buffer large enough to store all elements
// dynamically allocated to comply with cpplint
char* buffer = new char[n * sizeof(*first)];
// buffer size can be optimized to largest power of 2 less than n
// elements divide the container into equally-sized segments whose
// length start at 1 and keeps increasing by factors of 2
for (size_t length(1); length < n; length <<= 1) {
// merge adjacent segments whose number is n / (length * 2)
Iterator left(first);
for (size_t counter(n / (length << 1)); counter; --counter) {
Iterator right(left + length), end(right + length);
merge(left, right, end, buffer);
left = end;
}
// if the number of remaining elements (n * 2 % length) is longer
// than a segment, merge the remaining elements
if ((n & ((length << 1) - 1)) > length)
merge(left, left + length, last, buffer);
}
delete[] buffer;
}
/// merges 2 sorted adjacent segments into a larger sorted segment
/**
* best-case = worst-case = O(n)
* @param l points to the left part
* @param r points to the right part, end of left part
* @param e points to end of right part
* @param b points at the buffer
*/
template <class Iterator>
void merge(Iterator l, Iterator r, const Iterator e, char b[]) {
// create 2 pointers to point at the buffer
auto p(reinterpret_cast<std::remove_reference_t<decltype(*l)>*>(b)), c(p);
// move the left part of the segment
for (Iterator t(l); r != t; ++t) *p++ = std::move(*t);
// while neither the buffer nor the right part has been exhausted
// move the smallest element of the two back to the container
while (e != r && c != p) *l++ = std::move(*r < *c ? *r++ : *c++);
// notice only one of the two following loops will be executed
// while the right part hasn't bee exhausted, move it back
while (e != r) *l++ = std::move(*r++);
// while the buffer hasn't bee exhausted, move it back
while (c != p) *l++ = std::move(*c++);
}
/// bottom-up merge sort which sorts elements in a non-decreasing order
/**
* @param first points to the first element
* @param n the number of elements
*/
template <class Iterator>
void non_recursive_merge_sort(const Iterator first, const size_t n) {
non_recursive_merge_sort(first, first + n, n);
}
/// bottom-up merge sort which sorts elements in a non-decreasing order
/**
* @param first points to the first element
* @param last points to 1-step past the last element
*/
template <class Iterator>
void non_recursive_merge_sort(const Iterator first, const Iterator last) {
non_recursive_merge_sort(first, last, last - first);
}
} // namespace sorting
using sorting::non_recursive_merge_sort;
int main() {
int size;
std::cout << "Enter the number of elements : ";
std::cin >> size;
int* arr = new int[size];
for (int i = 0; i < size; ++i) {
std::cout << "arr[" << i << "] = ";
std::cin >> arr[i];
}
non_recursive_merge_sort(arr, size);
std::cout << "Sorted array\n";
for (int i = 0; i < size; ++i)
std::cout << "arr[" << i << "] = " << arr[i] << '\n';
delete[] arr;
return 0;
}
+55
View File
@@ -0,0 +1,55 @@
// Using general algorithms to sort a collection of strings results in
// alphanumeric sort. If it is a numeric string, it leads to unnatural sorting
// eg, an array of strings 1,10,100,2,20,200,3,30,300
// would be sorted in that same order by using conventional sorting,
// even though we know the correct sorting order is 1,2,3,10,20,30,100,200,300
// This Programme uses a comparator to sort the array in Numerical order instead
// of Alphanumeric order
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
bool NumericSort(std::string a, std::string b) {
while (a[0] == '0') {
a.erase(a.begin());
}
while (b[0] == '0') {
b.erase(b.begin());
}
int n = a.length();
int m = b.length();
if (n == m)
return a < b;
return n < m;
}
int main() {
int n;
std::cout << "Enter number of elements to be sorted Numerically\n";
std::cin >> n;
std::vector<std::string> v(n);
std::cout << "Enter the string of Numbers\n";
for (int i = 0; i < n; i++) {
std::cin >> v[i];
}
sort(v.begin(), v.end());
std::cout << "Elements sorted normally \n";
for (int i = 0; i < n; i++) {
std::cout << v[i] << " ";
}
std::cout << "\n";
std::sort(v.begin(), v.end(), NumericSort);
std::cout << "Elements sorted Numerically \n";
for (int i = 0; i < n; i++) {
std::cout << v[i] << " ";
}
return 0;
}
+53
View File
@@ -0,0 +1,53 @@
/* C++ implementation Odd Even Sort */
#include <iostream>
#include <vector>
using namespace std;
void oddEven(vector<int> &arr, int size) {
bool sorted = false;
while (!sorted) {
sorted = true;
for (int i = 1; i < size - 1; i += 2) // Odd
{
if (arr[i] > arr[i + 1]) {
swap(arr[i], arr[i + 1]);
sorted = false;
}
}
for (int i = 0; i < size - 1; i += 2) // Even
{
if (arr[i] > arr[i + 1]) {
swap(arr[i], arr[i + 1]);
sorted = false;
}
}
}
}
void show(vector<int> A, int size) {
int i;
for (i = 0; i < size; i++) cout << A[i] << "\n";
}
int main() {
int size, temp;
cout << "\nEnter the number of elements : ";
cin >> size;
vector<int> arr;
cout << "\nEnter the unsorted elements : \n";
for (int i = 0; i < size; ++i) {
cin >> temp;
arr.push_back(temp);
}
oddEven(arr, size);
cout << "Sorted array\n";
show(arr, size);
return 0;
}
+131
View File
@@ -0,0 +1,131 @@
/**
* @file
* @brief pancake sort sorts a disordered stack of pancakes by flipping any
* number of pancakes using a spatula using minimum number of flips.
*
* @details
* Unlike a traditional sorting algorithm, which attempts to sort with the
* fewest comparisons possible, the goal is to sort the sequence in as few
* reversals as possible. Overall time complexity of pancake sort is O(n^2) For
* example: example 1:- Disordered pancake sizes: {2,5,3,7,8} Sorted:
* {2,3,5,7,8} For example: example 2:- Disordered pancake sizes:
* {22,51,37,73,81} Sorted: {22,37,51,73,81}
* @author [Divyansh Gupta](https://github.com/divyansh12323)
* @see more on [Pancake sort](https://en.wikipedia.org/wiki/Pancake_sorting)
* @see related problem at
* [Leetcode](https://leetcode.com/problems/pancake-sorting/)
*/
#include <algorithm> // for std::is_sorted
#include <cassert> // for std::assert
#include <iostream> // for io operations
#include <vector> // for std::vector
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace pancake_sort
* @brief Functions for [Pancake
* sort](https://en.wikipedia.org/wiki/Pancake_sorting) algorithm
*/
namespace pancake_sort {
/**
* @brief This implementation is for reversing elements in a a C-style array .
* @param [start,end] arr our vector of elements.
* @param start starting index of array
* @param end ending index of array
* @returns void
*/
template <typename T>
void reverse(std::vector<T> &arr, int start, int end) {
T temp; // Temporary variable
while (start <= end) {
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
/**
* @brief This implementation is for a C-style array input that gets modified in
* place.
* @param [start,end] arr our vector of elements.
* @param size size of given array
* @returns 0 on exit
*/
template <typename T>
int pancakeSort(std::vector<T> &arr, int size) {
for (int i = size; i > 1; --i) {
int max_index = 0, j = 0; // intialize some variables.
T max_value = 0;
for (j = 0; j < i; j++) {
if (arr[j] >= max_value) {
max_value = arr[j];
max_index = j;
}
}
if (max_index != i - 1) // check for reversing
{
reverse(arr, 0, max_index);
reverse(arr, 0, i - 1);
}
}
return 0;
}
} // namespace pancake_sort
} // namespace sorting
/**
* @brief Test implementations
* @returns void
*/
static void test() {
// example 1: vector of int
const int size1 = 7;
std::cout << "\nTest 1- as std::vector<int>...";
std::vector<int> arr1 = {23, 10, 20, 11, 12, 6, 7};
sorting::pancake_sort::pancakeSort(arr1, size1);
assert(std::is_sorted(arr1.begin(), arr1.end()));
std::cout << "Passed\n";
for (int i = 0; i < size1; i++) {
std::cout << arr1[i] << " ,";
}
std::cout << std::endl;
// example 2: vector of double
const int size2 = 8;
std::cout << "\nTest 2- as std::vector<double>...";
std::vector<double> arr2 = {23.56, 10.62, 200.78, 111.484,
3.9, 1.2, 61.77, 79.6};
sorting::pancake_sort::pancakeSort(arr2, size2);
assert(std::is_sorted(arr2.begin(), arr2.end()));
std::cout << "Passed\n";
for (int i = 0; i < size2; i++) {
std::cout << arr2[i] << ", ";
}
std::cout << std::endl;
// example 3:vector of float
const int size3 = 7;
std::cout << "\nTest 3- as std::vector<float>...";
std::vector<float> arr3 = {6.56, 12.62, 200.78, 768.484, 19.27, 68.87, 9.6};
sorting::pancake_sort::pancakeSort(arr3, size3);
assert(std::is_sorted(arr3.begin(), arr3.end()));
std::cout << "Passed\n";
for (int i = 0; i < size3; i++) {
std::cout << arr3[i] << ", ";
}
std::cout << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test();
return 0;
}
+133
View File
@@ -0,0 +1,133 @@
/**
* @file
* @brief Implementation of [Pigeonhole Sort algorithm]
* (https://en.wikipedia.org/wiki/Pigeonhole_sort)
* @author [Lownish](https://github.com/Lownish)
* @details
* Pigeonhole sorting is a sorting algorithm that is suitable for sorting lists
* of elements where the number of elements and the number of possible key
* values are approximately the same. It requires O(n + Range) time where n is
* number of elements in input array and Range is number of possible values in
* array.
*
* The time Complexity of the algorithm is \f$O(n+N)\f$.
*/
#include <algorithm> //for std::is_sorted
#include <array> //for std::array
#include <cassert> //for assert
#include <iostream> //for io operations
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* Pigeonhole sorting of array of size n
* The function will sort the array through Pigeonhole algorithm and print
* @param arr unsorted array of elements
* @returns sorted array of elements
*/
template <std::size_t N>
std::array<int, N> pigeonSort(std::array<int, N> arr) {
// Finding min and max*
auto min = std::min_element(std::begin(arr), std::end(arr));
auto max = std::max_element(std::begin(arr), std::end(arr));
// Range refers to the number of holes required
int range = *max - *min + 1;
int *hole = new int[range]();
// Copying all array values to pigeonhole
for (int i = 0; i < N; i++) {
hole[arr[i] - *min] = arr[i];
}
// Deleting elements from list and storing to original array
int count = 0;
for (int i = 0; i < range; i++) {
while (hole[i] != '\0') {
arr[count] = hole[i];
hole[i] = {};
count++;
}
}
delete[] hole;
return arr;
}
} // namespace sorting
/**
* Test function 1 with unsorted array
* {8, 3, 2, 7, 4, 6, 8}
* @returns none
*/
static void test_1() {
const int n = 7;
std::array<int, n> test_array = {8, 3, 2, 7, 4, 6, 8};
test_array = sorting::pigeonSort<n>(test_array);
assert(std::is_sorted(std::begin(test_array), std::end(test_array)));
// Printing sorted array
for (int i = 0; i < n; i++) {
std::cout << test_array.at(i) << " ";
}
std::cout << "\nPassed\n";
}
/**
* Test function 2 with unsorted array
* {802, 630, 20, 745, 52, 300, 612, 932, 78, 187}
* @returns none
*/
static void test_2() {
const int n = 10;
std::array<int, n> test_array = {802, 630, 20, 745, 52,
300, 612, 932, 78, 187};
test_array = sorting::pigeonSort<n>(test_array);
assert(std::is_sorted(std::begin(test_array), std::end(test_array)));
// Printing sorted array
for (int i = 0; i < n; i++) {
std::cout << test_array.at(i) << " ";
}
std::cout << "\nPassed\n";
}
/**
* Test function 1 with unsorted array
* {11,13,12,14}
* @returns none
*/
static void test_3() {
const int n = 4;
std::array<int, n> test_array = {11, 13, 12, 14};
test_array = sorting::pigeonSort<n>(test_array);
assert(std::is_sorted(std::begin(test_array), std::end(test_array)));
// Printing sorted array
for (int i = 0; i < n; i++) {
std::cout << test_array.at(i) << " ";
}
std::cout << "\nPassed\n";
}
/**
* Main function
*/
int main() {
test_1();
test_2();
test_3();
return 0;
}
+250
View File
@@ -0,0 +1,250 @@
/**
* @file
* @brief [Quick sort implementation](https://en.wikipedia.org/wiki/Quicksort)
* in C++
* @details
* Quick Sort is a [divide and conquer
* algorithm](https://en.wikipedia.org/wiki/Category:Divide-and-conquer_algorithms).
* It picks an element as pivot and partition the given array around the
* picked pivot. There are many different versions of quickSort that pick pivot
* in different ways.
*
* 1. Always pick the first element as pivot
* 2. Always pick the last element as pivot (implemented below)
* 3. Pick a random element as pivot
* 4. Pick median as pivot
*
* The key process in quickSort is partition(). Target of partition is,
* given an array and an element x(say) of array as pivot, put x at it's
* correct position in sorted array and put all smaller elements (samller
* than x) before x, and put all greater elements (greater than x) after
* x. All this should be done in linear time
*
* @author [David Leal](https://github.com/Panquesito7)
* @author [popoapp](https://github.com/popoapp)
*/
#include <algorithm> /// for std::is_sorted
#include <cassert> /// for std::assert
#include <cstdint>
#include <ctime> /// for std::time
#include <iostream> /// for IO operations
#include <vector> /// for std::vector
/**
* @brief Sorting algorithms
* @namespace sorting
*/
namespace sorting {
/**
* @namespace quick_sort
* @brief Functions for the [Quick sort
* implementation](https://en.wikipedia.org/wiki/Quicksort) in C++
*/
namespace quick_sort {
/**
* @brief Sorts the array taking the last element as pivot
* @details
* This function takes last element as pivot, places
* the pivot element at its correct position in sorted
* array, and places all smaller (smaller than pivot)
* to left of pivot and all greater elements to right of pivot
* @tparam T array type
* @param arr the array with contents given by the user
* @param low first point of the array (starting index)
* @param high last point of the array (ending index)
* @returns index of the smaller element
*
* ### Time Complexity
* best case, average Case: O(nlog(n))
* Worst Case: O(n^2) (Worst case occur when the partition
* is consistently unbalanced.)
* ### Space Complexity
* average Case: O(log(n))
* Worst Case: O(n)
* It's space complexity is due to the recursive function calls and partitioning process.
*/
template <typename T>
int partition(std::vector<T> *arr, const int &low, const int &high) {
T pivot = (*arr)[high]; // taking the last element as pivot
int i = (low - 1); // Index of smaller element
for (int j = low; j < high; j++) {
// If current element is smaller than or
// equal to pivot
if ((*arr)[j] <= pivot) {
i++; // increment index of smaller element
std::swap((*arr)[i], (*arr)[j]);
}
}
std::swap((*arr)[i + 1], (*arr)[high]);
return (i + 1);
}
/**
* @brief the main function that implements Quick Sort.
*
* Void function used in T (array type) function, which then
* can be used as self-tests or other functionalities.
* @tparam T array type
* @param arr array to be sorted
* @param low starting index
* @param high ending index
*/
template <typename T>
void quick_sort(std::vector<T> *arr, const int &low, const int &high) {
if (low < high) {
int p = partition(arr, low, high);
quick_sort(arr, low, p - 1);
quick_sort(arr, p + 1, high);
}
}
/**
* @brief the main function that implements Quick Sort.
*
* T (array type) function which calls the void function. Can
* be used for self-tests and other functionalities.
* @tparam T array type
* @param arr array to be sorted
* @param low starting index
* @param high ending index
*/
template <typename T>
std::vector<T> quick_sort(std::vector<T> arr, const int &low, const int &high) {
if (low < high) {
int p = partition(&arr, low, high);
quick_sort(&arr, low, p - 1);
quick_sort(&arr, p + 1, high);
}
return arr;
}
/**
* @brief Utility function to print the array contents
* @param arr the array to be printed
* @param size size of the given array
* @returns void
*/
template <typename T>
void show(const std::vector<T> &arr, const int &size) {
for (int i = 0; i < size; i++) std::cout << arr[i] << " ";
std::cout << "\n";
}
} // namespace quick_sort
} // namespace sorting
/**
* @brief Self-test implementations
* @returns void
*/
static void tests() {
// 1st test (normal numbers)
std::vector<uint64_t> arr = {5, 3, 8, 12, 14, 16, 28, 96, 2, 5977};
std::vector<uint64_t> arr_sorted = sorting::quick_sort::quick_sort(
arr, 0, int(std::end(arr) - std::begin(arr)) - 1);
assert(std::is_sorted(std::begin(arr_sorted), std::end(arr_sorted)));
std::cout << "\n1st test: passed!\n";
// 2nd test (normal and negative numbers)
std::vector<int64_t> arr2 = {9, 15, 28, 96, 500, -4, -58,
-977, -238, -800, -21, -53, -55};
std::vector<int64_t> arr_sorted2 = sorting::quick_sort::quick_sort(
arr2, 0, std::end(arr2) - std::begin(arr2));
assert(std::is_sorted(std::begin(arr_sorted2), std::end(arr_sorted2)));
std::cout << "2nd test: passed!\n";
// 3rd test (decimal and normal numbers)
std::vector<double> arr3 = {29, 36, 1100, 0, 77, 1,
6.7, 8.97, 1.74, 950.10, -329.65};
std::vector<double> arr_sorted3 = sorting::quick_sort::quick_sort(
arr3, 0, int(std::end(arr3) - std::begin(arr3)) - 1);
assert(std::is_sorted(std::begin(arr_sorted3), std::end(arr_sorted3)));
std::cout << "3rd test: passed!\n";
// 4th test (random decimal and negative numbers)
size_t size = std::rand() % 750 + 100;
std::vector<float> arr4(size);
for (uint64_t i = 0; i < size; i++) {
arr4[i] = static_cast<float>(std::rand()) /
static_cast<float>(RAND_MAX / 999.99 - 0.99) -
250;
}
std::vector<float> arr4_sorted = sorting::quick_sort::quick_sort(
arr4, 0, int(std::end(arr4) - std::begin(arr4)) - 1);
assert(std::is_sorted(std::begin(arr4_sorted), std::end(arr4_sorted)));
std::cout << "4th test: passed!\n";
// Printing all sorted arrays
std::cout << "\n\tPrinting all sorted arrays:\t\n";
std::cout << "1st array:\n";
sorting::quick_sort::show(arr_sorted, std::end(arr) - std::begin(arr));
std::cout << std::endl;
std::cout << "2nd array:\n";
sorting::quick_sort::show(arr_sorted2, std::end(arr2) - std::begin(arr2));
std::cout << std::endl;
std::cout << "3rd array:\n";
sorting::quick_sort::show(arr_sorted3,
int(std::end(arr3) - std::begin(arr3)) - 1);
std::cout << std::endl;
std::cout << "Start: 4th array:\n\n";
sorting::quick_sort::show(
arr4_sorted, int(std::end(arr4_sorted) - std::begin(arr4_sorted)) - 1);
std::cout << "\nEnd: 4th array.\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
int choice = 0;
std::cout << "\tAvailable modes\t\n\n";
std::cout << "1. Self-tests mode\n2. Interactive mode";
std::cout << "\nChoose a mode: ";
std::cin >> choice;
std::cout << "\n";
while ((choice != 1) && (choice != 2)) {
std::cout << "Invalid option. Choose between the valid modes: ";
std::cin >> choice;
}
if (choice == 1) {
std::srand(std::time(nullptr));
tests(); // run self-test implementations
} else if (choice == 2) {
int size = 0;
std::cout << "\nEnter the number of elements: ";
std::cin >> size;
std::vector<float> arr(size);
std::cout
<< "\nEnter the unsorted elements (can be negative/decimal): ";
for (int i = 0; i < size; ++i) {
std::cout << "\n";
std::cin >> arr[i];
}
sorting::quick_sort::quick_sort(&arr, 0, size - 1);
std::cout << "\nSorted array: \n";
sorting::quick_sort::show(arr, size);
}
return 0;
}
+189
View File
@@ -0,0 +1,189 @@
/**
* @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, int32_t(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, int32_t(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;
}
+132
View File
@@ -0,0 +1,132 @@
/**
* @file
* @brief Quick Sort without recursion. This method uses the stack instead.
* Both recursive and iterative implementations have O(n log n) best case
* and O(n^2) worst case.
* @details
* https://stackoverflow.com/questions/12553238/quicksort-iterative-or-recursive
* https://en.wikipedia.org/wiki/Quicksort
* https://www.geeksforgeeks.org/iterative-quick-sort/
* @author [Sebe324](https://github.com/sebe324)
*/
#include <iostream> /// for std::cout
#include <vector> /// for std::vector
#include <stack> /// for std::stack
#include <algorithm> /// for std::is_sorted
#include <cassert> /// for assert
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @brief The partition function sorts the array from
* start to end and uses the last element as the pivot.
* @param arr the array to be sorted
* @param start starting index
* @param end ending index
* @return int next index of the pivot
*/
int partition(std::vector<int> &arr, int start, int end)
{
int pivot = arr[end];
int index = start - 1;
for (int j = start; j < end; j++) {
if (arr[j] <= pivot) {
std::swap(arr[++index], arr[j]);
}
}
std::swap(arr[index + 1], arr[end]);
return index + 1;
}
/**
* @brief The main sorting function
* @details The iterative quick sort uses
* the stack instead of recursion for saving
* and restoring the environment between calls.
* It does not need the end and start params, because
* it is not recursive.
* @param arr array to be sorted
* @return void
*/
void iterativeQuickSort(std::vector<int> &arr)
{
std::stack<int> stack;
int start = 0;
int end = arr.size()-1;
stack.push(start);
stack.push(end);
while(!stack.empty())
{
end = stack.top();
stack.pop();
start = stack.top();
stack.pop();
int pivotIndex = partition(arr,start,end);
if(pivotIndex -1 > start)
{
stack.push(start);
stack.push(pivotIndex-1);
}
if(pivotIndex+1<end)
{
stack.push(pivotIndex+1);
stack.push(end);
}
}
}
} // namespace sorting
/**
* @brief Self-test implementations
* @returns void
*/
void tests()
{
//TEST 1 - Positive numbers
std::vector<int> case1={100,534,1000000,553,10,61,2000,238,2756,9,12,56,30};
std::cout<<"TEST 1\n";
std::cout<<"Before: \n";
for(auto x : case1) std::cout<<x<<",";
std::cout<<"\n";
sorting::iterativeQuickSort(case1);
assert(std::is_sorted(std::begin(case1),std::end(case1)));
std::cout<<"Test 1 succesful!\n";
std::cout<<"After: \n";
for(auto x : case1) std::cout<<x<<",";
std::cout<<"\n";
//TEST 2 - Negative numbers
std::vector<int> case2={-10,-2,-5,-2,-3746,-785,-123, -452, -32456};
std::cout<<"TEST 2\n";
std::cout<<"Before: \n";
for(auto x : case2) std::cout<<x<<",";
std::cout<<"\n";
sorting::iterativeQuickSort(case2);
assert(std::is_sorted(std::begin(case2),std::end(case2)));
std::cout<<"Test 2 succesful!\n";
std::cout<<"After: \n";
for(auto x : case2) std::cout<<x<<",";
std::cout<<"\n";
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main()
{
tests(); // run self test implementation
return 0;
}
+58
View File
@@ -0,0 +1,58 @@
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <iostream>
void radixsort(int a[], int n) {
int count[10];
int* output = new int[n];
memset(output, 0, n * sizeof(*output));
memset(count, 0, sizeof(count));
int max = 0;
for (int i = 0; i < n; ++i) {
if (a[i] > max) {
max = a[i];
}
}
int maxdigits = 0;
while (max) {
maxdigits++;
max /= 10;
}
for (int j = 0; j < maxdigits; j++) {
for (int i = 0; i < n; i++) {
int t = std::pow(10, j);
count[(a[i] % (10 * t)) / t]++;
}
int k = 0;
for (int p = 0; p < 10; p++) {
for (int i = 0; i < n; i++) {
int t = std::pow(10, j);
if ((a[i] % (10 * t)) / t == p) {
output[k] = a[i];
k++;
}
}
}
memset(count, 0, sizeof(count));
for (int i = 0; i < n; ++i) {
a[i] = output[i];
}
}
delete[] output;
}
void print(int a[], int n) {
for (int i = 0; i < n; ++i) {
std::cout << a[i] << " ";
}
std::cout << std::endl;
}
int main() {
int a[] = {170, 45, 75, 90, 802, 24, 2, 66};
int n = sizeof(a) / sizeof(a[0]);
radixsort(a, n);
print(a, n);
return 0;
}
+122
View File
@@ -0,0 +1,122 @@
/**
* @file
* @brief Algorithm of [Radix sort](https://en.wikipedia.org/wiki/Radix_sort)
* @author [Suyash Jaiswal](https://github.com/Suyashjaiswal)
* @details
* Sort the vector of unsigned integers using radix sort i.e. sorting digit by
* digit using [Counting Sort](https://en.wikipedia.org/wiki/Counting_sort) as
* subroutine. Running time of radix sort is O(d*(n+b)) where b is the base for
* representing numbers and d in the max digits in input integers and n is
* number of unsigned integers. consider example for n = 5, aray elements =
* 432,234,143,332,123 sorting digit by digit sorting according to 1) 1st digit
* place
* => 432, 332, 143, 123, 234
*
* 2) 2nd digit place
* => 123, 432, 332, 234, 143
*
* 3) 3rd digit place
* => 123, 143, 234, 332, 432
*
* using count sort at each step, which is stable.
* stable => already sorted according to previous digits.
*/
/// header files
#include <algorithm> /// for collection of functions
#include <cassert> /// for a macro called assert which can be used to verify assumptions
#include <cstdint>
#include <iostream> /// for io operations
#include <vector> /// for std::vector
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace radix_sort
* @brief Functions for [Radix sort](https://en.wikipedia.org/wiki/Radix_sort)
* algorithm
*/
namespace radix_sort {
/**
* @brief Function to sort vector according to current digit using stable
* sorting.
* @param cur_digit - sort according to the cur_digit
* @param ar - vector to be sorted
* @returns std::vector sorted till ith digit
*/
std::vector<uint64_t> step_ith(
uint16_t cur_digit,
const std::vector<uint64_t>& ar) { // sorting according to current digit.
int n = ar.size();
std::vector<uint32_t> position(10, 0);
for (int i = 0; i < n; ++i) {
position[(ar[i] / cur_digit) %
10]++; // counting frequency of 0-9 at cur_digit.
}
int cur = 0;
for (int i = 0; i < 10; ++i) {
int a = position[i];
position[i] = cur; // assingning starting position of 0-9.
cur += a;
}
std::vector<uint64_t> temp(n);
for (int i = 0; i < n; ++i) {
temp[position[(ar[i] / cur_digit) % 10]] =
ar[i]; // storing ar[i] in ar[i]'s cur_digit expected position of
// this step.
position[(ar[i] / cur_digit) %
10]++; // incrementing ar[i]'s cur_digit position by 1, as
// current place used by ar[i].
}
return temp;
}
/**
* @brief Function to sort vector digit by digit.
* @param ar - vector to be sorted
* @returns sorted vector
*/
std::vector<uint64_t> radix(const std::vector<uint64_t>& ar) {
uint64_t max_ele =
*max_element(ar.begin(), ar.end()); // returns the max element.
std::vector<uint64_t> temp = ar;
for (int i = 1; max_ele / i > 0;
i *= 10) { // loop breaks when i > max_ele because no further digits
// left to makes changes in aray.
temp = step_ith(i, temp);
}
for (uint64_t i : temp) {
std::cout << i << " ";
}
std::cout << "\n";
return temp;
}
} // namespace radix_sort
} // namespace sorting
/**
* @brief Function to test the above algorithm
* @returns none
*/
static void tests() {
/// Test 1
std::vector<uint64_t> ar1 = {432, 234, 143, 332, 123};
ar1 = sorting::radix_sort::radix(ar1);
assert(std::is_sorted(ar1.begin(), ar1.end()));
/// Test 2
std::vector<uint64_t> ar2 = {213, 3214, 123, 111, 112, 142,
133, 132, 32, 12, 113};
ar2 = sorting::radix_sort::radix(ar2);
assert(std::is_sorted(ar2.begin(), ar2.end()));
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // execute the tests
return 0;
}
+337
View File
@@ -0,0 +1,337 @@
/**
* @file
* @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.
*
* ### 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.
*
* ### 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.
*
* ### 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.
* * Return the partition index from the function.
*
* @author [Nitin Sharma](https://github.com/foo290)
*/
#include <algorithm> /// for std::is_sorted(), std::swap()
#include <array> /// for std::array
#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
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @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;
}
/**
* @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;
}
} // namespace random_pivot_quick_sort
} // namespace sorting
/**
* @brief a class containing the necessary test cases
*/
class TestCases {
private:
/**
* @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:
/**
* @brief Executes test cases
* @returns void
* */
void runTests() {
log("Running Tests...");
testCase_1();
testCase_2();
testCase_3();
log("Test Cases over!");
std::cout << std::endl;
}
/**
* @brief A test case with single input
* @returns void
* */
void testCase_1() {
const int64_t inputSize = 1;
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};
int64_t start = 0;
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);
log("Algorithm finished!");
log("Checking assert expression...");
assert(std::is_sorted(sorted_arr.begin(), sorted_arr.end()));
log("Assertion check passed!");
log("[PASS] : TEST CASE 1 PASS!");
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
"~");
}
/**
* @brief A test case with input array of length 500
* @returns void
* */
void testCase_2() {
const int64_t inputSize = 500;
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);
int64_t start = 0;
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);
log("Algorithm finished!");
log("Checking assert expression...");
assert(std::is_sorted(sorted_arr.begin(), sorted_arr.end()));
log("Assertion check passed!");
log("[PASS] : TEST CASE 2 PASS!");
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
"~");
}
/**
* @brief A test case with array of length 1000.
* @returns void
* */
void testCase_3() {
const int64_t inputSize = 1000;
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);
int64_t start = 0;
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);
log("Algorithm finished!");
log("Checking assert expression...");
assert(std::is_sorted(sorted_arr.begin(), sorted_arr.end()));
log("Assertion check passed!");
log("[PASS] : TEST CASE 3 PASS!");
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
"~");
}
};
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
TestCases tc = TestCases();
tc.runTests();
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
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::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::cout << "Sorted array is : " << std::endl;
sorting::random_pivot_quick_sort::showArray(sorted_array);
return 0;
}
+157
View File
@@ -0,0 +1,157 @@
/**
* @file
* @author [Aditya Prakash](https://adityaprakash.tech)
* @brief This is an implementation of a recursive version of the [Bubble sort
algorithm](https://www.geeksforgeeks.org/recursive-bubble-sort/)
*
* @details
* The working principle of the Bubble sort algorithm.
* Bubble sort is a simple sorting algorithm used to rearrange a set of
ascending or descending order elements.
* Bubble sort gets its name from the fact that data "bubbles" to the top of the
dataset.
* ### Algorithm
* What is Swap?
* Swapping two numbers means that we interchange their values.
* Often, an additional variable is required for this operation.
* This is further illustrated in the following:
* void swap(int x, int y){
* int z = x;
* x = y;
* y = z;
* }
* The above process is a typical displacement process.
* When we assign a value to x, the old value of x is lost.
* That's why we create a temporary variable z to store the initial value of x.
* z is further used to assign the initial value of x to y, to complete
swapping.
* Recursion
* While the recursive method does not necessarily have advantages over
iterative
* versions, but it is useful to enhance the understanding of the algorithm and
* recursion itself. In Recursive Bubble sort algorithm, we firstly call the
* function on the entire array, and for every subsequent function call, we
exclude
* the last element. This fixes the last element for that sub-array.Formally,
for
* `ith` iteration, we consider elements up to n-i, where n is the number of
* elements in the array. Exit condition: n==1; i.e. the sub-array contains only
* one element.
* Complexity
* Time complexity: O(n) best case; O(n²) average case; O(n²) worst case
* Space complexity: O(n)
* We need to traverse the array `n * (n-1)` times. However, if the entire array
is
* already sorted, then we need to traverse it only once. Hence, O(n) is the
best case
* complexity
*/
#include <algorithm> /// for std::is_sorted
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for IO operations
#include <vector> /// for std::vector
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @brief This is an implementation of the recursive_bubble_sort. A vector is
* passed to the function which is then dereferenced, so that the changes are
* reflected in the original vector. It also accepts a second parameter of
* type `int` and name `n`, which is the size of the array.
*
* @tparam T type of data variables in the array
* @param nums our array of elements.
* @param n size of the array
*/
template <typename T>
void recursive_bubble_sort(std::vector<T> *nums, uint64_t n) {
if (n == 1) { //!< base case; when size of the array is 1
return;
}
for (uint64_t i = 0; i < n - 1; i++) { //!< iterating over the entire array
//!< if a larger number appears before the smaller one, swap them.
if ((*nums)[i] > (*nums)[i + 1]) {
std::swap((*nums)[i], (*nums)[i + 1]);
}
}
//!< calling the function after we have fixed the last element
recursive_bubble_sort(nums, n - 1);
}
} // namespace sorting
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// 1st example. Creating an array of type `int`.
std::cout << "1st test using `int`\n";
const uint64_t size = 6;
std::vector<int64_t> arr;
// populating the array
arr.push_back(22);
arr.push_back(46);
arr.push_back(94);
arr.push_back(12);
arr.push_back(37);
arr.push_back(63);
// array populating ends
sorting::recursive_bubble_sort(&arr, size);
assert(std::is_sorted(std::begin(arr), std::end(arr)));
std::cout << " 1st test passed!\n";
// printing the array
for (uint64_t i = 0; i < size; i++) {
std::cout << arr[i] << ", ";
}
std::cout << std::endl;
// 2nd example. Creating an array of type `double`.
std::cout << "2nd test using doubles\n";
std::vector<double> double_arr;
// populating the array
double_arr.push_back(20.4);
double_arr.push_back(62.7);
double_arr.push_back(12.2);
double_arr.push_back(43.6);
double_arr.push_back(74.1);
double_arr.push_back(57.9);
// array populating ends
sorting::recursive_bubble_sort(&double_arr, size);
assert(std::is_sorted(std::begin(double_arr), std::end(double_arr)));
std::cout << " 2nd test passed!\n";
// printing the array
for (uint64_t i = 0; i < size; i++) {
std::cout << double_arr[i] << ", ";
}
std::cout << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+127
View File
@@ -0,0 +1,127 @@
/******************************************************************************
* @file
* @brief Implementation of the [Selection
* sort](https://en.wikipedia.org/wiki/Selection_sort) implementation using
* swapping
* @details
* The selection sort algorithm divides the input vector into two parts: a
* sorted subvector of items which is built up from left to right at the front
* (left) of the vector, and a subvector of the remaining unsorted items that
* occupy the rest of the vector. Initially, the sorted subvector is empty, and
* the unsorted subvector is the entire input vector. The algorithm proceeds by
* finding the smallest (or largest, depending on the sorting order) element in
* the unsorted subvector, exchanging (swapping) it with the leftmost unsorted
* element (putting it in sorted order), and moving the subvector boundaries one
* element to the right.
*
* ### Implementation
*
* SelectionSort
* The algorithm divides the input vector into two parts: the subvector of items
* already sorted, which is built up from left to right. Initially, the sorted
* subvector is empty and the unsorted subvector is the entire input vector. The
* algorithm proceeds by finding the smallest element in the unsorted subvector,
* exchanging (swapping) it with the leftmost unsorted element (putting it in
* sorted order), and moving the subvector boundaries one element to the right.
*
* @author [Lajat Manekar](https://github.com/Lazeeez)
* @author Unknown author
*******************************************************************************/
#include <algorithm> /// for std::is_sorted
#include <cassert> /// for std::assert
#include <cstdint>
#include <iostream> /// for IO operations
#include <vector> /// for std::vector
/******************************************************************************
* @namespace sorting
* @brief Sorting algorithms
*******************************************************************************/
namespace sorting {
/******************************************************************************
* @brief The main function which implements Selection sort
* @param arr vector to be sorted
* @param len length of vector to be sorted
* @returns @param array resultant sorted vector
*******************************************************************************/
std::vector<uint64_t> selectionSort(const std::vector<uint64_t> &arr,
uint64_t len) {
std::vector<uint64_t> array(
arr.begin(),
arr.end()); // declare a vector in which result will be stored
for (uint64_t it = 0; it < len; ++it) {
uint64_t min = it; // set min value
for (uint64_t it2 = it + 1; it2 < len; ++it2) {
if (array[it2] < array[min]) { // check which element is smaller
min = it2; // store index of smallest element to min
}
}
if (min != it) { // swap if min does not match to i
uint64_t tmp = array[min];
array[min] = array[it];
array[it] = tmp;
}
}
return array; // return sorted vector
}
} // namespace sorting
/*******************************************************************************
* @brief Self-test implementations
* @returns void
*******************************************************************************/
static void test() {
// testcase #1
// [1, 0, 0, 1, 1, 0, 2, 1] returns [0, 0, 0, 1, 1, 1, 1, 2]
std::vector<uint64_t> vector1 = {1, 0, 0, 1, 1, 0, 2, 1};
uint64_t vector1size = vector1.size();
std::cout << "1st test... ";
std::vector<uint64_t> result_test1;
result_test1 = sorting::selectionSort(vector1, vector1size);
assert(std::is_sorted(result_test1.begin(), result_test1.end()));
std::cout << "Passed" << std::endl;
// testcase #2
// [19, 22, 540, 241, 156, 140, 12, 1] returns [1, 12, 19, 22, 140, 156,
// 241,540]
std::vector<uint64_t> vector2 = {19, 22, 540, 241, 156, 140, 12, 1};
uint64_t vector2size = vector2.size();
std::cout << "2nd test... ";
std::vector<uint64_t> result_test2;
result_test2 = sorting::selectionSort(vector2, vector2size);
assert(std::is_sorted(result_test2.begin(), result_test2.end()));
std::cout << "Passed" << std::endl;
// testcase #3
// [11, 20, 30, 41, 15, 60, 82, 15] returns [11, 15, 15, 20, 30, 41, 60, 82]
std::vector<uint64_t> vector3 = {11, 20, 30, 41, 15, 60, 82, 15};
uint64_t vector3size = vector3.size();
std::cout << "3rd test... ";
std::vector<uint64_t> result_test3;
result_test3 = sorting::selectionSort(vector3, vector3size);
assert(std::is_sorted(result_test3.begin(), result_test3.end()));
std::cout << "Passed" << std::endl;
// testcase #4
// [1, 9, 11, 546, 26, 65, 212, 14, -11] returns [-11, 1, 9, 11, 14, 26, 65,
// 212, 546]
std::vector<uint64_t> vector4 = {1, 9, 11, 546, 26, 65, 212, 14};
uint64_t vector4size = vector2.size();
std::cout << "4th test... ";
std::vector<uint64_t> result_test4;
result_test4 = sorting::selectionSort(vector4, vector4size);
assert(std::is_sorted(result_test4.begin(), result_test4.end()));
std::cout << "Passed" << std::endl;
}
/*******************************************************************************
* @brief Main function
* @returns 0 on exit
*******************************************************************************/
int main() {
test(); // run self-test implementations
return 0;
}
+133
View File
@@ -0,0 +1,133 @@
/**
* @file
* @brief Implementation of the [Selection
* sort](https://en.wikipedia.org/wiki/Selection_sort)
* implementation using recursion
* @details
* The selection sort algorithm divides the input list into two parts: a sorted
* sublist of items which is built up from left to right at the front (left) of
* the list, and a sublist of the remaining unsorted items that occupy the rest
* of the list. Initially, the sorted sublist is empty, and the unsorted sublist
* is the entire input list. The algorithm proceeds by finding the smallest (or
* largest, depending on the sorting order) element in the unsorted sublist,
* exchanging (swapping) it with the leftmost unsorted element (putting it in
* sorted order), and moving the sublist boundaries one element to the right.
*
* ### Implementation
* FindMinIndex
* This function finds the minimum element of the array(list) recursively by
* simply comparing the minimum element of array reduced size by 1 and compares
* it to the last element of the array to find the minimum of the whole array.
*
* SelectionSortRecursive
* Just like selection sort, it divides the list into two parts (i.e.: sorted
* and unsorted) and finds the minimum of the unsorted array. By calling the
* `FindMinIndex` function, it swaps the minimum element with the first element
* of the list, and then solves recursively for the remaining unsorted list.
* @author [Tushar Khanduri](https://github.com/Tushar-K24)
*/
#include <algorithm> /// for std::is_sorted
#include <cassert> /// for assert
#include <cstdint>
#include <iostream> /// for std::swap and io operations
#include <vector> /// for std::vector
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace selection_sort_recursive
* @brief Functions for the [Selection
* sort](https://en.wikipedia.org/wiki/Selection_sort)
* implementation using recursion
*/
namespace selection_sort_recursive {
/**
* @brief The main function finds the index of the minimum element
* @tparam T type of array
* @param in_arr array whose minimum element is to be returned
* @param current_position position/index from where the in_arr starts
* @returns index of the minimum element
*/
template <typename T>
uint64_t findMinIndex(const std::vector<T> &in_arr,
uint64_t current_position = 0) {
if (current_position + 1 == in_arr.size()) {
return current_position;
}
uint64_t answer = findMinIndex(in_arr, current_position + 1);
if (in_arr[current_position] < in_arr[answer]) {
answer = current_position;
}
return answer;
}
/**
* @brief The main function implements Selection sort
* @tparam T type of array
* @param in_arr array to be sorted,
* @param current_position position/index from where the in_arr starts
* @returns void
*/
template <typename T>
void selectionSortRecursive(std::vector<T> &in_arr,
uint64_t current_position = 0) {
if (current_position == in_arr.size()) {
return;
}
uint64_t min_element_idx =
selection_sort_recursive::findMinIndex(in_arr, current_position);
if (min_element_idx != current_position) {
std::swap(in_arr[min_element_idx], in_arr[current_position]);
}
selectionSortRecursive(in_arr, current_position + 1);
}
} // namespace selection_sort_recursive
} // namespace sorting
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// 1st test
// [1, 0, 2, 1] return [0, 1, 1, 2]
std::vector<uint64_t> array1 = {0, 1, 1, 2};
std::cout << "1st test... ";
sorting::selection_sort_recursive::selectionSortRecursive(array1);
assert(std::is_sorted(std::begin(array1), std::end(array1)));
std::cout << "passed" << std::endl;
// 2nd test
// [1, 0, 0, 1, 1, 0, 2, 1] return [0, 0, 0, 1, 1, 1, 1, 2]
std::vector<uint64_t> array2 = {1, 0, 0, 1, 1, 0, 2, 1};
std::cout << "2nd test... ";
sorting::selection_sort_recursive::selectionSortRecursive(array2);
assert(std::is_sorted(std::begin(array2), std::end(array2)));
std::cout << "passed" << std::endl;
// 3rd test
// [1, 1, 0, 0, 1, 2, 2, 0, 2, 1] return [0, 0, 0, 1, 1, 1, 1, 2, 2, 2]
std::vector<uint64_t> array3 = {1, 1, 0, 0, 1, 2, 2, 0, 2, 1};
std::cout << "3rd test... ";
sorting::selection_sort_recursive::selectionSortRecursive(array3);
assert(std::is_sorted(std::begin(array3), std::end(array3)));
std::cout << "passed" << std::endl;
// 4th test
// [2, 2, 2, 0, 0, 1, 1] return [0, 0, 1, 1, 2, 2, 2]
std::vector<uint64_t> array4 = {2, 2, 2, 0, 0, 1, 1};
std::cout << "4th test... ";
sorting::selection_sort_recursive::selectionSortRecursive(array4);
assert(std::is_sorted(std::begin(array4), std::end(array4)));
std::cout << "passed" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+37
View File
@@ -0,0 +1,37 @@
#include <iostream>
int main() {
int size = 10;
int* array = new int[size];
// Input
std::cout << "\nHow many numbers do want to enter in unsorted array : ";
std::cin >> size;
std::cout << "\nEnter the numbers for unsorted array : ";
for (int i = 0; i < size; i++) {
std::cin >> array[i];
}
// Sorting
for (int i = size / 2; i > 0; i = i / 2) {
for (int j = i; j < size; j++) {
for (int k = j - i; k >= 0; k = k - i) {
if (array[k] < array[k + i]) {
break;
} else {
int temp = array[k + i];
array[k + i] = array[k];
array[k] = temp;
}
}
}
}
// Output
std::cout << "\nSorted array : ";
for (int i = 0; i < size; ++i) {
std::cout << array[i] << "\t";
}
delete[] array;
return 0;
}
+234
View File
@@ -0,0 +1,234 @@
/**
* \file
* \brief [Shell sort](https://en.wikipedia.org/wiki/Shell_sort) algorithm
* \author [Krishna Vedala](https://github.com/kvedala)
*/
#include <cassert>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <utility> // for std::swap
#include <vector>
/** pretty print array
* \param[in] arr array to print
* \param[in] LEN length of array to print
*/
template <class T>
void show_data(T *arr, size_t LEN) {
size_t i;
for (i = 0; i < LEN; i++) {
std::cout << arr[i] << ", ";
}
std::cout << std::endl;
}
/** pretty print array
* \param[in] arr array to print
* \param[in] N length of array to print
*/
template <typename T, size_t N>
void show_data(T (&arr)[N]) {
show_data(arr, N);
}
/** \namespace sorting
* \brief Sorting algorithms
*/
namespace sorting {
/**
* Optimized algorithm - takes half the time by utilizing
* Mar
**/
template <typename T>
void shell_sort(T *arr, size_t LEN) {
const unsigned int gaps[] = {701, 301, 132, 57, 23, 10, 4, 1};
const unsigned int gap_len = 8;
size_t i, j, g;
for (g = 0; g < gap_len; g++) {
unsigned int gap = gaps[g];
for (i = gap; i < LEN; i++) {
T tmp = arr[i];
for (j = i; j >= gap && (arr[j - gap] - tmp) > 0; j -= gap) {
arr[j] = arr[j - gap];
}
arr[j] = tmp;
}
}
}
/** function overload - when input array is of a known length array type
*/
template <typename T, size_t N>
void shell_sort(T (&arr)[N]) {
shell_sort(arr, N);
}
/** function overload - when input array is of type std::vector,
* simply send the data content and the data length to the above function.
*/
template <typename T>
void shell_sort(std::vector<T> *arr) {
shell_sort(arr->data(), arr->size());
}
} // namespace sorting
using sorting::shell_sort;
/**
* function to compare sorting using cstdlib's qsort
**/
template <typename T>
int compare(const void *a, const void *b) {
T arg1 = *static_cast<const T *>(a);
T arg2 = *static_cast<const T *>(b);
if (arg1 < arg2)
return -1;
if (arg1 > arg2)
return 1;
return 0;
// return (arg1 > arg2) - (arg1 < arg2); // possible shortcut
// return arg1 - arg2; // erroneous shortcut (fails if INT_MIN is present)
}
/**
* Test implementation of shell_sort on integer arrays by comparing results
* against std::qsort.
*/
void test_int(const int NUM_DATA) {
// int array = new int[NUM_DATA];
int *data = new int[NUM_DATA];
int *data2 = new int[NUM_DATA];
// int array2 = new int[NUM_DATA];
int range = 1800;
for (int i = 0; i < NUM_DATA; i++)
data[i] = data2[i] = (std::rand() % range) - (range >> 1);
/* sort using our implementation */
std::clock_t start = std::clock();
shell_sort(data, NUM_DATA);
std::clock_t end = std::clock();
double elapsed_time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
std::cout << "Time spent sorting using shell_sort2: " << elapsed_time
<< "s\n";
/* sort using std::qsort */
start = std::clock();
std::qsort(data2, NUM_DATA, sizeof(data2[0]), compare<int>);
end = std::clock();
elapsed_time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
std::cout << "Time spent sorting using std::qsort: " << elapsed_time
<< "s\n";
for (int i = 0; i < NUM_DATA; i++) {
assert(data[i] == data2[i]); // ensure that our sorting results match
// the standard results
}
delete[] data;
delete[] data2;
}
/**
* Test implementation of shell_sort on float arrays by comparing results
* against std::qsort.
*/
void test_f(const int NUM_DATA) {
// int array = new int[NUM_DATA];
float *data = new float[NUM_DATA];
float *data2 = new float[NUM_DATA];
// int array2 = new int[NUM_DATA];
int range = 1000;
for (int i = 0; i < NUM_DATA; i++) {
data[i] = data2[i] = ((std::rand() % range) - (range >> 1)) / 100.;
}
/* sort using our implementation */
std::clock_t start = std::clock();
shell_sort(data, NUM_DATA);
std::clock_t end = std::clock();
double elapsed_time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
std::cout << "Time spent sorting using shell_sort2: " << elapsed_time
<< "s\n";
/* sort using std::qsort */
start = std::clock();
std::qsort(data2, NUM_DATA, sizeof(data2[0]), compare<float>);
end = std::clock();
elapsed_time = static_cast<double>(end - start) / CLOCKS_PER_SEC;
std::cout << "Time spent sorting using std::qsort: " << elapsed_time
<< "s\n";
for (int i = 0; i < NUM_DATA; i++) {
assert(data[i] == data2[i]); // ensure that our sorting results match
// the standard results
}
delete[] data;
delete[] data2;
}
/** Main function */
int main(int argc, char *argv[]) {
// initialize random number generator - once per program
std::srand(std::time(NULL));
test_int(100); // test with sorting random array of 100 values
std::cout << "Test 1 - 100 int values - passed. \n";
test_int(1000); // test with sorting random array of 1000 values
std::cout << "Test 2 - 1000 int values - passed.\n";
test_int(10000); // test with sorting random array of 10000 values
std::cout << "Test 3 - 10000 int values - passed.\n";
test_f(100); // test with sorting random array of 100 values
std::cout << "Test 1 - 100 float values - passed. \n";
test_f(1000); // test with sorting random array of 1000 values
std::cout << "Test 2 - 1000 float values - passed.\n";
test_f(10000); // test with sorting random array of 10000 values
std::cout << "Test 3 - 10000 float values - passed.\n";
int i, NUM_DATA;
if (argc == 2)
NUM_DATA = atoi(argv[1]);
else
NUM_DATA = 200;
// int array = new int[NUM_DATA];
int *data = new int[NUM_DATA];
// int array2 = new int[NUM_DATA];
int range = 1800;
std::srand(time(NULL));
for (i = 0; i < NUM_DATA; i++) {
// allocate random numbers in the given range
data[i] = (std::rand() % range) - (range >> 1);
}
std::cout << "Unsorted original data: " << std::endl;
show_data(data, NUM_DATA);
std::clock_t start = std::clock();
shell_sort(data, NUM_DATA); // perform sorting
std::clock_t end = std::clock();
std::cout << std::endl
<< "Data Sorted using custom implementation: " << std::endl;
show_data(data, NUM_DATA);
double elapsed_time = (end - start) * 1.f / CLOCKS_PER_SEC;
std::cout << "Time spent sorting: " << elapsed_time << "s\n" << std::endl;
delete[] data;
return 0;
}
+56
View File
@@ -0,0 +1,56 @@
// Returns the sorted vector after performing SlowSort
// It is a sorting algorithm that is of humorous nature and not useful.
// It's based on the principle of multiply and surrender, a tongue-in-cheek joke
// of divide and conquer. It was published in 1986 by Andrei Broder and Jorge
// Stolfi in their paper Pessimal Algorithms and Simplexity Analysis. This
// algorithm multiplies a single problem into multiple subproblems It is
// interesting because it is provably the least efficient sorting algorithm that
// can be built asymptotically, and with the restriction that such an algorithm,
// while being slow, must still all the time be working towards a result.
#include <iostream>
void SlowSort(int a[], int i, int j) {
if (i >= j)
return;
int m = i + (j - i) / 2; // midpoint, implemented this way to avoid
// overflow
int temp;
SlowSort(a, i, m);
SlowSort(a, m + 1, j);
if (a[j] < a[m]) {
temp = a[j]; // swapping a[j] & a[m]
a[j] = a[m];
a[m] = temp;
}
SlowSort(a, i, j - 1);
}
// Sample Main function
int main() {
int size;
std::cout << "\nEnter the number of elements : ";
std::cin >> size;
int *arr = new int[size];
std::cout << "\nEnter the unsorted elements : ";
for (int i = 0; i < size; ++i) {
std::cout << "\n";
std::cin >> arr[i];
}
SlowSort(arr, 0, size);
std::cout << "Sorted array\n";
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << " ";
}
delete[] arr;
return 0;
}
+84
View File
@@ -0,0 +1,84 @@
/**
* @file
* @brief [Stooge sort implementation](https://en.wikipedia.org/wiki/Stooge_sort)
* in C++
* @details
* Stooge sort is a recursive sorting algorithm.
* It divides the array into 3 parts and proceeds to:
* - sort first two thirds of the array
* - sort last two thirds of the array
* - sort first two thirds of the array
* It's time complexity is O(n^(log3/log1.5)), which is about O(n^2.7),
* which makes it to be not the most efficient sorting algorithm
* on the street on average. Space complexity is O(1).
*/
#include <vector> /// for vector
#include <cassert> /// for assert
#include <algorithm> /// for std::is_sorted
#include <iostream> /// for IO operations
/**
* @brief The stoogeSort() function is used for sorting the array.
* @param L - vector of values (int) to be sorted in in place (ascending order)
* @param i - the first index of the array (0)
* @param j - the last index of the array (L.size() - 1)
* @returns void
*/
void stoogeSort(std::vector<int>* L, size_t i, size_t j) {
if (i >= j) {
return;
}
if ((*L)[i] > (*L)[j]) {
std::swap((*L)[i], (*L)[j]);
}
if (j - i > 1) {
size_t third = (j - i + 1) / 3;
stoogeSort(L, i, j - third);
stoogeSort(L, i + third, j);
stoogeSort(L, i, j - third);
}
}
/**
* @brief Function to test sorting algorithm
* @returns void
*/
void test1() {
std::vector<int> L = { 8, 9, 10, 4, 3, 5, 1 };
stoogeSort(&L, 0, L.size() - 1);
assert(std::is_sorted(std::begin(L), std::end(L)));
}
/**
* @brief Function to test sorting algorithm, one element
* @returns void
*/
void test2() {
std::vector<int> L = { -1 };
stoogeSort(&L, 0, L.size() - 1);
assert(std::is_sorted(std::begin(L), std::end(L)));
}
/**
* @brief Function to test sorting algorithm, repeating elements
* @returns void
*/
void test3() {
std::vector<int> L = { 1, 2, 5, 4, 1, 5 };
stoogeSort(&L, 0, L.size() - 1);
assert(std::is_sorted(std::begin(L), std::end(L)));
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test1();
test2();
test3();
std::cout << "All tests have successfully passed!\n";
return 0;
}
+87
View File
@@ -0,0 +1,87 @@
/**
* @file strand_sort.cpp
* @brief Implementation of [Strand Sort](https://en.wikipedia.org/wiki/Strand_sort) algorithm.
*
* @details
* Strand Sort is a sorting algorithm that works in \f$O(n)\f$ time if list is already sorted and works in \f$O(n^2)\f$ in worst case.
*
* It is passed over the array to be sorted once and the ascending (sequential) numbers are taken.
* After the first iteration, the sequential sub-array is put on the empty sorted array.
* The main sequence is passed over again and a new sub-sequence is created in order.
* Now that the sorted array is not empty, the newly extracted substring is merged with the sorted array.
* Repeat types 3 and 4 until the sub-sequence and main sequence are empty.
*
* @author [Mertcan Davulcu](https://github.com/mertcandav)
*/
#include <iostream>
#include <list>
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace strand
* @brief Functions for [Strand Sort](https://en.wikipedia.org/wiki/Strand_sort) algorithm
*/
namespace strand {
/**
* @brief Apply sorting
* @tparam element type of list
* @param lst List to be sorted
* @returns Sorted list<T> instance
*/
template <typename T>
std::list<T> strand_sort(std::list<T> lst) {
if (lst.size() < 2) { // Returns list if empty or contains only one element
return lst; // Returns list
}
std::list<T> result; // Define new "result" named list instance.
std::list<T> sorted; // Define new "sorted" named list instance.
while(!lst.empty()) /* if lst is not empty */ {
sorted.push_back(lst.front()); // Adds the first element of "lst" list to the bottom of the "sorted" list.
lst.pop_front(); // Remove first element of "lst" list.
for (auto it = lst.begin(); it != lst.end(); ) { // Return the loop as long as the current iterator is not equal to the last literator of the "lst" list.
if (sorted.back() <= *it) { // If the last reference of the "sorted" list is less than or equal to the current iterator reference.
sorted.push_back(*it); // Adds the iterator retrieved in the loop under the "sorted" list.
it = lst.erase(it); // Deletes the element with the current iterator and assigns the deleted element to the iterator.
} else {
it++; // Next iterator.
}
}
result.merge(sorted); // Merge "result" list with "sorted" list.
}
return result; // Returns sorted list
}
} // namespace strand
} // namespace sorting
/**
* @brief Function for testing
* @return N/A
*/
static void test() {
std::list<int> lst = { -333, 525, 1, 0, 94, 52, 33 };
std::cout << "Before: ";
for(auto item: lst) {
std::cout << item << " ";
}
lst = sorting::strand::strand_sort(lst); // Sort list.
std::cout << "\nAfter: ";
for(auto item: lst) {
std::cout << item << " ";
}
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test();
return 0;
}
+68
View File
@@ -0,0 +1,68 @@
// C++ program to find minimum number of swaps required to sort an array
#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
// Function returns the minimum number of swaps
// required to sort the array
int minSwaps(int arr[], int n) {
// Create an array of pairs where first
// element is array element and second element
// is position of first element
std::pair<int, int> *arrPos = new std::pair<int, int>[n];
for (int i = 0; i < n; i++) {
arrPos[i].first = arr[i];
arrPos[i].second = i;
}
// Sort the array by array element values to
// get right position of every element as second
// element of pair.
std::sort(arrPos, arrPos + n);
// To keep track of visited elements. Initialize
// all elements as not visited or false.
std::vector<bool> vis(n, false);
// Initialize result
int ans = 0;
// Traverse array elements
for (int i = 0; i < n; i++) {
// already swapped and corrected or
// already present at correct pos
if (vis[i] || arrPos[i].second == i)
continue;
// find out the number of node in
// this cycle and add in ans
int cycle_size = 0;
int j = i;
while (!vis[j]) {
vis[j] = 1;
// move to next node
j = arrPos[j].second;
cycle_size++;
}
// Update answer by adding current cycle.
if (cycle_size > 0) {
ans += (cycle_size - 1);
}
}
delete[] arrPos;
// Return result
return ans;
}
// program to test
int main() {
int arr[] = {6, 7, 8, 1, 2, 3, 9, 12};
int n = (sizeof(arr) / sizeof(int));
std::cout << minSwaps(arr, n);
return 0;
}
+125
View File
@@ -0,0 +1,125 @@
// C++ program to perform TimSort.
#include <algorithm>
#include <cassert>
#include <iostream>
#include <numeric>
const int RUN = 32;
// this function sorts array from left index to to right index which is of size
// atmost RUN
void insertionSort(int arr[], int left, int right) {
for (int i = left + 1; i <= right; i++) {
const int temp = arr[i];
int j = i - 1;
while (j >= left && arr[j] > temp) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
// merge function merges the sorted runs
void merge(int arr[], int l, int m, int r) {
// original array is broken in two parts, left and right array
const int len1 = m - l + 1, len2 = r - m;
int *left = new int[len1], *right = new int[len2];
for (int i = 0; i < len1; i++) left[i] = arr[l + i];
for (int i = 0; i < len2; i++) right[i] = arr[m + 1 + i];
int i = 0;
int j = 0;
int k = l;
// after comparing, we merge those two array in larger sub array
while (i < len1 && j < len2) {
if (left[i] <= right[j]) {
arr[k] = left[i];
i++;
} else {
arr[k] = right[j];
j++;
}
k++;
}
// copy remaining elements of left, if any
while (i < len1) {
arr[k] = left[i];
k++;
i++;
}
// copy remaining element of right, if any
while (j < len2) {
arr[k] = right[j];
k++;
j++;
}
delete[] left;
delete[] right;
}
// iterative Timsort function to sort the array[0...n-1] (similar to merge sort)
void timSort(int arr[], int n) {
// Sort individual subarrays of size RUN
for (int i = 0; i < n; i += RUN)
insertionSort(arr, i, std::min((i + 31), (n - 1)));
// start merging from size RUN (or 32). It will merge to form size 64, then
// 128, 256 and so on ....
for (int size = RUN; size < n; size = 2 * size) {
// pick starting point of left sub array. We are going to merge
// arr[left..left+size-1] and arr[left+size, left+2*size-1] After every
// merge, we increase left by 2*size
for (int left = 0; left < n; left += 2 * size) {
// find ending point of left sub array
// mid+1 is starting point of right sub array
const int mid = std::min((left + size - 1), (n - 1));
const int right = std::min((left + 2 * size - 1), (n - 1));
// merge sub array arr[left.....mid] & arr[mid+1....right]
merge(arr, left, mid, right);
}
}
}
// utility function to print the Array
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
std::cout << std::endl;
}
/**
* @brief self-test implementation
* @returns void
*/
void tests() {
// Case: array of length 65
constexpr int N = 65;
int arr[N];
std::iota(arr, arr + N, 0);
std::reverse(arr, arr + N);
assert(!std::is_sorted(arr, arr + N));
timSort(arr, N);
assert(std::is_sorted(arr, arr + N));
}
// Driver program to test above function
int main() {
tests(); // run self test implementations
int arr[] = {5, 21, 7, 23, 19};
const int n = sizeof(arr) / sizeof(arr[0]);
printf("Given Array is\n");
printArray(arr, n);
timSort(arr, n);
printf("After Sorting Array is\n");
printArray(arr, n);
return 0;
}
+94
View File
@@ -0,0 +1,94 @@
/**
* @file
* @brief Implementation of the [Wave
* sort](https://www.geeksforgeeks.org/sort-array-wave-form-2/) algorithm
* @details
* Wave Sort is a sorting algorithm that works in \f$O(nlogn)\f$ time assuming
* the sort function used works in \f$O(nlogn)\f$ time.
* @author [Swastika Gupta](https://github.com/Swastyy)
*/
#include <algorithm> /// for std::is_sorted, std::swap
#include <cassert> /// for assert
#include <iostream> /// for IO operations
#include <vector> /// for std::vector
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace wave_sort
* @brief Functions for the [Wave
* sort](https://www.geeksforgeeks.org/sort-array-wave-form-2/) implementation
*/
namespace wave_sort {
/**
* @brief The main function implements that implements the Wave Sort algorithm
* @tparam T type of array
* @param in_arr array to be sorted
* @returns arr the wave sorted array
*/
template <typename T>
std::vector<T> waveSort(const std::vector<T> &in_arr, int64_t n) {
std::vector<T> arr(in_arr);
for (int64_t i = 0; i < n; i++) {
arr[i] = in_arr[i];
}
std::sort(arr.begin(), arr.end());
for (int64_t i = 0; i < n - 1; i += 2) { // swap all the adjacent elements
std::swap(arr[i], arr[i + 1]);
}
return arr;
}
} // namespace wave_sort
} // namespace sorting
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// [10, 90, 49, 2, 1, 5, 23] return [2, 1, 10, 5, 49, 23, 90]
std::vector<int64_t> array1 = {10, 90, 49, 2, 1, 5, 23};
std::cout << "Test 1... ";
std::vector<int64_t> arr1 = sorting::wave_sort::waveSort(array1, 7);
const std::vector<int64_t> o1 = {2, 1, 10, 5, 49, 23, 90};
assert(arr1 == o1);
std::cout << "passed" << std::endl;
// [1, 3, 4, 2, 7, 8] return [2, 1, 4, 3, 8, 7]
std::vector<int64_t> array2 = {1, 3, 4, 2, 7, 8};
std::cout << "Test 2... ";
std::vector<int64_t> arr2 = sorting::wave_sort::waveSort(array2, 6);
const std::vector<int64_t> o2 = {2, 1, 4, 3, 8, 7};
assert(arr2 == o2);
std::cout << "passed" << std::endl;
// [3, 3, 3, 3] return [3, 3, 3, 3]
std::vector<int64_t> array3 = {3, 3, 3, 3};
std::cout << "Test 3... ";
std::vector<int64_t> arr3 = sorting::wave_sort::waveSort(array3, 4);
const std::vector<int64_t> o3 = {3, 3, 3, 3};
assert(arr3 == o3);
std::cout << "passed" << std::endl;
// [9, 4, 6, 8, 14, 3] return [4, 3, 8, 6, 14, 9]
std::vector<int64_t> array4 = {9, 4, 6, 8, 14, 3};
std::cout << "Test 4... ";
std::vector<int64_t> arr4 = sorting::wave_sort::waveSort(array4, 6);
const std::vector<int64_t> o4 = {4, 3, 8, 6, 14, 9};
assert(arr4 == o4);
std::cout << "passed" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}
+133
View File
@@ -0,0 +1,133 @@
/**
* \addtogroup sorting Sorting Algorithms
* @{
* \file
* \brief [Wiggle Sort Algorithm]
* (https://leetcode.com/problems/wiggle-sort-ii/) Implementation
*
* \author [Roshan Kanwar](http://github.com/roshan0708)
*
* \details
* Wiggle Sort sorts the array into a wave like array.
* An array arr[0..n-1] is sorted in wave form,
* if arr[0] >= arr[1] <= arr[2] >= arr[3] <= arr[4] >= …..
*
* \example
* arr = [1,1,5,6,1,4], after wiggle sort arr will become equal to [1,1,6,1,5,4]
* arr = [2,8,9,1,7], after wiggle sort arr will become equal to [8,2,9,1,7]
*/
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <ctime>
#include <iostream> /// for io operations
#include <vector>
/**
* @namespace sorting
* @brief Sorting algorithms
*/
namespace sorting {
/**
* @namespace wiggle_sort
* @brief Functions for [Wiggle
* Sort](https://leetcode.com/problems/wiggle-sort-ii/) algorithm
*/
namespace wiggle_sort {
/**
*
* @brief Function used for sorting the elements in wave form.
* @details
* Checking whether the even indexed elements are greater than
* their adjacent odd elements.
* Traversing all even indexed elements of the input arr.
* If current element is smaller than the previous odd element, swap them.
* If current element is smaller than the next odd element, swap them.
*
* @param arr input array (unsorted elements)
*
*/
template <typename T> // this allows to have vectors of ints, double, float,
// etc
std::vector<T> wiggleSort(const std::vector<T> &arr) {
uint32_t size = arr.size();
std::vector<T> out(
arr); // create a copy of input vector. this way, the original input
// vector does not get modified. a sorted array is is returned.
for (int i = 0; i < size; i += 2) {
if (i > 0 && out[i - 1] > out[i]) {
std::swap(out[i], out[i - 1]); // swapping the two values
}
if (i < size - 1 && out[i] < out[i + 1]) {
std::swap(out[i], out[i + 1]); // swapping the two values
}
}
return out; // returns the sorted vector
}
} // namespace wiggle_sort
} // namespace sorting
/**
*
* @brief Utility function used for printing the elements.
* Prints elements of the array after they're sorted using wiggle sort
* algorithm.
*
* @param arr array containing the sorted elements
*
*/
template <typename T>
static void displayElements(const std::vector<T> &arr) {
uint32_t size = arr.size();
std::cout << "Sorted elements are as follows: ";
std::cout << "[";
for (int i = 0; i < size; i++) {
std::cout << arr[i];
if (i != size - 1) {
std::cout << ", ";
}
}
std::cout << "]" << std::endl;
}
/**
* Test function
* @returns void
*/
static void test() {
std::srand(std::time(nullptr)); // initialize random number generator
std::vector<float> data1(100);
for (auto &d : data1) { // generate random numbers between -5.0 and 4.99
d = float(std::rand() % 1000 - 500) / 100.f;
}
std::vector<float> sorted = sorting::wiggle_sort::wiggleSort<float>(data1);
displayElements(sorted);
for (uint32_t j = 0; j < data1.size(); j += 2) {
assert(data1[j] <= data1[j + 1] &&
data1[j + 1] >= data1[j + 2]); // check the validation condition
}
std::cout << "Test 1 passed\n";
}
/** Driver Code */
int main() {
test();
return 0;
}
/** @} */