插入排序
思路
遍历数组将当前位置的数据依次与前边的数据进行比较符合条件则进行交换。
代码
namespace AC {
template <typename T>
void insertionSort(T _target_array[], int _array_count) {
for (int index = 1; index < _array_count; ++index) {
T temp_data = _target_array[index];
int move_index = index;
for (; move_index > 0 && _target_array[move_index - 1] > temp_data; --move_index) {
_target_array[move_index] = _target_array[move_index - 1];
}
_target_array[move_index] = temp_data;
}
}
}
选择排序
思路
数据分为两个部分已排序部分
和未排序部分
在未排序部分的数据中找到最小或最大
的数据,与未排序部分的第一个位置的数据进行交换。
代码
namespace AC {
template <typename T>
void selectionSort(T _target_array[], int _array_count) {
for (int index = 0; index < _array_count - 1; ++index) {
int min_index = index;
for (int comp_index = index + 1; comp_index < _array_count; ++comp_index) {
if(_target_array[min_index] > _target_array[comp_index]) {
min_index = comp_index;
}
}
std::swap(_target_array[index], _target_array[min_index]);
}
}
}
归并排序-自顶向下
思路
将未排序的数组划分为多个小的数组段,将每个小的数组段进行排序,然后将每个排序好的数组段进行合并汇总,最终汇总成一个有序的数组。
代码
namespace AC {
template <typename T>
void mergeSort(T _target_array[], int _array_count) {
__mergeSort(_target_array, 0, _array_count - 1);
}
template <typename T>
void __mergeSort(T _target_array[], int _left, int _right) {
if (_left >= _right) {
return;
}
int mid = (_left + _right) / 2;
__mergeSort(_target_array, _left, mid);
__mergeSort(_target_array, mid + 1, _right);
// 如果左半部分的最后一个数值大于右半部分第一个数值则再进行合并,否则说明两个部分的数据已经有序不用再次合并
if (_target_array[mid] > _target_array[mid + 1]) {
__merge(_target_array, _left, mid, _right);
}
}
template <typename T>
void __merge(T _target_array[], int _left, int _mid, int _right) {
T * aux = new int[_right - _left + 1];
for (int index = _left; index <= _right; ++index) {
aux[index - _left] = _target_array[index];
}
int i = _left, j = _mid + 1;
for (int k = _left; k <= _right; ++k) {
if (i > _mid) {
_target_array[k] = aux[j - _left];
j++;
} else if (j > _right) {
_target_array[k] = aux[i - _left];
i++;
} else if (aux[i - _left] < aux[j - _left]) {
_target_array[k] = aux[i - _left];
i++;
} else {
_target_array[k] = aux[j - _left];
j++;
}
}
delete [] aux;
}
}
归并排序-自底向上
思路
先将数组从左头到尾依次划分为多个小段,一般从两个元素一段开始进行归并,当归并完成一轮(到末尾后)
后,在成倍扩展一下分段,再次从头到尾进行归并,直至扩展结束。
代码
namespace AC {
template <typename T>
void mergeSortBU(T _target_array[], int _array_count) {
for (int index = 1; index <= _array_count; index += index) {
for (int i = 0; i + index < _array_count; i += index + index) {
__merge(_target_array, i, i + index - 1, std::min(i + index + index - 1, _array_count - 1));
}
}
}
}
快速排序
思路
首先找到一个数作为基础数值,以基础数值作为中点
将数据分为前后两个部分,前半部分全部小于基础数值
而后半部分全部大于基础数值
,然后分别在前后两个部分中找到新的基础数值重复进行以上步骤。
代码
namespace AC {
template <typename T>
void quickSort(T _target_array[], int _array_count) {
srand(time(nullptr)); // 设置随机数优化当数值大量有序的时候分段偏不均
__quickSort(_target_array, 0, _array_count - 1);
}
template <typename T>
int __partition(T _target_array[], int _left, int _right) {
// 将最左边的数和后边随机位置的一个数据交换,可以优化当数组数据基本有序时快速排序退化为O(n^2)级别的算法
std::swap(_target_array[_left], _target_array[rand() % (_right - _left + 1) + _left]);
T aux = _target_array[_left];
int j = _left;
for (int i = _left + 1; i <= _right; ++i) {
if (_target_array[i] < aux) {
std::swap(_target_array[++j], _target_array[i]);
}
}
std::swap(_target_array[_left], _target_array[j]);
return j;
}
template <typename T>
void __quickSort(T _target_array[], int _left, int _right) {
if (_left >= _right) {
return;
}
// 快速排序定位基础数值是算法核心
int partition_index = __partition(_target_array, _left, _right);
__quickSort(_target_array, _left, partition_index - 1);
__quickSort(_target_array, partition_index + 1, _right);
}
}
快速排序- 三路排序
思路
按照基础数值V
将数组分为三个部分,小于V
、大于V
和等于V
,定义lt
、gt
、index
三个变量,lt
是小于V
部分的最后一个数值所在位置,gt
是大于V
部分的第一个数值所在位置,等于V
部分的区域范围是[lt + 1...index - 1]
,index
是未排序部分的第一个数值所在位置。
当index
的数值小于V
时与lt + 1
进行交换;当index
的数值大于V
时与gt - 1
进行交换;当index
的数值等于V
时继续下一次比较。
代码
namespace AC {
template <typename T>
void quickSort(T _target_array[], int _array_count) {
srand(time(nullptr)); // 设置随机数优化当数值大量有序的时候分段偏不均
__quickSort3Ways(_target_array, 0, _array_count - 1);
}
template <typename T>
void __quickSort3Ways(T _target_array[], int _left, int _right) {
if (_right <= _left) {
return;
}
std::swap(_target_array[_left], _target_array[rand() % (_right - _left + 1) + _left]);
T aux = _target_array[_left];
int lt = _left, gt = _right + 1, index = _left + 1;
while (index < gt) {
if (_target_array[index] < aux) {
std::swap(_target_array[index++], _target_array[++lt]);
} else if (_target_array[index] > aux) {
std::swap(_target_array[index], _target_array[--gt]);
} else {
++index;
}
}
std::swap(_target_array[_left], _target_array[lt]);
__quickSort3Ways(_target_array, _left, lt - 1);
__quickSort3Ways(_target_array, gt, _right);
}
}
测试
完全无序
- 代码
#include <iostream>
#include "src/sort_test_helper.cpp"
#include "src/sort_algoritm.cpp"
int main() {
int array_count = 50000;
// 生成随机数组
int * arrays = SortTestHelper::generateRandomArray(array_count, 1, array_count);
// 5种排序算法
return 0;
}
- 结果
insertionSort: 1.234 s.
selectionSort: 2.357 s.
mergeSort: 0.016 s.
mergeSortBU: 0.019 s.
quickSort: 0.011 s.
quickSort3Ways: 0.013 s.
基本有序
- 代码
#include <iostream>
#include "src/sort_test_helper.cpp"
#include "src/sort_algoritm.cpp"
int main() {
int array_count = 50000;
// 生辰一个有序的数组,随机将其中的10个位置进行调换
int * arrays = SortTestHelper::generateNearlyOrderedArray(array_count, 10);
// 5种排序算法
return 0;
}
- 结果
insertionSort: 0.001 s.
selectionSort: 2.369 s.
mergeSort: 0.001 s.
mergeSortBU: 0.016 s.
quickSort: 0.009 s.
quickSort3Ways: 0.014 s.
无序大量重复数组
- 代码
#include <iostream>
#include "src/sort_test_helper.cpp"
#include "src/sort_algoritm.cpp"
int main() {
int array_count = 50000;
// 生成一个无序的数组,其中的值在1-10之间
int * arrays = SortTestHelper::generateRandomArray(array_count, 1, 10);
// 5种排序算法
return 0;
}
- 结果
insertionSort: 1.1 s.
selectionSort: 2.35 s.
mergeSort: 0.013 s.
mergeSortBU: 0.017 s.
quickSort: 0.255 s.
quickSort3Ways: 0.001 s.