快速排序是对冒泡排序的一种改进,由 C.A.R.Hoare(Charles Antony Richard Hoare,东尼·霍尔)在 1962 年提出。
快速排序的核心思维
每次都取数组的第一个元素作为基准元素,凡是大于这个基准元素的都放在他的右边,凡是小于这个基准元素的都放在它的左边,具体步骤如下:
- 设置两个变量i和j(也称为哨兵),令序列第一个元素作为基准元素
- i指向序列的最左边,j指向序列的最右边,j从右往左试探,i从左往右试探,直到j找到小于基准的数就停止,i找到大于基准的数就停止,交换i和j指向的两个数,j继续往左试探,i继续往右试探
- 如果i和j相遇,则i或j上的元素与基准元素交换,则这一轮排序结束
- 对基准元素两边的序列重复以上操作
这里以数组 6 2 7 3 9 8 为例,我们的基准元素取首元素6,首先i和j分别为头和尾元素。根据步骤2中,首先j往左边移动直到遇到第一个比6小的元素
此时的j到3这儿,然后i开始往右边移动直到找到第一个比基准元素大的元素,此时找到了7
然后交换i和j指向的两个数据
然后j接着往左边移动再找到第一个小于基准的数据,但是这儿i和j在3数字这儿相遇,由此根据步骤3,把i或j(因为此时的i和j都指向同一个数字3)与基准元素进行交换,这样就完成了第一轮的交换。
此时会发现基准元素6的左边都是比6小,右边都是比6 大,由此第一轮排序结束,然后分别接着对 3 2 这两个数字重复上面的操作(即将3作为基准元素,然后3 和2分别为头和尾元素),7 8 9 也重复上面的操作,最后就可以完成整个数组的排序
下面是c++代码实现:
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
using std::swap;
void quickSort(vector<int>& vi, int lo, int hi)
{
int pivot = vi[lo];
int i = lo;
int j = hi;
if (lo < hi)
{
while (i != j)
{
while (vi[j] >= pivot && j > i)
{
j--;
}
while (vi[i] <= pivot && j > i)
{
i++;
}
if(i<j)
{
swap(vi[i], vi[j]);
}
}
swap(vi[lo], vi[i]);
quickSort(vi, lo, i-1);
quickSort(vi, i+1, hi);
}
}
int main()
{
vector<int> s{6, 2, 7, 3, 9, 8};
quickSort(s, 0, 5);
for(auto x:s)
{
cout<<x<<endl;
}
return 0;
}