快速排序前言
前言:快速排序由C. A. R. Hoare在1960年提出,是冒泡排序的一种改进。快速排序就跟它的名字一样,效率很快。跟冒泡排序,选择排序相比,它们使用相同的空间大小,但是,快速排序却可以达到O(nlogn)的时间复杂度,比O(n^2)要快上很多。快速排序是一个非常高效的排序方法,很多编译器里的排序方法都是选择的快速排序(比如vs编译器)。
.
.
.
.
快速排序的特点
时间复杂度:O(N*logN)
空间复杂度:O(logN)
稳定性:不稳定
稳定性:相同的数据在排序的过程中这些数据的相对位置是否会变化,不变化则稳定
.
.
.
.
单趟排序
写快速排序你需要知道的点:每一趟排序能使某一个数据排到他最后该待的位置,因为排完一趟序能使一个值(例-4)比-4值小的值都在-4左边,比-4大的值都在-4右边
所以我们先写单趟,之后递归实现整体的快排。写好单趟排序代码量就完成了80%
单趟排序有三种写法
方法一:hoare法
方法二:挖坑法
方法三:前后指针法
三种方法的效率差异很小
.
.
hoare方法:
第一步:选left做key(key是单趟排序后能排到最后该待的位置的数据)
第二步:right开始找,right遇到比key大或相等的就往左边走,遇到比key小的就停下,进行第三步。(若right超过了left,直接进行第五步)
第三步:left开始找,left遇到比key小或相等的就往右边走,遇到比key大的就停下,进行第四步。(若left超过了right,直接进行第五步)
第四步:交换left和right,从第二步继续向下走。
第五步:交换left和key。
.
.
GIF动图:
参考代码:
// 快速排序hoare版本
int PartSort1(int* a, int left, int right)
{
int keyi = left;
while (left < right)
{
while (left < right)
{
if (left < right && a[right] >= a[keyi])
{
right--;
}
else
{
break;
}
}
while (left < right)
{
if (left < right && a[left] <= a[keyi])
{
left++;
}
else
{
break;
}
}
swap(a[left], a[right]);
}
swap(a[left], a[keyi]);
return left;
}
递归实现快速排序
每次递归结束都有一个值排好顺序了
参考代码:
void QuickSort(int* a, int left, int right)
{
if (left >= right)
return;
int div = PartSort1(a, left, right);
QuickSort(a, left, div - 1);
QuickSort(a, div + 1, right);
}