本系列算法实现都是在学习数据结构(C++语言版),清华大学邓俊辉教授编,听邓老师edX网课过程中自己实现的例子。
问题:对一组无顺序向量进行排序,使得按<排列
解决:用常见的排序算法解决,有如下几种
- 冒泡排序
- 选择排序
- 归并排序
- 快速排序
- 堆排序
参考链接:
* 排序算法可视化——visualgo
* 排序算法wiki
* Jark’s Blog——经典排序算法总结与实现
0 各种排序算法的比较
表格来自wiki
1 冒泡排序
这里给出的冒泡排序是优化后的,主要思想是从左到右依次扫描,如果相邻是逆序对,则交换,这样最多经过N-1次(N是元素个数)就能排序完成。
其是平均时间复杂度为O(n^2)
//! name : 起泡排序
//! brief: sort elems in array[low, high) by <
//! time : O(n^2)
//! stability: STABLE
template <typename T>
void bubble_sort(T& array, int low, int high)
{
int last = 0;//mark 最右侧逆序对位置
while (low < high)
{
last = low;
while (++low < high)
{
if (array[low - 1] > array[low])// > not the >= , make this algorithm stable
{
last = low;
std::swap(array[low - 1], array[low]);
}
}
low = 0;
high = last;//最右侧逆序对位置
}
}
2 选择排序
选择排序的思路是从左到右扫描,每次扫描找到最小元素,然后追加到有序区后面。算法时间复杂度为O(n^2)
//! name : 选择排序
//! brief: sort elems in array[low, high) by <
//! time : O(n^2)
//! stability: UNSTABLE
template <typename T>
void select_sort(T& array, int low, int high)
{
int min;
for (int i = low; i < high; ++i)//traversal elem
{
min = i;
for (int j = i + 1; j < high; ++j)
{
if (array[min] > array[j])
{
min = j;
}
}
std::swap(array[min], array[i]);
}
}
3 归并排序
归并排序的优点是时间复杂度低,为O(NlogN), 并且是稳定排序
算法实现分为两个部分,
- 对无序向量进行递归分解
- 对有序向量进行逐层归并
3.1 递归分解
首先确定递归分解的递归基
//recursion base
if (high - low < 2)
return;
算法实现如下
template <typename T>
void merge_sort(T* array, int low, int high)
{
//recursion base
if (high - low < 2)
return;
int mid = (low + high) >> 1;
merge_sort(array, low, mid);//[low, mid)
merge_sort(array, mid, high);//[mid, high)
merge(array, low, mid, high);
}
3.2 逐层合并
- 首先申请内存,复制array的第一部分array[low,mid)到tmp[0, mid-low)中
- 然后逐个比较tmp[0, mid-low)和array[mid, high),较小的放到array[low, high)中
//! name : 归并排序
//! brief: sort elems in array[low, high) by <
//! time : O(NlogN)
//! stability: STABLE
template <typename T>
void merge(T* array, int low, int mid, int high)
{
T* tmp = new T[mid - low];
for (int i = 0; i < mid - low; ++i) //copy first part of array
{
tmp[i] = array[low + i];
}
// i for tmp[i], i = [0, mid-low)
// j for array[j],j = [mid, high)
// k for merge, array[k], k = [low, high)
int i = 0, j = mid, k = low;
while (k < high)//sorted all
{
if (i < mid - low && j < high)
{
tmp[i] > array[j] ? array[k++] = array[j++] : array[k++] = tmp[i++];
}
else if (i < mid - low && j == high)
{
while (i < mid)
{
array[k++] = tmp[i++];
}
}
else if (i == mid - low && j < high)
{
while (j < high)
{
array[k++] = array[j++];
}
}
}
delete [] tmp;
}