快速排序
公认的高效排序。这次在原来的基础上加上了随机化的选择划分值,降低最坏时间复杂度。
写划分函数可能有点困难,常见的有两种方法。一种是填坑法,另一种就是本文的方法。
填坑法的思路是:
1.预先保存key值;
2.从后往前找,找到一个比key值小的数,然后把这个数填到key值的位置;
3.从前往后找,找到一个比key值大的数,然后把这个数填到上面的数的原先位置;
4.回到第2步,直至两个下标相遇;
5.把key值填到下标相遇位置(原来的数已经填到别的地方了)。
我以前也一直在写这种方法,因为思路很简单,但是写起来不够简洁。这次用了另外一种方法,可能有点难理解,但代码相当很简洁。我不知道能不能讲清楚。
同样需要用到两个下标i, j
1. j从前往后找,一直到遇到一个比key值小的数;
2.这时将i+1,显然i+1这个位置要不就是当前找到的位置,要不就是一个比key值大的数所处的位置;
3.若属于后者,则需要交换这个两个值。然后回到第一步,一直到遍历完数组;
4.最后将i的位置与low位置交换(i所处位置的数必然小于key值)
这里说的下标和代码用的有点不同,但思路就是这样了。
public static void quickSort(int[] A){ quickSortDo(A, 0, A.length-1); } private static void quickSortDo(int[] A, int low, int high){ if(low < high){ int key = partition(A, low, high); quickSortDo(A, low, key-1); quickSortDo(A, key+1, high); } } private static int partition(int[] A, int low, int high){ int key = low; Random rand = new Random(); int k = rand.nextInt(high-low+1) + low; swap(A, k, low); int x = A[key]; for(int i = low+1; i <= high; i ++){ if(A[i] < x){ key ++; if(i != key){ swap(A, i, key); } } } swap(A, low, key); return key; }