荷兰国旗
链接:荷兰国旗算法
荷兰国旗中的基准数是选定的,而这里快速排序我们默认每次的基准数都是最后一个数。
快排思路
基准数选定为最后一个数x
L用于正在遍历的元素的下标,初始值为0,从左向右遍历,当L>=more时遍历结束。
less用于记录小于x的区域的最右边的下标,初始为-1,代表不存在。
more 用于记录大于 x区域的最左边的下标,初始为x所在的位置。
arr[ l ] 初始值为排序数组的第一个元素
arr[ r ]初始值为排序数组的最后一个元素,即x
1⃣️当arr[ l ] < arr[ r ]时,less向右移一位(即空间开辟一位),当arr[ l ] 与less右移之后的位置上的数交换,其实就是把小于基准数的那个数存在less这个区域。L++继续遍历。
2⃣️当arr[ l ] > arr[ r ]时,指针more向左移一位(即空间开辟一位),并将arr[ l ] 的元素与more左移后位置上所在的元素互换,其实就是把小于基准数的那个数存在more这个区域。
3⃣️L指向的元素x = num时,L++继续遍历。
4⃣️L>=more时遍历结束,此时将指针more所在的值(记录大于 x区域的最左边的下标对应的元素)和arr[ r ](基准值)进行交换。此时,基准值x就被交换到了中间,左边less区域为小于基准值x的值,右边more区域为大于基准值x的值。
5⃣️返回一个新的数组,由两个数组成,即基准值x的位置。这里可能出现多个相同的基准值,所以保险的下标范围是[less+1,more],即小于x区域的最右边的下标+1和大于 x区域的最左边的下标+1(more=大于 x区域的最左边的下标+1)。
6⃣️用上一步返回的新数组作为的两个值作为边界,采用分治思想,将数组划分成两个,继续排序。
代码
public class QuickSort {
public void quickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
quickSort(arr, 0, arr.length - 1);
}
public void quickSort(int[] arr,int l,int r){
if (l < r){
int[] p = patition(arr,l,r);
patition(arr,l,p[0]-1);
patition(arr,p[1]+1,r);
}
}
public int[] patition(int[] arr,int l, int r){
int less = l-1;
int more = r;
while (l < more){
if (arr[l] < arr[r]){
swap(arr,++less,l++);
}else if (arr[l] > arr[r]){
swap(arr,--more,l);
}else {
l++;
}
}
swap(arr,more,r);
return new int[]{less+1,more};
}
public void swap(int[] arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args) {
int[] array = {1,4,3,3,7,6,5};
QuickSort quick = new QuickSort();
quick.quickSort(array);
for (int i = 0; i <= array.length-1; i++)
System.out.print(array[i]+" ");
}
}
局限性
总拿最后一个数作为基准数,此时的时间复杂度被实际的数据状况影响。
坏情况:
int[] arr = {1,2,3,4,5};
此时第一趟搞定5,第二趟搞定4…每一趟的时间复杂度为o(n),n趟之后即为o(N^2)