为什么要学习快速排序?
- 因为它快!平均时间复杂度为
O(NlogN)
快速排序图解
示例:对6 1 2 7 9 3 4 5 10 8
这十个数进行排序
步骤
-
找一个数作为基准数(就是一个用来参照的数)。为了方便,这里选第一个数6作为基准数
-
从初始序列
6 1 2 7 9 3 4 5 10 8
两端开始探测。先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换他们。 -
重复第二步直到在6左边的比6小,在6右边的比6大
-
把
6
为中心将初始序列拆为两个序列(不包括6) -
重复第四步,直到所得序列不可拆分
细节
(1)合理的设置基准数
(2)设置哨兵i
,j
,最开始让哨兵i
指向序列第一个元素,j
指向最后一个元素
第一次交换
- 哨兵
j
先出动,因为设置的基准数是最左边的数(这点非常重要) - 哨兵
j
一步步的向左移动,直到找到一个小于6的数停下来 - 接着哨兵
i
一步一步的向右移动,直到找到一个大于6的数停下来 - 最后哨兵
j
停在数字5
前,哨兵i
停在数字7面前 - 交换哨兵
i
与j
所指向的元素
第二次交换
- 哨兵
j
继续向左移动(每次都必须是哨兵j
先动) ,在4
处停下来(比基准数6小)于是, - 哨兵
i
也继续向右移动,在9
处停下来(比基准数6要大) - 交换
第三次交换
- 哨兵
j
向右一步步移动,在3
处停了下来(比基准数6小) - 哨兵
i
继续移动,当哨兵在探测到符合条件的数时(即3
),两者相遇 - “探测”结束,将基准数
6
与3
进行交换。
- 此时,以
6
为分界点拆分成两个序列,左边的序列3 1 2 5 4
都比6
小,右边的序列9 7 10 8
都比6
大。就回到了最开始时的时候,只不过序列变短了 - 重复这个过程,直到不可拆分出新的子序列
c++
实现
# include<iostream>
using namespace std;
int a[101], n;//定义全局变量
void quicksort(int left, int right)
{
int i, j, t, temp;
if (left > right)
return;
temp = a[left];//temp存放基准数
i = left;
j = right;
while (i != j)
{
//顺序很重要,要先从右往左找
while (a[j] >= temp && i < j)
j--;
//再从左往右找
while (a[i] <= temp && i < j)
i++;
//交换两个数在数组的位置
if (i < j)//当哨兵i和哨兵j没有相遇时
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}//最终基准数归位
a[left] = a[i];
a[i] = temp;
quicksort(left, i - 1);//继续处理左边的
quicksort(i + 1, right);//继续处理右边的
}
int main()
{
int i, j, t;
cin >> n;
for (i = 1; i <= n; i++)
cin >> a[i];
quicksort(1, n);
for (i = 1; i <= n; i++)
cout << a[i];
return 0;
}