快速排序
模板题目
LGOJ模板题:P1177 【模板】快速排序
既然名字都叫快速排序,辣么我们就用快速排序来做(笑)。
思路简介
快速排序和归并排序一样,也是基于一种分治法。
我们设void Qsort(int l, int r)
表示将
[
l
,
r
]
[l,r]
[l,r]区间排好序。
每排一次:
我们先找到
[
l
.
r
]
[l.r]
[l.r]的中位数
v
a
l
val
val
然后从前、从后分别设两个指针
i
,
j
i,j
i,j,分别从前、从后寻找符合条件的元素。
什么叫做符合条件的元素呢?
对于
i
i
i指针,如果
a
[
i
]
≥
v
a
l
a[i]\geq val
a[i]≥val,也就是说
i
i
i号元素本来在中位数
v
a
l
val
val后,那么它的位置不太对,它
a
[
i
]
a[i]
a[i]就是符合条件的元素
对于
j
j
j指针,如果
a
[
j
]
≤
v
a
l
a[j]\leq val
a[j]≤val,也就是说
j
j
j号元素本来在中位数
v
a
l
val
val后,那么它的位置不太对,它
a
[
j
]
a[j]
a[j]就是符合条件的元素
找到了这两个元素后,如果
i
≤
j
i\leq j
i≤j,也就是说满足了
i
≤
j
a
n
d
a
[
i
]
≥
a
[
j
]
i\leq j \ and \ a[i]\geq a[j]
i≤j and a[i]≥a[j],我们就把它们交换,就是这样。
这样一次排序完后,我们实际上可以把整个区间分为三部分:
1) 区间
[
l
,
j
]
[l,j]
[l,j]和区间
[
i
,
r
]
[i,r]
[i,r]这两个区间里的元素分别是
<
v
a
l
<val
<val或
>
v
a
l
>val
>val的,它们区间的相对位置已正确,我们只要递归地进行排序:
Qsort(l, j);
Qsort(i, r);
即可
2) 区间
[
j
,
i
]
[j,i]
[j,i]。这里面的元素是
=
v
a
l
=val
=val的,那还排它干啥。
完美。实际代码记得判边界哦。
详细代码
#define USEFASTERREAD 1
#define rg register
#define inl inline
#define DEBUG printf("[Passing [%s] in line %d.]\n", __func__, __LINE__)
#define putline putchar('\n')
#define putsp putchar(' ')
#define Rep(a, s, t) for(rg int a = s; a <= t; a++)
#define Repdown(a, t, s) for(rg int a = t; a >= s; a--)
typedef long long ll;
#include<cstdio>
#define rs freopen("test.in", "r", stdin), freopen("test.out", "w", stdout)
#if USEFASTERREAD
char In[1 << 20], *ss = In, *tt = In;
#define getchar() (ss == tt && (tt = (ss = In) + fread(In, 1, 1 << 20, stdin), ss == tt) ? EOF : *ss++)
#endif
struct IO
{
void RS() {rs;}
template<typename T> inline IO r(T& x)const
{
x = 0; T f = 1; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + int(ch - '0');
x *= f; return *this;
}
template<typename T> inline IO w(T x)const
{
if(x < 0) {putchar('-'); x = -x;}
if(x >= 10) w(x / 10);
putchar(x % 10 + '0'); return *this;
}
template<typename T> inline IO wl(const T& x)const {w(x), putline; return *this;}
template<typename T> inline IO ws(const T& x)const {w(x), putsp; return *this;}
inline IO l() {putline; return *this;}
inline IO s() {putline; return *this;}
}io;
template<typename T> inline T Max(const T& x, const T& y) {return y < x ? x : y;}
template<typename T> inline T Min(const T& x, const T& y) {return y < x ? y : x;}
template<typename T> inline void Swap(T& x, T& y) {T tmp = x; x = y; y = tmp;}
int N;
int A[100005];
void Qsort(int l, int r)
{
if(l >= r) return;
int val = A[(l + r) >> 1];
int i = l, j = r;
while(i <= j)
{
while(i <= r && A[i] < val) i++;
while(j >= l && A[j] > val) j--;
if(i <= j) Swap(A[i], A[j]), i++, j--;
}
Qsort(l, j);
Qsort(i, r);
}
int main()
{
//io.RS();
io.r(N);
for(rg int i = 1; i <= N; i++) io.r(A[i]);
Qsort(1, N);
for(rg int i = 1; i <= N; i++) io.ws(A[i]);
return 0;
}
时空分析
快速排序的最优时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n),最坏时间复杂度为 O ( n 2 ) O(n^2) O(n2),平均时间复杂度为 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)
稳定性
快速排序是一种不稳定的排序
STL
在C++ STL
标准中,在algorithm
头文件里提供了sort()
函数,可以用来快速排序。一般我们排序都用它。