快速排序小结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速排序小结相关的知识,希望对你有一定的参考价值。
快速排序小结
大纲:
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;}
以上是关于快速排序小结的主要内容,如果未能解决你的问题,请参考以下文章