Skip to content

Commit 1371b53

Browse files
authored
[feat/docs]: improve the quick_sort.cpp algorithm (TheAlgorithms#2396)
* [feat/docs]: improve the `quick_sort.cpp`... ...algorithm implementation. * clang-format and clang-tidy fixes for 40c858b * chore(fix): add original author * updating DIRECTORY.md
1 parent e5ca477 commit 1371b53

File tree

2 files changed

+188
-50
lines changed

2 files changed

+188
-50
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* [Count Bits Flip](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/count_bits_flip.cpp)
1818
* [Count Of Set Bits](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/count_of_set_bits.cpp)
1919
* [Count Of Trailing Ciphers In Factorial N](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/count_of_trailing_ciphers_in_factorial_n.cpp)
20+
* [Find Non Repeating Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/find_non_repeating_number.cpp)
2021
* [Hamming Distance](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/hamming_distance.cpp)
2122
* [Set Kth Bit](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/bit_manipulation/set_kth_bit.cpp)
2223

sorting/quick_sort.cpp

Lines changed: 187 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/**
22
* @file
3-
* @brief Quick sort algorithm
4-
*
5-
* Implementation Details -
6-
* Quick Sort is a divide and conquer algorithm. It picks and element as
7-
* pivot and partition the given array around the picked pivot. There
8-
* are many different versions of quickSort that pick pivot in different
9-
* ways.
3+
* @brief [Quick sort implementation](https://en.wikipedia.org/wiki/Quicksort)
4+
* in C++
5+
* @details
6+
* Quick Sort is a [divide and conquer
7+
* algorithm](https://en.wikipedia.org/wiki/Category:Divide-and-conquer_algorithms).
8+
* It picks an element as pivot and partition the given array around the
9+
* picked pivot. There are many different versions of quickSort that pick pivot
10+
* in different ways.
1011
*
1112
* 1. Always pick the first element as pivot
1213
* 2. Always pick the last element as pivot (implemented below)
@@ -19,83 +20,219 @@
1920
* than x) before x, and put all greater elements (greater than x) after
2021
* x. All this should be done in linear time
2122
*
23+
* @author [David Leal](https://github.com/Panquesito7)
24+
* @author [popoapp](https://github.com/popoapp)
2225
*/
2326

24-
#include <cstdlib>
25-
#include <iostream>
27+
#include <algorithm> /// for std::is_sorted
28+
#include <cassert> /// for std::assert
29+
#include <ctime> /// for std::time
30+
#include <iostream> /// for IO operations
31+
#include <vector> /// for std::vector
2632

33+
/**
34+
* @brief Sorting algorithms
35+
* @namespace sorting
36+
*/
2737
namespace sorting {
2838
/**
29-
* This function takes last element as pivot, places
30-
* the pivot element at its correct position in sorted
31-
* array, and places all smaller (smaller than pivot)
32-
* to left of pivot and all greater elements to right
33-
* of pivot
34-
*
39+
* @namespace quick_sort
40+
* @brief Functions for the [Quick sort
41+
* implementation](https://en.wikipedia.org/wiki/Quicksort) in C++
3542
*/
36-
37-
int partition(int arr[], int low, int high) {
38-
int pivot = arr[high]; // taking the last element as pivot
39-
int i = (low - 1); // Index of smaller element
43+
namespace quick_sort {
44+
/**
45+
* @brief Sorts the array taking the last element as pivot
46+
* @details
47+
* This function takes last element as pivot, places
48+
* the pivot element at its correct position in sorted
49+
* array, and places all smaller (smaller than pivot)
50+
* to left of pivot and all greater elements to right of pivot
51+
* @tparam T array type
52+
* @param arr the array with contents given by the user
53+
* @param low first point of the array (starting index)
54+
* @param high last point of the array (ending index)
55+
* @returns index of the smaller element
56+
*/
57+
template <typename T>
58+
int partition(std::vector<T> *arr, const int &low, const int &high) {
59+
T pivot = (*arr)[high]; // taking the last element as pivot
60+
int i = (low - 1); // Index of smaller element
4061

4162
for (int j = low; j < high; j++) {
4263
// If current element is smaller than or
4364
// equal to pivot
44-
if (arr[j] <= pivot) {
65+
if ((*arr)[j] <= pivot) {
4566
i++; // increment index of smaller element
46-
int temp = arr[i];
47-
arr[i] = arr[j];
48-
arr[j] = temp;
67+
std::swap((*arr)[i], (*arr)[j]);
4968
}
5069
}
51-
int temp = arr[i + 1];
52-
arr[i + 1] = arr[high];
53-
arr[high] = temp;
70+
71+
std::swap((*arr)[i + 1], (*arr)[high]);
5472
return (i + 1);
5573
}
5674

5775
/**
58-
* The main function that implements QuickSort
59-
* arr[] --> Array to be sorted,
60-
* low --> Starting index,
61-
* high --> Ending index
76+
* @brief the main function that implements Quick Sort.
77+
*
78+
* Void function used in T (array type) function, which then
79+
* can be used as self-tests or other functionalities.
80+
* @tparam T array type
81+
* @param arr array to be sorted
82+
* @param low starting index
83+
* @param high ending index
6284
*/
63-
void quickSort(int arr[], int low, int high) {
85+
template <typename T>
86+
void quick_sort(std::vector<T> *arr, const int &low, const int &high) {
6487
if (low < high) {
6588
int p = partition(arr, low, high);
66-
quickSort(arr, low, p - 1);
67-
quickSort(arr, p + 1, high);
89+
90+
quick_sort(arr, low, p - 1);
91+
quick_sort(arr, p + 1, high);
6892
}
6993
}
7094

71-
} // namespace sorting
95+
/**
96+
* @brief the main function that implements Quick Sort.
97+
*
98+
* T (array type) function which calls the void function. Can
99+
* be used for self-tests and other functionalities.
100+
* @tparam T array type
101+
* @param arr array to be sorted
102+
* @param low starting index
103+
* @param high ending index
104+
*/
105+
template <typename T>
106+
std::vector<T> quick_sort(std::vector<T> arr, const int &low, const int &high) {
107+
if (low < high) {
108+
int p = partition(&arr, low, high);
72109

73-
using sorting::quickSort;
110+
quick_sort(&arr, low, p - 1);
111+
quick_sort(&arr, p + 1, high);
112+
}
113+
return arr;
114+
}
74115

75-
// prints the array after sorting
76-
void show(int arr[], int size) {
116+
/**
117+
* @brief Utility function to print the array contents
118+
* @param arr the array to be printed
119+
* @param size size of the given array
120+
* @returns void
121+
*/
122+
template <typename T>
123+
void show(const std::vector<T> &arr, const int &size) {
77124
for (int i = 0; i < size; i++) std::cout << arr[i] << " ";
78125
std::cout << "\n";
79126
}
80127

81-
/** Driver program to test above functions */
128+
} // namespace quick_sort
129+
} // namespace sorting
130+
131+
/**
132+
* @brief Self-test implementations
133+
* @returns void
134+
*/
135+
static void tests() {
136+
// 1st test (normal numbers)
137+
std::vector<uint64_t> arr = {5, 3, 8, 12, 14, 16, 28, 96, 2, 5977};
138+
std::vector<uint64_t> arr_sorted = sorting::quick_sort::quick_sort(
139+
arr, 0, int(std::end(arr) - std::begin(arr)) - 1);
140+
141+
assert(std::is_sorted(std::begin(arr_sorted), std::end(arr_sorted)));
142+
std::cout << "\n1st test: passed!\n";
143+
144+
// 2nd test (normal and negative numbers)
145+
std::vector<int64_t> arr2 = {9, 15, 28, 96, 500, -4, -58,
146+
-977, -238, -800, -21, -53, -55};
147+
std::vector<int64_t> arr_sorted2 = sorting::quick_sort::quick_sort(
148+
arr2, 0, std::end(arr2) - std::begin(arr2));
149+
150+
assert(std::is_sorted(std::begin(arr_sorted2), std::end(arr_sorted2)));
151+
std::cout << "2nd test: passed!\n";
152+
153+
// 3rd test (decimal and normal numbers)
154+
std::vector<double> arr3 = {29, 36, 1100, 0, 77, 1,
155+
6.7, 8.97, 1.74, 950.10, -329.65};
156+
std::vector<double> arr_sorted3 = sorting::quick_sort::quick_sort(
157+
arr3, 0, int(std::end(arr3) - std::begin(arr3)) - 1);
158+
159+
assert(std::is_sorted(std::begin(arr_sorted3), std::end(arr_sorted3)));
160+
std::cout << "3rd test: passed!\n";
161+
162+
// 4th test (random decimal and negative numbers)
163+
size_t size = std::rand() % 750 + 100;
164+
165+
std::vector<float> arr4(size);
166+
for (uint64_t i = 0; i < size; i++) {
167+
arr4[i] = static_cast<float>(std::rand()) /
168+
static_cast<float>(RAND_MAX / 999.99 - 0.99) -
169+
250;
170+
}
171+
172+
std::vector<float> arr4_sorted = sorting::quick_sort::quick_sort(
173+
arr4, 0, int(std::end(arr4) - std::begin(arr4)) - 1);
174+
assert(std::is_sorted(std::begin(arr4_sorted), std::end(arr4_sorted)));
175+
176+
std::cout << "4th test: passed!\n";
177+
178+
// Printing all sorted arrays
179+
std::cout << "\n\tPrinting all sorted arrays:\t\n";
180+
181+
std::cout << "1st array:\n";
182+
sorting::quick_sort::show(arr_sorted, std::end(arr) - std::begin(arr));
183+
std::cout << std::endl;
184+
std::cout << "2nd array:\n";
185+
sorting::quick_sort::show(arr_sorted2, std::end(arr2) - std::begin(arr2));
186+
std::cout << std::endl;
187+
std::cout << "3rd array:\n";
188+
sorting::quick_sort::show(arr_sorted3,
189+
int(std::end(arr3) - std::begin(arr3)) - 1);
190+
std::cout << std::endl;
191+
std::cout << "Start: 4th array:\n\n";
192+
sorting::quick_sort::show(
193+
arr4_sorted, int(std::end(arr4_sorted) - std::begin(arr4_sorted)) - 1);
194+
std::cout << "\nEnd: 4th array.\n";
195+
}
196+
197+
/**
198+
* @brief Main function
199+
* @returns 0 on exit
200+
*/
82201
int main() {
83-
int size;
84-
std::cout << "\nEnter the number of elements : ";
202+
int choice = 0;
85203

86-
std::cin >> size;
204+
std::cout << "\tAvailable modes\t\n\n";
205+
std::cout << "1. Self-tests mode\n2. Interactive mode";
87206

88-
int *arr = new int[size];
207+
std::cout << "\nChoose a mode: ";
208+
std::cin >> choice;
209+
std::cout << "\n";
89210

90-
std::cout << "\nEnter the unsorted elements : ";
211+
while ((choice != 1) && (choice != 2)) {
212+
std::cout << "Invalid option. Choose between the valid modes: ";
213+
std::cin >> choice;
214+
}
215+
216+
if (choice == 1) {
217+
std::srand(std::time(nullptr));
218+
tests(); // run self-test implementations
219+
} else if (choice == 2) {
220+
int size = 0;
221+
std::cout << "\nEnter the number of elements: ";
222+
223+
std::cin >> size;
224+
std::vector<float> arr(size);
91225

92-
for (int i = 0; i < size; ++i) {
93-
std::cout << "\n";
94-
std::cin >> arr[i];
226+
std::cout
227+
<< "\nEnter the unsorted elements (can be negative/decimal): ";
228+
229+
for (int i = 0; i < size; ++i) {
230+
std::cout << "\n";
231+
std::cin >> arr[i];
232+
}
233+
sorting::quick_sort::quick_sort(&arr, 0, size - 1);
234+
std::cout << "\nSorted array: \n";
235+
sorting::quick_sort::show(arr, size);
95236
}
96-
quickSort(arr, 0, size);
97-
std::cout << "Sorted array\n";
98-
show(arr, size);
99-
delete[] arr;
100237
return 0;
101238
}

0 commit comments

Comments
 (0)