785. 快速排序

 

题目描述

给定你一个长度为n的整数数列。

请你使用快速排序对这个数列按照从小到大进行排序。

并将排好序的数列按顺序输出。

输入格式

输入共两行,第一行包含整数 n。

第二行包含 n 个整数(所有整数均在1~109

范围内),表示整个数列。

输出格式

输出共一行,包含 n 个整数,表示排好序的数列。

数据范围

1 ≤ n ≤ 100000

1n100000

输入样例

5

3 1 2 4 5

输出样例

1 2 3 4 5

 

思路

  快速排序时间复杂度O(N*logN),其思想是分治法,

  该方法的基本思想是:

  1.先从数列中取一个数k作为基准数(一般是数列的第一个数或中间那个数);

  2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边.

  ①k为第一个数:设一个头指针i(此时i指向k),尾指针j,当i<j时,先从数列末端往前(j--)找到第一个小于k的数,将j指向的那个值放到i的位置,然后从i往后(i++)找到第一个大于k的数,将i指向的那个值放到j的位置. 直到最后i==j,k就放到这个位置;

  ②k为中间那个数:设一个头指针i,尾指针j,当i<j时,i向后移动直到i指向的数≥k,j向前移动直到j指向的数≤k,此时若i<j则将它们指向的两个数交换,然后继续重复这个步骤,直到i>=j;

  3.再对左右区间重复第二步,直到各区间只有一个数;

 

  一般我选择第一个数作为基准值,不过在这里超时了,代码如下——

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 using namespace std;
 5 int q[100005];
 6 
 7 void quickSort(int l, int r) {
 8     if(l>=r) return;
 9     int i=l, j=r, k=q[l];
10     while(i<j) {
11         while(i<j && q[j]>=k) j--;
12         q[i]=q[j];
13         while(i<j && q[i]<=k) i++;
14         q[j]=q[i];
15     }
16     q[i]=k;
17     quickSort(l, i-1);
18     quickSort(i+1, r);
19 }
20 
21 int main() {
22     int n;
23     cin>>n;
24     for(int i=0; i<n; i++) cin>>q[i];
25     quickSort(0, n-1);
26     for(int i=0; i<n; i++) cout<<q[i]<<' ';
27 }

  然后改用中间数作为基准值了,但是因为不怎么用,所以出了bug,上个代码以告诫自己,避免错误重犯,要仔细审题——

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 
 8 int q[100005];
 9 
10 void quickSort(int l, int r) {
11     if(l>=r) return;
12     int i=l,  j=r, k=q[l+r >> 1];
13     while(1) {
14         while (q[i]<k) i++;
15         while (q[j]>k) j--;
16         if(i>=j) break;
17         swap(q[i], q[j]);
18     }
19     quickSort(l, j-1);
20     quickSort(j+1, r);
21 }
22 
23 int main() {
24     int n;
25     cin>>n;
26     for(int i=0; i<n; i++) cin>>q[i];
27     quickSort(0, n-1);
28     for(int i=0; i<n; i++) cout<<q[i]<<' ';
29     return 0;
30 }

  分析错误数据可知,数列中存在相等的数,因为是用while,所以当q[i]和q[j]都为k时,i和j都不会更新,导致while陷入死循环,所以i要自增,j要自减;不过看了一下题解发现基本上都是用do...while...写的,所以说,平时不要只用一种写法,其他的写法也要熟悉,这样才能随机应变.

  以下是AC代码——

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 
 8 int q[100005];
 9 
10 void quickSort(int l, int r) {
11     if(l>=r) return;
12     //do...while...
13     int i=l-1,  j=r+1, k=q[l+r >> 1];
14     while(i<j) {
15         do i++; while(q[i]<k);
16         do j--; while(q[j]>k);
17         if(i<j) swap(q[i], q[j]);
18     }
19     //while...
20 //    int i=l,  j=r, k=q[l+r >> 1];
21 //    while(1) {
22 //        while (q[i]<k) i++;
23 //        while (q[j]>k) j--;
24 //        if(i>=j) break;
25 //        swap(q[i], q[j]);
26 //        i++;
27 //        j--;
28 //    }
29     quickSort(l, j);
30     quickSort(j+1, r);
31 }
32 
33 int main() {
34     int n;
35     cin>>n;
36     for(int i=0; i<n; i++) cin>>q[i];
37     quickSort(0, n-1);
38     for(int i=0; i<n; i++) cout<<q[i]<<' ';
39     return 0;
40 }

 

posted @ 2020-09-10 23:39  自在逍遥处  阅读(166)  评论(0编辑  收藏  举报