1. 算法思想
1、无论是冒泡法、堆排序法还是归并法排序,都是重复找到数组中剩余未排序元素的最大或最小值,然后将每次找到的最大或最小值依次放进数组中就可以得到一个有序的数组。快速排序法也与其类似,但不同的是,快速排序是通过任意指定数组中的一个元素作为基准,比该元素大的放在右边,比该元素小的放在左边,这样就可以保证指定的这个元素一定会处于有序数组中的位置,然后再分别对左边和右边的未排序元素重复进行该步骤(在未排序的元素中指定新基准元素,然后查找该基准元素在有序情况下所应该在的位置,然后与该位置的元素进行交换),就可以将实现排序。
2、算法核心:快速排序的算法核心就在于以数组中的一个元素作为基准,如何实现比该元素大的放在右边,比该元素小的放在左边,也就是基准元素在有序数组中的位置查找,基准元素通常指定数组中最后一个元素。算法步骤如下
(1)首先需要一个下标来记录基准元素的下标位置,为m;
(2)其次还需要用i和j来标记大于基准元素的元素下标区间,i<j,arr[i]到arr[j]的元素都是大于基准元素的,下标 i 用来记录大于基准元素的区间下标起点,而 j 表示区间下标终点。
(3)由 j 负责向后遍历,如果 j++后遇到小于基准元素的,那么就需要将arr[j]与arr[i]的值交换,并且i++。
(4)如果j++后遇到的值是大于基准元素,那么就不执行i++,继续执行j++访问下一个元素。
(5)保证下标 i与j 之间的元素都是大于基准元素的,直到 j 的值为m-1。此时 arr[i]到arr[j]之间的就全部为大于基准元素的,此时只需要将 arr[m]与arr[i]的值进行交换,就能实现比基准元素大的放在右边,比基准元素小的放在左边。
3、算法核心实例:以数组 arr=[ 12,32,4,23,45,66,21 ] 为例,基准元素下标为 m=arr.length,也就是最后一个元素21
(1)从下标j= i=0开始,arr[j] =12 小于21,不属于大于基准元素区间的,arr[i]和arr[j]交换值,i++,j++,跳转至下一个元素。(i=1,j=1)
(2)对于arr[j] = 32大于21,所以 i 不变,j++。(i=1,j=2)
(3)对于 arr[j] = 4小于21,所以arr[i]和arr[j]交换值,i++,j++,跳转至下一个元素,此时数组形式[ 12,4,32,23,45,66,21 ]。(i=2,j=3)
(4)对于 arr[j] = 23大于21,所以 i 不变,j++。(i=2,j=4)
(5)对于 arr[j] = 45 , i 不变,j++。(i=2,j=5)
(6)对于 arr[j] = 66 , i 不变,j++。(i=2,j=6)
(7)j= m-1,遍历结束,将arr[i] 和arr[m]的值交换,即可得到 [ 12,4,21,23,45,66,32 ]
4、基准元素在有序数组中的位置查找核心算法思想完成,现在就只需要考虑如何对数组中的每一个元素都进行一次位置查找,通过递归,对基准元素两边的其他元素分别进行递归调用即可实现排序。具体实现代码如下
public class Sort {
public static int[] sort(int[] arr, int right, int left) {
if (right >= left) {
return arr;
}
int i = right;
for (int j = right; j<=left-1; j++){
if (arr[j] >= arr[left]) {
continue;
} else {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
i++;
}
}
int temp = arr[left];
arr[left] = arr[i];
arr[i] = temp;
//对左边的元素进行排序
sort(arr, right, i-1);
//对右边元素进行排序
sort(arr, i+1, left);
return arr;
}
public static void main(String[] args) {
int[] arr = {3,23,4,13,4,5,63,6,2};
for(int i:sort(arr,0,arr.length-1)) {
System.out.print(i+",");
}
}
}