原理
核心思想:分而治之
从选择排序演化而来
选择排序是每一轮找出最大值,与当前范围最后一位交换,将最大值放在末尾
快速排序是每次选择一个分割器(一般选当前范围的最后一个),比它大的放它右边,比它小的放它左边,再递归调用直到范围<=1时
递归调用的深度:log(n)
性能
时间复杂度:平均和最好O (logn * n),最坏O (n^2)
空间复杂度:O(logn),用来存分割器(枢纽)
问题
数组过大时,递归深度可能导致栈溢出(解决:使用非递归的快排)
重复元素过多时,会退化成选择排序的时间复杂度(解决:可以先去重,再快排)
代码
输入:数组地址,首元素下标,尾元素下标
输出:升序排列的数组
quick_sort.c
int partition(int *arr, int left, int right)
{
//选数组最后一个元素作为枢纽(分割器)
//i 用来遍历数组
//j 是一个界限,左边元素都比分割器小
int pivot = arr[right];
int i = left;
int j = left;
for (; i < right; ++i) {
if (arr[i] < pivot) {
//比枢纽小的,放j左边
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
++j;
}
}
//将枢纽放中间
arr[right] = arr[j];
arr[j] = pivot;
//返回枢纽的下标
return j;
}
void quick_sort(int *arr, int left, int right)
{
if (right > left) { //数组范围大于1,就进入递归
int pivot = partition(arr, left, right); //通过划分得到枢纽(分割器)
quick_sort(arr, left, pivot - 1); //递归枢纽左半边
quick_sort(arr, pivot + 1, right); //递归枢纽右半边
}
}