- 前言
- 选择排序
- 冒泡排序
- 堆排序
- 快速排序
- 归并排序
前言
列举了常用排序算法,并给出代码
对算法的核心思想进行了简明扼要地说明
选择排序
从数组中选出最小的元素,将其与前面的元素互换
#includevoid select_sort(int *arr, size_t arr_size) { for (int i=0; i for (int j=i+1; j if (arr[j] < arr[i]){ int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } } } int main() { int arr[]= {56,7,8,8,0,1}; select_sort(arr, sizeof(arr)/sizeof(arr[0])); for (auto c: arr) std::printf("%d ", c); }
时间复杂度:O(n^2)
n-1+n-2+······+1+0 ~ n^2
空间复杂度:O(1)
占用常量空间
比较相邻的两元素,确定是否互换,经过一边遍历后最大/小的元素像泡泡一样冒出来,经过多次遍历后完成排序
void bubble_sort(int *arr, size_t arr_size)
{
for (int i=0; i
for (int j=1; j
if (arr[j-1] > arr[j]){
int tmp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = tmp;
}
}
}
}
int main()
{
int arr[]= {56,7,8,8,0,1};
bubble_sort(arr, sizeof(arr)/sizeof(arr[0]));
for (auto c: arr) std::printf("%d ", c);
}
- 时间复杂度:O(n^2)
n-1+n-2+······+1+0 ~ n^2
- 空间复杂度:O(1)
占用常量空间
优化版
void bubble_sort(int *arr, size_t arr_size)
{
for (int i=0; i
bool flag = true;
for (int j=1; j
if (arr[j-1] > arr[j]){
int tmp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = tmp;
flag = false;
}
}
if ( flag) break;
}
}
堆排序
堆是用数组存储的完全二叉树,并且父节点比孩子节点小(小顶堆)/大(大顶堆)
可用于解决topK问题
leftchild = 2*parent + 1 rightchild = 2*parent +2 parent = [ (leftchld - 1) / 2] parent = [ (rightchild- 1) / 2]
#includevoid shift_below(int *arr, int parent, int end ) { int child = 2*parent + 1; while (child < end){ if ( child+1 < end && arr[child] < arr[child+1]){ ++child; } if (arr[parent] < arr[child]){ int tmp = arr[parent]; arr[parent] = arr[child]; arr[child] = tmp; parent = child; child = 2*parent + 1; } else { break; } } } void create_heap(int *arr, int arr_size) { int parent = (arr_size - 1 - 1) / 2; for (int i=parent; i>=0; --i){ shift_below(arr, i, arr_size); } } void heap_sort(int *arr, int arr_size) { create_heap(arr, arr_size); for (int i=arr_size-1; i>0; --i){ int tmp = arr[0]; arr[0] = arr[i]; arr[i] = tmp; shift_below(arr, 0, i); } } int main() { int arr[]= {56,7,8,8,0,1}; heap_sort(arr, sizeof(arr)/sizeof(arr[0])); for (auto c: arr) std::printf("%d ", c); }
- 时间复杂度: O(n * logN)
2*(logn + logn-1 + logn-2 ······ log 1) - 空间复杂度: O(1)
分治思想:将大问题简化为小问题,解决每个小问题,从而大问题得到解决
减治思想:将大问题简化为小问题,解决一个小问题,从而大问题得到解决
// 选择第一个作为基准,它左边的都比他小(<=),右边的都比他大(>=)
// 返回这个基准的索引
// 左右两边都能取到
int partition(int *arr, int start, int end)
{
int base = arr[start];
while (start < end)
{
while (start < end && arr[end] >= base){
--end;
}
arr[start] = arr[end];
while (start < end && arr[start] <= base){
++start;
}
arr[end] = arr[start];
}
arr[start] = base;
return start;
}
void quick_sort(int *arr, int start, int end)
{
if (start >= end) return ;
int i = partition(arr, start, end);
quick_sort(arr, start, i-1);
quick_sort(arr, i+1, end);
}
int main()
{
int arr[]= {7,2,6,4,5,1,7,8,9};
// 左右两边都能取到
quick_sort(arr, 0, sizeof(arr)/sizeof(arr[0])-1 );
for (auto c : arr)
std::printf("%d ", c);
}
归并排序
将一个无序数组递归的的分成两个数组,将仅有两个元素的数组排序。将两个有序的数组合并成一个。
核心代码是将两个有序的数组合并成一个有序的数组
#include// 左边取得到,右边取不到 void merge_sort(int *arr, int start, int mid, int end) { int p1 = start; int p2 = mid; int tmp[end-start] = {0}; int point = 0; while (1){ if ( p1 >= mid){ while (point < end-start && p2 tmp[point++] = arr[p2++]; } break; } if ( p2 >= end){ while (point < end-start && p1 tmp[point++] = arr[p1++]; } break; } if (arr[p1] < arr[p2]){ tmp[point++] = arr[p1++]; } else { tmp[point++] = arr[p2++]; } } for (int c:tmp){ arr[start++] = c; } } void m_sort(int *arr, int start, int end) { if (start >= end) return ; if (end - start == 1){ if (arr[start] > arr[end]){ int tmp = arr[start]; arr[start] = arr[end]; arr[end] = tmp; } return ; } int mid = (start+end) / 2; m_sort(arr, start, mid); m_sort(arr, mid, end); merge_sort(arr, start, mid, end); } int main() { int arr[] = {5,7,6,9,1,5,0,9,8,7,3,7}; m_sort(arr, 0, sizeof(arr)/sizeof(arr[0]) ); for (int c: arr){ std::printf("%d ", c); } }
- 时间复杂度: O(N * logN)
- 空间复杂度:O(N)
- 稳定性: 稳定



