什么是快速排序 ?
在无序的序列中选择第一个数作为准基,我们第一次排序要做的事情就是把比准基小的放在准基左边,比准基大的放在准基右边.
怎么才能做到以上操作呢?
我们把数组的两端分别加上指针left,right
我们从右边指针开始跟准基作比较,发现2比6小,那么它应该在左侧,我们把它放在左侧指针位置,我们把left指到的位置变为2,同时把left指针向右移,因为第一次排序2的位置已经确定了。
此时有人会问,那6呢,6没了啊? 6其实一开始被我们新开辟的一个空间保存着了,所以我们想要的时候直接拿就可以。
右边我们进行过一次,那么下一次轮到左边,将9和准基做比较,发现9大于准基,它应该在右边,那么就把它放在right的位置。同时让right指针左移.
下面是不是又轮到右边啦,我们发现8比准基大,那么它就应该在右边,所以它不用动。
值得注意的是!!!!当右边没动时,我们还从右边开始!!!!!
也就是说我们把right指针左移,并且让7和准基作比较。
那么什么时候轮到左边呢? 直到像1,2步那样动了为止!!!!!!
直到右指针指针到3了,发现比准基小了,他应该在左边,那就放在左边指针!!!!!同时让左边的指针右移!!
左右指针在一起了怎么办!!!!!
我们的准基还没放进去呢,我们把准基放进去
好了,经历了好久好久,我们终于把6的位置确定了。。 ? ? ? ? ?才确定了一个 ? ? ?
慢慢来仔细看,准基6的两边又是无序的,那么我们再用这样的方法进行排序,是吧,你想到了递归。
递归肯定要有结束条件吧? 啥时候结束啊,
是不是lelf或者right到一起并且是边界的时候!!!
i和j是我们要排序的数组的下标,一开始我们传入i=0 j等于a数组的长度即可
第一次排序我们不是已经确定好准基的位置了吗
下次我们需要排序的就是上次准基位置的左边和上次准基位置的右边
下面看一下代码
public static void queckOrder(int[] a,int i,int j){ //以第一个数作为准基 int base = a[i]; //赋值左右两边 int left=i; int right=j; int flag = 1; //1代表从右边开始 0代表从左边开始 //当左右两边没有碰撞 while(right>left){ //右边的数字比准基小 if(flag==1){ if(a[right]<base){ //放到左边 左边的指针右移 a[left]=a[right]; left++; //下面要从左边开始了 flag=0; }else { //否则不动,右边指针左移 right--; } } else if(flag==0){ if(a[left]>base){ //放到左边 左边的指针右移 a[right]=a[left]; right--; //下面要从右边开始了 flag=1; }else { //否则不动,右边指针左移 left++; } } } if(left==right){ a[left]=base; if(left!=i){ queckOrder(a,i,left-1); }else {return;} if(left!=j){ queckOrder(a,left+1,j); }else {return;} } }
测试用例:
需要注意:选择排序不是稳定的排序方法。
堆排序 、 快速排序 、 希尔排序 、 直接选择排序 是不稳定的排序算法,而 冒泡排序 、 直接插入排序 、 折半插入排序 、 归并排序 是稳定的排序算法