Skip to content

Commit 654dd0b

Browse files
author
cesar-011
committed
feat: add hybrid quick-insertion-selection sorting algorithm with tests
1 parent 93a700c commit 654dd0b

File tree

1 file changed

+209
-0
lines changed

1 file changed

+209
-0
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/**
2+
* @file
3+
* @brief Hybrid of QuickSort, InsertionSort and SelectionSort
4+
* https://es.wikipedia.org/wiki/Quicksort
5+
* https://en.wikipedia.org/wiki/Selection_sort
6+
* https://en.wikipedia.org/wiki/Insertion_sort
7+
* @details
8+
* this is a hybrid sorting algorithm
9+
* uses quicksort to split the array in two
10+
* sorts the left half with insertion sort
11+
* sorts the right half with selection sort
12+
* created for educational purposes not optimized for speed.
13+
* @author Cesar (https://github.com/cesar-011)
14+
* @see quick_sort.cpp, insertion_sort.cpp, selection_sort_iterative.cpp
15+
*/
16+
17+
#include <algorithm> // for std::is_sorted
18+
#include <cassert> // for assert
19+
#include <iostream> // for IO
20+
#include <vector> // for vector in test
21+
22+
/**
23+
* @brief swap two elements of an array
24+
*/
25+
template <typename T>
26+
void swap(T *arr, int i, int j) {
27+
T aux = arr[i];
28+
arr[i] = arr[j];
29+
arr[j] = aux;
30+
}
31+
32+
/**
33+
* @brief print the array
34+
*/
35+
template <typename T>
36+
void print_array(T *arr, int size) {
37+
for (int i = 0; i < size; i++) {
38+
std::cout << arr[i] << " ";
39+
}
40+
}
41+
42+
/**
43+
* @namespace sorting
44+
* @brief Sorting algorithms
45+
*/
46+
namespace sorting {
47+
48+
/**
49+
* @namespace hybrid_quick_insert_select
50+
* @brief Hybrid of QuickSort, InsertionSort and SelectionSort algorithms
51+
*/
52+
namespace hybrid_quick_insert_select {
53+
54+
/**
55+
* @brief Sorts an array using a hybrid of QuickSort, Insertion Sort, and
56+
* Selection Sort.
57+
*
58+
* This algorithm partitions the array using QuickSort's partitioning scheme.
59+
* It then applies Insertion Sort to the left half and Selection Sort to the
60+
* right half. This hybrid is intended for educational purposes and not
61+
* optimized for performance.
62+
*
63+
* @tparam T Type of the elements in the array. Must support comparison
64+
* operators.
65+
* @param arr Pointer to the array to be sorted.
66+
* @param low Starting index of the subarray to sort.
67+
* @param high Ending index of the subarray to sort (inclusive).
68+
*/
69+
template <typename T>
70+
void hybrid_quick_insertion_selection(T *arr, int low, int high) {
71+
if (low >= high)
72+
return; // Empty range
73+
// A single iteration of Quicksort partitioning to divide the array into two
74+
// halves
75+
int i = low;
76+
int f = high - 1;
77+
T pivot = arr[(i + f) / 2];
78+
while (i <= f) {
79+
while (arr[i] < pivot) i++;
80+
while (arr[f] > pivot) f--;
81+
if (i <= f) {
82+
swap(arr, i, f);
83+
i++;
84+
f--;
85+
}
86+
}
87+
88+
// Insertion at the left
89+
if (low < f) {
90+
for (int k = low + 1; k <= f; k++) {
91+
int key = arr[k];
92+
int j = k - 1;
93+
while (j >= low && arr[j] > key) {
94+
arr[j + 1] = arr[j];
95+
j--;
96+
}
97+
arr[j + 1] = key;
98+
}
99+
}
100+
101+
// Selection at the right
102+
if (i < high) {
103+
for (int k = i; k < high; k++) {
104+
int minimum = arr[k];
105+
int min_ind = k;
106+
int j = k + 1;
107+
while (j < high) {
108+
if (arr[j] < minimum) {
109+
minimum = arr[j];
110+
min_ind = j;
111+
}
112+
j++;
113+
}
114+
swap(arr, k, min_ind);
115+
}
116+
}
117+
}
118+
} // namespace hybrid_quick_insert_select
119+
} // namespace sorting
120+
121+
static void test() {
122+
using sorting::hybrid_quick_insert_select::hybrid_quick_insertion_selection;
123+
124+
// Test 1: empty
125+
{
126+
std::vector<int> arr = {};
127+
hybrid_quick_insertion_selection(arr.data(), 0,
128+
static_cast<int>(arr.size()));
129+
assert(std::is_sorted(arr.begin(), arr.end()));
130+
}
131+
132+
// Test 2: one element
133+
{
134+
std::vector<int> arr = {42};
135+
hybrid_quick_insertion_selection(arr.data(), 0,
136+
static_cast<int>(arr.size()));
137+
assert(std::is_sorted(arr.begin(), arr.end()));
138+
}
139+
140+
// Test 3: positive numbers
141+
{
142+
std::vector<int> arr = {1, 2, 3, 4, 5};
143+
hybrid_quick_insertion_selection(arr.data(), 0,
144+
static_cast<int>(arr.size()));
145+
assert(std::is_sorted(arr.begin(), arr.end()));
146+
}
147+
148+
// Test 4: positive and negative numbers
149+
{
150+
std::vector<int> arr = {-5, 4, -3, 2, 1};
151+
hybrid_quick_insertion_selection(arr.data(), 0,
152+
static_cast<int>(arr.size()));
153+
assert(std::is_sorted(arr.begin(), arr.end()));
154+
}
155+
156+
// Test 5: repeated elements
157+
{
158+
std::vector<int> arr = {3, 1, 2, 3, 2, 1, 4};
159+
hybrid_quick_insertion_selection(arr.data(), 0,
160+
static_cast<int>(arr.size()));
161+
assert(std::is_sorted(arr.begin(), arr.end()));
162+
}
163+
164+
// Test 6: negative numbers
165+
{
166+
std::vector<int> arr = {-10, -7, -8, -9, -1, -5};
167+
hybrid_quick_insertion_selection(arr.data(), 0,
168+
static_cast<int>(arr.size()));
169+
assert(std::is_sorted(arr.begin(), arr.end()));
170+
}
171+
172+
// Test 7: big array
173+
{
174+
std::vector<int> arr(1000);
175+
for (int i = 0; i < 1000; ++i) {
176+
arr[i] = 1000 - i;
177+
}
178+
hybrid_quick_insertion_selection(arr.data(), 0,
179+
static_cast<int>(arr.size()));
180+
assert(std::is_sorted(arr.begin(), arr.end()));
181+
}
182+
183+
std::cout << "All tests passed successfully!\n";
184+
}
185+
186+
/**
187+
* @brief Main program to demonstrate the hybrid sorting algorithm.
188+
*
189+
* Runs the built-in self-tests, then sorts a sample array using the hybrid
190+
* algorithm that combines QuickSort, Insertion Sort, and Selection Sort.
191+
*
192+
* The array is printed before and after sorting to show the result.
193+
*
194+
* @return int Program exit code (0 indicates successful execution).
195+
*/
196+
int main() {
197+
test(); // run self-test implementations
198+
199+
// An example
200+
int N = 8;
201+
int array[N] = {8, 5, 9, 20, 2, 13, 3, 1};
202+
print_array(array, N);
203+
std::cout << '\n';
204+
sorting::hybrid_quick_insert_select::hybrid_quick_insertion_selection(array,
205+
0, N);
206+
print_array(array, N);
207+
std::cout << '\n';
208+
return 0;
209+
}

0 commit comments

Comments
 (0)