快速排序小结

 

大纲:

         1.快排的原理

         2.最坏情况

         3.优化快排的方法

         4.一般写法与更好的写法

1.快排的原理(本文重点)

         伪代码:

                   Void sqsort(int left,int right){

                           1.随便找个数aN

                            2.把要排序的数组分成以下 区间

                                     <aN|<aN|<aN|…|==aN|==aN|==aN|…|>aN|>aN|>aN|…|

                            3.分别递归<aN与>aN的两个部分

                                     If(left<最右边的<aN.sub) sqsort(left,最右边的<aN.sub);

                                     If(最左边的>aN.sub >最左边的) sqsort(最左边的>aN.sub,right);

}

2.最坏情况

         1.数组为有序或相同

         2.任何能让快排每次递归的区间都只比上一次递归区间少一元素的数据

        最坏情况后果:

           快排会退化成冒泡

           具体请见算法导论或其它博客

3.优化快排的方法

              1.使用随机数找aN

              2.随机三个取中值为aN

              3.最左,中间,最右取中值为aN

              4.数据效小时用插入排序

              5.尾递归

              6. …

 4.一般写法与更好的写法

一般,详细请看:http://developer.51cto.com/art/201403/430986.htm

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 int a[10000005];
 4 void swap(int *a, int *b) {
 5     int t = *a;
 6     *a = *b;
 7     *b = t;
 8 }
 9 int sj(int l, int r) {
10     return rand() % (r - l + 1) + l;
11 }
12 void qSort(int l,int r) {
13     int i = l,j = r;
14     swap(&a[l],&a[sj(l,r)]);//始终以最左为基准
15     while (i < j) {
16         while (i < j&&a[j] >= a[l])j--;while (i < j&&a[i] <= a[l])i++;//前面后面分别找个不该在此区间的
17         //只有j在前才能归位最左基准,要是j在后那就以i-1归位
18         if (i < j) { swap(&a[i], &a[j]); }//把两站错区间的交换到正确区间
19     }
20     swap(&a[l],&a[i]);//归位基准
21     if(l<i-1)qSort(l, i - 1);//<aN区间递归
22     if(i+1<r)qSort(i+1,r);//>aN区间递归
23 }
24 int main() {
25     int n;
26     freopen("in.in", "r", stdin);
27     scanf("%d", &n);
28     for (int i = 1;i <= n;i++)scanf("%d", &a[i]);
29     qSort(1, n);
30     for (int i = 1;i <= n;i++)printf("%d ", a[i]);
31     return 0;
32 }

更好:2017/3/4 网上没详解这个的,这种的性能简直出奇好

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 int a[10000005];
 4 
 5 void swap(int *a, int *b) {
 6     int t = *a;
 7     *a = *b;
 8     *b = t;
 9 }
10 
11 void quicksort(int left,int right)
12 {
13     int i,j,base;i=left; j=right;base=a[(left+right)/2];
14     //基准数随意选了位于中间的
15     while (i<=j){
16        while (a[j]>base) j--;while (a[i]<base) i++;//前面后面分别找个不该在此区间的
17         //j在前还是i在前随意
18        //while (a[i]<base) i++;while (a[j]>base) j--;
19        if (i <= j) {
20             swap(&a[i],&a[j]);//交换
21             i++;j--;//是个小优化
22         }
23     }
24     //到此,区间划分完成 。这种写法更注重区间的划分,而不是在意基准数的归位
25     if (left<j) quicksort(left,j);//<aN区间递归
26     if (i<right) quicksort(i,right);//>aN区间递归
27 }
28 int main(){
29     int n;
30     freopen("in.in","r",stdin);
31     scanf_s("%d",&n);
32     for (int i=0;i<n;i++)scanf_s("%d",&a[i]);  
33     quicksort(0,n-1);
34     for (int i=0;i<n;i++)printf("%d ",a[i]);
35     return 0;
36 }

总的来说就是 1.减少了递归层次2.与遍历次数3.解决了繁锁的基准数操作问题

10485765个重复数测试,这种1分25秒完成,传统3分种的时候爆栈

普通版评测:https://www.luogu.org/record/show?rid=1818379

更优版评测:https://www.luogu.org/record/show?rid=1821228

#include <stdio.h>#include <stdlib.h>int a[10000005];void swap(int *a, int *b) {int t = *a;*a = *b;*b = t;}int sj(int l, int r) {return rand() % (r - l + 1) + l;}void qSort(int l,int r) {int i = l,j = r;swap(&a[l],&a[sj(l,r)]);//始终以最左为基准while (i < j) {while (i < j&&a[j] >= a[l])j--;while (i < j&&a[i] <= a[l])i++;//前面后面分别找个不该在此区间的//只有j在前才能归位最左基准,要是j在后那就以i-1归位if (i < j) { swap(&a[i], &a[j]); }//把两站错区间的交换到正确区间}swap(&a[l],&a[i]);//归位基准if(l<i-1)qSort(l, i - 1);//<aN区间递归if(i+1<r)qSort(i+1,r);//>aN区间递归}int main() {int n;freopen("in.in", "r", stdin);scanf("%d", &n);for (int i = 1;i <= n;i++)scanf("%d", &a[i]);qSort(1, n);for (int i = 1;i <= n;i++)printf("%d ", a[i]);return 0;}

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!