快速排序
- 快速排序(Quicksort)的思想是分治(Divide and conquer),顾名思义将一个串分成两个串,再讲其中一个继续分治,直到全部完成。
- 算法描述
- 1.从数列中选取一个分界点
- 2.分区操作,基于分界点,将整个数列进行排序,所有小于分界点的数放在分界点左边,所有大于分界点的数放在分界点右边,和分界点相等的数可以到任意一边,此后,分界点就会在整个数列的中间位置。
- 3.递归的把左右两个子数列进行排序。
- 时间复杂度(平均复杂度):n log n
常用时间复杂度排序:
O( 1 )<O( longn )<O( n )<O(n longn )<O( n^2 )<O( n^3 )<O(2^n)
快排模板如下:
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;//如果待排列的数组p里面数字只有一个或者为空的情况下
int x = q[ l ],i = l - 1, j = r + 1;//x为选的分界点,如果取/2,可能依然会报错(内存溢出),但是用位运算符就可以AC,以为CPU对于位运算符的处理速度比/2快很多
while(i < j)
{
do i++ ; while (q[i] < x);
do j-- ; while (q[j] > x);
if(i < j) swap(q[i],q[j]);
}
quick_sort(q,l,j);
quick_sort(q,j + 1,r);
}
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;//如果待排列的数组p里面数字只有一个或者为空的情况下
int x = q[(l + r + 1) / 2],i = l - 1, j = r + 1;//x为选的分界点,此时x不能选l,会出现死循环
while(i < j)
{
do i++ ; while (q[i] < x);
do j-- ; while (q[j] > x);
if(i < j) swap(q[i],q[j]);
}
quick_sort(q,l,j);
quick_sort(q,j + 1, r);
}
注意
-
比如说取左边界int x = q[l]; quick_sort(q,l,i - 1); quick_sort(q,i,r),对于数组0,1进行快排,选0为分界点,i指向0,j指向1,i不满足,继续指向0,j满足大于0,j指向0,此时i和j相遇,分为左右数组,左边的是quick_sort(q[2],0, - 1),右边的是quick_sort(q[2],0,2),右边的数组将陷入死循环。
-
当x=q[l+r>>1]的边界情况,此时x取的是序列中间靠左的位置(如果序列个数为奇,则取正中间,如果为偶,则取中间靠左),此时如果元素个数为2,
则中间靠左就是第1个元素,这时就跟x=q[l]的边界情况一致了,所以这时只能用sort(l,j),sort(j+1,r); -
当x=q[l+r + 1>>1]的边界情况
此时x取的是序列中间靠右的情况,同理,当元素只有两个,情况就会类似x=q[r],此时只能用sort(l,i-1),sort(i,r); -
如果x=q[l] or x=q[l+r>>1]此时只能用sort(l,j),sort(j+1,r);
如果x=q[r] or x=q[l+r + 1>>1]此时只能用sort(l,i-1),sort(i,r);