算法真好玩,今天写写快排
快速排序作为常见的一种排序,可以说关于他的介绍已经烂大街了。本文不做赘述。 值得一提的是
快速排序是冒泡排序的改良版他的时间复杂度也为O(nlogn)。快速排序也属于稳定排序,即排序之后,相等的两个元素的相对位置不会发生改变经过测试快排的排序效率相当高,这也是他流行的原因吧。百度百科评价其为排序一哥。这个咱也不知道是不是,不敢乱说。本人不喜欢长篇大论,想尽可能用简洁的语言说明一下。突然发现这东西真不是简简单单就能说明白的🤔🤔🤔。建议结合代码和动图理解。动图自己去网上找找很多的。
给出个人的代码实现
public int[] quicksort1(int []a){ if(a.length==0)return a; if(a.length<3){//只剩1个元素或者两个元素,递归结束 if(a[0]>a[a.length-1]){//两个元素时。对这两个元素排序 int tmp=a[0]; a[0]=a[a.length-1]; a[a.length-1]=tmp; } return a; } int tmp=a[0];//当前标准元素,相当于在头指针位置挖了个坑 int head=0;//头指针 int tail=a.length-1;//尾指针 boolean b=false;//当b为false时,尾指针向前遍历。当b为true时,尾指针向后遍历 while(head!=tail){//当头尾指针没有相遇时 if(!b) {//尾指针向前遍历 if (a[tail] < tmp) {//尾指针指向的元素比标准元素小,把尾指针元素填到头指针的坑里。尾指针成为新的坑 a[head++] = a[tail]; b=true;//改变遍历方向 } else { tail--; } }else {//头指针向后遍历 if(a[head]>tmp){ a[tail--]=a[head]; b=false; }else{ head++; } } } //当循环结束,head和tail所在位置就是本轮标准元素该在的位置 a[head]=tmp;//得到标准元素排序后的准确位置 int[] right = Arrays.copyOfRange(a,0,head); int[] left =Arrays.copyOfRange(a,head+1,a.length); left=quicksort1(left); right=quicksort1(right); for (int i = 0; i <right.length ; i++) { a[i]=right[i]; } for (int i = 0; i <left.length ; i++) { a[i+head+1]=left[i]; } return a; }代码写完了,突然想去看看别人的代码。不看不要紧,一看吓一跳,怎么别人的代码辣么少。经过分析,上面的代码创建好了几个新数组,浪费空间不说还没有节省时间。于是修改代码如下
public int[] quicksort2(int []a,int head,int tail){ if(tail-head<2){//优化递归结束条件 return a; } int tmp=a[head]; int h=head;//备份起始下标 int t=tail;//备份结束下标 boolean b=false;//当b为false时,尾指针向前遍历。当b为true时,头指针向后遍历 while(head!=tail){//当头尾指针没有相遇时 if(!b) {//尾指针向前遍历 if (a[tail] < tmp) {//尾指针指向的元素比标准元素小,把尾指针元素填到头指针的坑里。尾指针成为新的坑 a[head++] = a[tail]; b=true;//改变遍历方向 } else { tail--; } }else {//头指针向后遍历 if(a[head]>tmp){ a[tail--]=a[head]; b=false; }else{ head++; } } } a[head]=tmp; quicksort2(a,h,head-1);//优化内存占用 quicksort2(a,head+1,t); return a; }这回看着舒服点了
原数组{3,44,38,5,47,15,36,26,27,2,46,4,19,50,48,38}
QuickSort1排序时间为:49100 [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 47, 48, 50]
QuickSort2排序时间为:31800 [2, 3, 4, 5, 15, 19, 27, 26, 36, 38, 38, 44, 46, 47, 48, 50]
试了好几次,优化之后的代码执行确实变快了