与归并排序一样,快速排序也是采用分治策略。但是归并排序的计算量主要集中在有序子序列的合并上,而子序列的划分几乎不花费时间。快速排序恰恰相反,可以在o(1)的时间内完成子序列的合并,对于将原问题划分上需要花费O(n)的时间。对于子序列的划分上,可能的划分是极不平等的,因此该算法不能保证最坏情况下的O(nlogn)的时间复杂度。一般来说,快排是首选的算法。
因此:版本一
package Basic.QuickSort;
import java.util.Random;
/**
* 该方法对于出现大量的重复元素的时候,轴点位置总是接近与lo,子序列的划分极不均匀,二分递归退化为线性递归,递归深度接近于O(n),运行时间接近于O(n2)
* 在移动lo和hi时,同时比较相邻元素的:lo与hi会交替移动,二者移动的距离大致相等。见于第二版本,而对于重复元素不多的时候,法二反而会增加计算量。
*/
public class QuickSort_v1 {
public static void main(String[] args) {
int[] array = {9, 10, 5, 84, 2, 45, 1, 4, 56, 1};
quickSort(array, 0, array.length - 1);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
public static void quickSort(int[] array, int lo, int hi) {
if (lo >= hi) return;
int mid = partition(array, lo, hi);
quickSort(array, lo, mid - 1);
quickSort(array, mid + 1, hi);
}
private static int partition(int[] array, int lo, int hi) {
swap(array, lo, hi);
int key = array[lo];
while (lo < hi) {
while (lo < hi && array[hi] >= key) hi--;
array[lo] = array[hi];
while (lo < hi && array[lo] <= key) lo++;
array[hi] = array[lo];
}
array[hi] = key;
return hi;
}
private static void swap(int[] array, int lo, int hi) {
int temp = 0;
Random r = new Random();
int k = r.nextInt(10) % (hi - lo + 1) + lo;
temp = array[lo];
array[lo] = array[k];
array[k] = temp;
}
}
版本二:
该方法对于出现大量的重复元素的时候,轴点位置总是接近与lo,子序列的划分极不均匀,二分递归退化为线性递归,递归深度接近于O(n),运行时间接近于O(n2)在移动lo和hi时,同时比较相邻元素的:lo与hi会交替移动,二者移动的距离大致相等。见于第二版本,而对于重复元素不多的时候,法二反而会增加计算量。
package Basic.QuickSort;
import java.util.Random;
import static Basic.QuickSort.QuickSort_v1.quickSort;
/**
*
*/
public class QuickSort_v2 {
public static void main(String[] args) {
int[] array = {9, 10, 5, 84,56 ,96,2, 45, 1, 4, 56,1,10000};
quickSort2(array, 0, array.length - 1);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
public static void quickSort2(int[] array, int lo, int hi) {
if (lo >= hi) return;
int mid = partition(array, lo, hi);
quickSort(array, lo, mid - 1);
quickSort(array, mid + 1, hi);
}
private static int partition(int[] array, int lo, int hi) {
swap(array, lo, hi);
int key = array[lo];
while (lo < hi) {
while (lo < hi) {
if (key < array[hi]) hi--;
else {
array[lo++] = array[hi];
break;
}
}
while (lo < hi) {
if (array[lo] < key) lo++;
else {
array[hi--] = array[lo];
break;
}
}
}
array[lo] = key;
return lo;
}
private static void swap(int[] array, int lo, int hi) {
int temp = 0;
Random r = new Random();
int k = r.nextInt(10) % (hi - lo + 1) + lo;
temp = array[lo];
array[lo] = array[k];
array[k] = temp;
}
}