快速排序算法
在刚刚开始学习算法时我们往往会遇到快速排序算法,快速排序法在笔试面试的时候经常会遇到,所以也是我们需要掌握的一个算法。
快速排序法是使用二分法的方法并利用递归的思想来对一个复杂的序列进行排序。快速排序法的时间复杂度为O(nlogn),除了其算法的稳定性不高之外,它的排序效率还是挺高的。
假设我们有以下序列:
arr[]={10, 9, 8, 4, 6, 5, 4, 11, 2, 11}
为了实现一个升序的快速排序,需要按以下的方案来实现:
- 设定一个基准,假设这个基准为序列的第一个元素
- 从序列的右侧依次寻找比基准小的元素并移至左侧,从序列的左侧依次寻找比基准大的元素并移至右侧。
- 对于基准数左右两遍的数组采用上面第二部的方法,不断的对序列进行排序,直到要排序的数组只有一个元素为止,序列有序。
可能文字说明会显得有些难懂,还是以作图的方式来解释:
现在我们将序列的第一个元素的值赋值给基准点 point=10,左侧的下标 i = 0,右侧的小标 j = 9,下面来我们对序列进行排序:
首先我们需要从右边开始找比基准小的元素,j- -
通过 寻找,我们发现当j的下标指向数值为2的数时,数值比基准小因此我们需要赋值 arr[i] = arr[j]
接着我们在左边寻找比基准大的元素,i++,我们发现当 下标数值为11时,数值比基准大,因此我们需要赋值
arr[j]=arr[i]
我们继续重复上面两步的步骤,在右边继续寻找比基准小的数,j- -,这时我们发现i与j指向了同一个下标
这时我们结束第一轮排序把基准的值给赋值进去,arr[i]=arr[j]=point
此时我们会发现,基准左边的数都比基准小,基准右边的数都比基准大,那么我们采用分治法的方式,分别对左边的序列和右边的序列进行排序之后是不是就能把整个序列完整排序了呢。
答案是当然可以的了,当不停的左右分组,直到序列只剩下一个元素的时候就停止排序,最终就会得出顺序的序列了。
具体实现的代码如下所示:
public class Main {
public static void main(String[] args) {
int a[] = new int[]{10, 9, 8, 4, 6, 5, 4, 11, 2, 12};
quickSort(a, 0, a.length-1);
for (int x : a) {
System.out.printf("%3d", x);
}
System.out.println();
}
//快速排序算法(从小到大)
//arr:需要排序的数组,left:需要排序的区间左边界,right:需要排序的区间的右边界
public static void quickSort(int[] arr, int left, int right) {
if (left>=right)
return;
int point = arr[left];//将区间的第一个数作为基准数
int i=left;
int j=right;
//不重复遍历
while (i < j) {
//当右边的数大于基准数时,略过,继续向左查找
//不满足条件时跳出循环,此时的j对应的元素是小于基准元素的
while (i < j && arr[j] >= point)
j--;
//将右边小于等于基准元素的数填入右边相应位置
arr[i]=arr[j];
while (i < j && arr[i] <= point)
i++;
//将左边大于基准元素的数填入左边相应位置
arr[j]=arr[i];
}
//将基准元素填入相应位置
arr[i] = point;
//此时的i即为基准元素的位置
//对基准元素的左边子区间进行相似的快速排序
quickSort(arr,left,i-1);
//对基准元素的右边子区间进行相似的快速排序
quickSort(arr,i+1,right);
}
}