介绍
快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
代码思路
我们要先设定一个基准策略,可以是序列的第一个、中间、最后一个数。我觉得选取第一个数作为基准比较容易理解,也容易实现。
1.首先有一个大前提,左边界 < 右边界,(并非左右指针)如果违反就说明已经排好了 !就可以退出!
left-左指针,right-右指针,base-基准值(序列首位)
3.寻找满足条件的两个逆序数,进行交换。细节如下:
左移,遇到小于base的数就停下
右移,遇到大于base的数就停下
交换
left < right!不控制的话就越界了!会死循环)
left=right
base与指针所指的数交换位置,那么base左右两边的数都是符合条件的了
5.修改边界,分别递归地对左右两个子列进行快速排序。直到每个子列只有一个数,即左右边界相等。再往下面递归的话就被 1 的条件 return 了
代码演示
public static Integer[] QuickSort(Integer[] arr,Integer left,Integer right){
if(left>right) return arr;
int l=left;
int r=right;
Integer base=arr[l];//以序列的首位元素为基准
//左指针循环右移,右指针循环左移,直到二者相遇就终止
while(l!=r){
//右指针左移,直到遇到比基准小的数时停止移动
while (arr[r]>=base && l<r) r--;
//左指针右移,直到遇到比基准大的数时停止移动
while (arr[l]<=base && l<r) l++;
//交换左右指针所指元素。注意这里面 l<r 的条件都是必须的,因为不能让左右指针越界啊!!,没有这个条件的话就无限执行了...
if(l<r) {
Integer temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
}
}
//左右指针相遇时,交换基准元素与指针指向的元素,此时基准元素的左边数都比他小,右边数都比它大
arr[left]=arr[l];
arr[l]=base;
//分别对基准元素的左右子序列执行同样的操作
QuickSort(arr,left,l-1);
QuickSort(arr,l+1,right);
return arr;
}
测试
@Test
public void testSelectSort(){
Integer[] arr = init();
System.out.println("原始数据为:");
print(arr);
Long beginTime= System.currentTimeMillis();
Integer[] result = QuickSort(arr,0,arr.length-1);
Long endTime= System.currentTimeMillis();
System.out.println("排序结果为:");
print(result);
System.out.println("耗时:"+(endTime-beginTime)+" ms");
}
总结
快速排序是对冒泡排序的改进,其效率还是挺高的
- 明确快排终止条件:左边界 < 右边界,即只有一个元素或者没有元素。
- 明确指针移动条件:left <= right,即左指针在右指针左边时才能移动,越界会死循环!
- 明确指针移动顺序:当选取首元素作为基准元素时,先移动的指针一定要是右指针(当选取最右边的元素为基准元素时,先移动的指针一定要是左边的指针)。因为右指针找的是小于基准元素的数,一轮排序的最后要让基准元素、指针所指元素互换,先让右指针移动才能保证互换后的序列满足条件!
这是错误的例子:以首元素为基准,先移动左指针,左指针找的是大于基准的数。再移动右指针,左右指针重合。交换元素,显然结果是错的!!
注:这是一个优化后的代码
public void quickSort(String[] strs,int left,int right){
if(left>=right) return;
String base=strs[left];
int l=left;
int r=right;
//与基准元素比较大小,交换左右指针元素
while(l<r){
while(strs[r]>strs[left] && l<r) r--;
while(strs[l]<strs[left] && l<r) l++;
String tmp = strs[l];
strs[l] = strs[r];
strs[r] = tmp;
}
//移动基准元素
strs[left]=strs[l];
strs[l]=base;
quickSort(strs,left,l-1);
quickSort(strs,l+1,right);
}