在之前寻找一个数组中的最大值的时候,我们可以使用二分法的方法寻找最大值,可以大大提高效率。那么在排序的时候,也可以使用类似的想法,利用分治(divide
and conquer)可以将时间复杂度降低至\(O(lgN)\)。首先,我们可以考虑一下情况,有两组数,都是已经排好序的,如果将这两组数按照顺序合并在一起,那么我们可以新创建一个数组,存储新的有顺序的数。首先,比较两组数的第一位数,将较小的数放进新的数组中,较小数所在数组的下一位与较大数所在数组原来的数继续进行比较,直到有一组数达到了尽头,然后把另一组剩下的数放进去得到的新的数组就是排好序的合并后的数组。Java代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
publicstaticvoidmerge(Comparable[] a, int lo, int mid, int hi){ // 数组aux[]为原数组的复制 inti= lo, j = mid+1; for(inri=0; i <= hi; i++){ aux[i] = a[i]; } for(intk= lo; k <= hi; k++){ if(i > mid) a[k] = aux[j++] elseif(j > hi) a[k] = aux[i++]; elseif(less(a[i], a[j])) a[k] = aux[i++]; else a[k] = a[j++]; } }
classQuickSort { publicvoidsort(Comparable[] a) { quickSort(a, 0, a.length-1); } privatevoidquickSort(Comparable[] a, int lo, int hi) { if (lo < hi) { intpartitionIndex= partition(a, lo, hi); quickSort(a, lo, partitionIndex-1); quickSort(a, hi, partitionIndex+1); } } privateintpartition(Comparable[] a, int lo, int hi) { ... } privatevoidswap(Comparable[] a, int i, int j) { inttemp= a[i]; a[i] = a[j]; a[j] = temp; } }
/* 算法第四版 */ privateintpartition(Comparable[] a, int lo, int hi) { inti= lo, j = hi + 1; intpivot= lo; // Scan right, scan left, check for scan complete, and exchange while (true) { while (a[++i] < a[pivot]) if (i == hi) break; while (a[pivot] < a[--j]) if (j == lo) break; if (i >= j) break; swap(a, i, j); } swap(a, lo, j); return j; }
1 2 3 4 5 6 7 8 9 10 11 12 13
/* 菜鸟教程 */ privateintpartition(Comaparable[] a, int lo, int hi) { intpivot= lo; intindex= pivot + 1; for (inti= index; i <= hi; i++) { if (arr[i] < arr[pivot]) { swap(arr, i, index); index++; } } swap(arr, pivot, index - 1); return index - 1; }