-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
/
binary_insertion_sort.cpp
146 lines (136 loc) · 5.29 KB
/
binary_insertion_sort.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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;
}