Skip to content

Commit 8d68e61

Browse files
kvedalaimmortal-jgithub-actions
authored
[feature] new implementation of Quick sort (TheAlgorithms#958)
* added quick_sort_3 * Corrected some formatting error * made more C-plus-plusy * add test cases * updating DIRECTORY.md * clang-tidy fixes for 30c9a19 * better selef-tests + use std::vector * use size_t * change size_t to int32_t Co-authored-by: mohit <[email protected]> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
1 parent 01ba336 commit 8d68e61

File tree

2 files changed

+189
-0
lines changed

2 files changed

+189
-0
lines changed

DIRECTORY.md

+1
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@
235235
* [Numeric String Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/numeric_string_sort.cpp)
236236
* [Odd Even Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/odd_even_sort.cpp)
237237
* [Quick Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/quick_sort.cpp)
238+
* [Quick Sort 3](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/quick_sort_3.cpp)
238239
* [Radix Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/radix_sort.cpp)
239240
* [Selection Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/selection_sort.cpp)
240241
* [Shell Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/shell_sort.cpp)

sorting/quick_sort_3.cpp

+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/**
2+
* @file
3+
* @brief Implementation Details
4+
* @details Quick sort 3 works on Dutch National Flag Algorithm
5+
* The major difference between simple quicksort and quick sort 3 comes in the
6+
* function partition3 In quick_sort_partition3 we divide the vector/array into
7+
* 3 parts. quick sort 3 works faster in some cases as compared to simple
8+
* quicksort.
9+
* @author immortal-j
10+
* @author [Krishna Vedala](https://github/kvedala)
11+
*/
12+
#include <algorithm>
13+
#include <cassert>
14+
#include <ctime>
15+
#include <iostream>
16+
#include <vector>
17+
18+
namespace {
19+
/**
20+
* Operator to print the array.
21+
* @param out std::ostream object to write to
22+
* @param arr array to write
23+
*/
24+
template <typename T>
25+
std::ostream &operator<<(std::ostream &out, const std::vector<T> &arr) {
26+
for (size_t i = 0; i < arr.size(); ++i) {
27+
out << arr[i];
28+
if (i < arr.size() - 1) {
29+
out << ", ";
30+
}
31+
}
32+
return out;
33+
}
34+
35+
} // namespace
36+
37+
/**
38+
* @namespace sorting
39+
* @brief Sorting Algorithms
40+
*/
41+
namespace sorting {
42+
namespace { // using un-named namespace here to prevent partition function
43+
// being visible to end-users
44+
/** This function partitions `arr[]` in three parts
45+
* 1. \f$arr[l\ldots i]\f$ contains all elements smaller than pivot
46+
* 2. \f$arr[(i+1)\ldots (j-1)]\f$ contains all occurrences of pivot
47+
* 3. \f$arr[j\ldots r]\f$ contains all elements greater than pivot
48+
* @tparam T type of data in the vector array
49+
* @param [in,out] arr vector array being partitioned
50+
* @param [in] low lower limit of window to partition
51+
* @param [in] high upper limit of window to partition
52+
* @param [out] i updated lower limit of partition
53+
* @param [out] j updated upper limit of partition
54+
*/
55+
template <typename T>
56+
void partition3(std::vector<T> *arr, int32_t low, int32_t high, int32_t *i,
57+
int32_t *j) {
58+
// To handle 2 elements
59+
if (high - low <= 1) {
60+
if ((*arr)[high] < (*arr)[low]) {
61+
std::swap((*arr)[high], (*arr)[low]);
62+
}
63+
*i = low;
64+
*j = high;
65+
return;
66+
}
67+
68+
int32_t mid = low;
69+
T pivot = (*arr)[high];
70+
while (mid <= high) {
71+
if ((*arr)[mid] < pivot) {
72+
std::swap((*arr)[low++], (*arr)[mid++]);
73+
} else if ((*arr)[mid] == pivot) {
74+
mid++;
75+
} else if ((*arr)[mid] > pivot) {
76+
std::swap((*arr)[mid], (*arr)[high--]);
77+
}
78+
}
79+
80+
// update i and j
81+
*i = low - 1;
82+
*j = mid; // or high-1
83+
}
84+
} // namespace
85+
86+
/** 3-way partition based quick sort. This function accepts array pointer and
87+
* modified the input array.
88+
* @tparam T type of data in the vector array
89+
* @param [in,out] arr vector array to sort
90+
* @param [in] low lower limit of window to partition
91+
* @param [in] high upper limit of window to partition
92+
*/
93+
template <typename T>
94+
void quicksort(std::vector<T> *arr, int32_t low, int32_t high) {
95+
if (low >= high) { // 1 or 0 elements
96+
return;
97+
}
98+
99+
int32_t i = 0, j = 0;
100+
101+
// i and j are passed as reference
102+
partition3(arr, low, high, &i, &j);
103+
104+
// Recur two halves
105+
quicksort(arr, low, i);
106+
quicksort(arr, j, high);
107+
}
108+
109+
/** 3-way partition based quick sort. This function accepts array by value and
110+
* creates a copy of it. The array copy gets sorted and returned by the
111+
* function.
112+
* @tparam T type of data in the vector array
113+
* @param [in] arr vector array to sort
114+
* @param [in] low lower limit of window to partition
115+
* @param [in] high upper limit of window to partition
116+
* @returns sorted array vector
117+
*/
118+
template <typename T>
119+
std::vector<T> quicksort(std::vector<T> arr, int32_t low, int32_t high) {
120+
if (low >= high) { // 1 or 0 elements
121+
return arr;
122+
}
123+
124+
int32_t i = 0, j = 0;
125+
126+
// i and j are passed as reference
127+
partition3(&arr, low, high, &i, &j);
128+
129+
// Recur two halves
130+
quicksort(&arr, low, i);
131+
quicksort(&arr, j, high);
132+
133+
return arr;
134+
}
135+
} // namespace sorting
136+
137+
/** Test function for integer type arrays */
138+
static void test_int() {
139+
std::cout << "\nTesting integer type arrays\n";
140+
141+
for (int num_tests = 1; num_tests < 21; num_tests++) {
142+
size_t size = std::rand() % 500;
143+
std::vector<int> arr(size);
144+
for (auto &a : arr) {
145+
a = std::rand() % 500 - 250; // random numbers between -250, 249
146+
}
147+
148+
std::cout << "Test " << num_tests << "\t Array size:" << size << "\t ";
149+
std::vector<int> sorted = sorting::quicksort(arr, 0, size - 1);
150+
if (size < 20) {
151+
std::cout << "\t Sorted Array is:\n\t";
152+
std::cout << sorted << "\n";
153+
}
154+
assert(std::is_sorted(std::begin(sorted), std::end(sorted)));
155+
std::cout << "\t Passed\n";
156+
}
157+
}
158+
159+
/** Test function for double type arrays */
160+
static void test_double() {
161+
std::cout << "\nTesting Double type arrays\n";
162+
for (int num_tests = 1; num_tests < 21; num_tests++) {
163+
size_t size = std::rand() % 500;
164+
std::vector<double> arr(size);
165+
for (auto &a : arr) {
166+
a = double(std::rand() % 500) -
167+
250.f; // random numbers between -250, 249
168+
a /= 100.f; // convert to -2.5 to 2.49
169+
}
170+
171+
std::cout << "Test " << num_tests << "\t Array size:" << size << "\t ";
172+
std::vector<double> sorted = sorting::quicksort(arr, 0, size - 1);
173+
if (size < 20) {
174+
std::cout << "\t Sorted Array is:\n\t";
175+
std::cout << sorted << "\n";
176+
}
177+
assert(std::is_sorted(std::begin(sorted), std::end(sorted)));
178+
std::cout << "\t Passed\n";
179+
}
180+
}
181+
182+
/** Driver program for above functions */
183+
int main() {
184+
std::srand(std::time(nullptr));
185+
test_int();
186+
test_double();
187+
return 0;
188+
}

0 commit comments

Comments
 (0)