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