快速排序 Java 針對重複元素
阿新 • • 發佈:2019-01-06
與歸併排序一樣,快速排序也是採用分治策略。但是歸併排序的計算量主要集中在有序子序列的合併上,而子序列的劃分幾乎不花費時間。快速排序恰恰相反,可以在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;
}
}