请把此文与快速元算法一文一起观察。
/** * partition,有台湾国人译为轴,也叫分段元素,姑且不论哪个更准确,两个名称我都用。 * 分析了SUN公司数组排序源代码,并且根据本人实际需要,照搬出来一个sort(number, numberArr); * 请把此类和QuickSort类一致观察运行效率的差异. * @author Josh Bloch * @see paulliu * */public class CollectionTest {
public static void main(String[] array) { int length=400000; String[] numberArr=new String[length]; int[] number=new int[length]; Random random=new Random(); for(int i=0;i<length;i++){ number[i]=random.nextInt(10000); numberArr[i]=number[i]+"ss"; } //int[] number={1,14,32,14,11,54,32,14,26,3,14,10,436,56}; long fisrtt=System.currentTimeMillis(); //sort(number); //sort(number, numberArr); System.out.println("计算时间MS:"+(System.currentTimeMillis()-fisrtt)); //***********************// long second=System.currentTimeMillis(); QuickSort.sort(number, numberArr); System.out.println("QuickSort计算时间MS:"+(System.currentTimeMillis()-second)); for(int i=0;i<number.length;i++){ //System.out.println(number[i]+"---------------"+numberArr[i]); //System.out.println(number[i]+"-----"); } number=null; numberArr=null; }
public static void sort(int[] a) { sort1(a, 0, a.length); }
public static void sort(int[] a, String[] array) { sort2(a, 0, a.length, array); }
/** * * @param x int[] * @param off int * @param len int * @param array String[] */ private static void sort2(int x[], int off, int len, String[] array) { // Insertion sort on smallest arrays if (len < 7) { for (int i = off; i < len + off; i++) {
//x[j - 1] > x[j] for (int j = i; j > off && x[j - 1]<x[j]; j--) { //swap(x, j, j - 1); swap2(x, array, j, j - 1); } } return; } // Choose a partition element, v int m = off + (len >> 1); // Small arrays, middle element if (len > 7) { int l = off; int n = off + len - 1; if (len > 40) { // Big arrays, pseudomedian of 9 int s = len / 8; l = med3(x, l, l + s, l + 2 * s); m = med3(x, m - s, m, m + s); n = med3(x, n - 2 * s, n - s, n); } m = med3(x, l, m, n); // Mid-size, med of 3 } int v = x[m]; // Establish Invariant: v* (<v)* (>v)* v* int a = off, b = a, c = off + len - 1, d = c; while (true) {
x[b] <= v while (b <= c && x[b] >= v) { if (x[b] == v) { //swap(x, a++, b); swap2(x, array, a++, b); } b++; } x[c] >= v while (c >= b && x[c] <= v) { if (x[c] == v) { //swap(x, c, d--); swap2(x, array, c, d--); } c--; } if (b > c) { break; } //swap(x, b++, c--); swap2(x, array, b++, c--); } // Swap partition elements back to middle int s, n = off + len; s = Math.min(a - off, b - a); //vecswap(x, off, b - s, s); vecswap2(x, array, off, b - s, s); s = Math.min(d - c, n - d - 1); //vecswap(x, b, n - s, s); vecswap2(x, array, b, n - s, s); // Recursively sort non-partition-elements if ( (s = b - a) > 1) { //sort1(x, off, s); sort2(x, off, s, array); } if ( (s = d - c) > 1) { //sort1(x, n - s, s); sort2(x, n - s, s, array); } }
private static void sort1(int x[], int off, int len) { // Insertion sort on smallest arrays if (len < 7) { for (int i = off; i < len + off; i++) { for (int j = i; j > off && x[j - 1] > x[j]; j--) { swap(x, j, j - 1); } } return; } // Choose a partition element, v //选择一个较为合理的轴,或者叫分段元素v int m = off + (len >> 1); // Small arrays, middle element if (len > 7) { int l = off; int n = off + len - 1; if (len > 40) { // Big arrays, pseudomedian of 9 //对于大数组,先分段选择各自的轴 int s = len / 8; l = med3(x, l, l + s, l + 2 * s); m = med3(x, m - s, m, m + s); n = med3(x, n - 2 * s, n - s, n); } m = med3(x, l, m, n); // Mid-size, med of 3 所有轴中挑选更"合理"的那个作为整个数组的分段元素 } int v = x[m]; // Establish Invariant: v* (<v)* (>v)* v* int a = off, b = a, c = off + len - 1, d = c; while (true) { while (b <= c && x[b] <= v) {//游标1,从起始到结束位置,找到大于中间值的数值 if (x[b] == v) { swap(x, a++, b);//与中间值相等的数值放到前面 } b++; } while (c >= b && x[c] >= v) {//游标2,从结束位置到起始位置,找寻小于中间值的数值 if (x[c] == v) { swap(x, c, d--);//与中间值相等的数值放到后面 } c--; } if (b > c) {//停止查找 break; } swap(x, b++, c--);//把大于中间值并且位置起始位置的数值与小于中间值且位于数组末尾的数值进行交换 } // Swap partition elements back to middle int s, n = off + len; s = Math.min(a - off, b - a);//游标1,停止查找后把中间值交换到末尾 vecswap(x, off, b - s, s); s = Math.min(d - c, n - d - 1); vecswap(x, b, n - s, s);//游标2,停止查找后把中间值交换到起始 // Recursively sort non-partition-elements if ( (s = b - a) > 1) { sort1(x, off, s);//以中间值为界对小于中间值部分排序,不包含中间值 } if ( (s = d - c) > 1) { sort1(x, n - s, s);//以中间值为界对大于中间值部分排序,不包含中间值 } }
//---------------// private static void vecswap2(int x[], String[] arr, int a, int b, int n) { for (int i = 0; i < n; i++, a++, b++) { swap2(x, arr, a, b);
} }
/** * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)]. */ private static void vecswap(int x[], int a, int b, int n) { for (int i = 0; i < n; i++, a++, b++) { swap(x, a, b); } } /** * 找出中间值 * @param x * @param a * @param b * @param c * @return */ private static int med3(int x[], int a, int b, int c) { return (x[a] < x[b] ? (x[b] < x[c] ? b : x[a] < x[c] ? c : a) : (x[b] > x[c] ? b : x[a] > x[c] ? c : a)); }
/** * * @param x String[] * @param a int * @param b int */ private static void swap2(int[] x, String[] array, int a, int b) { swap(x, a, b); String t = array[a]; array[a] = array[b]; array[b] = t; }
private static void swap(int x[], int a, int b) { int t = x[a]; x[a] = x[b]; x[b] = t; }
}
研究一下算法的效率,对比一下从他处看到的快速算法与jdk中排序算法的速度。单机测试环境P4-2.66GHZ,随机数组测试,没有进行压力测试。
结论如下:
1、以前给出的QuickSort中三个方法,第一个和第二个效率相当,第三个方法thirdsort()效率比较差,以前认为它在查找轴/分段元素时有一定优点,可测试发现比较笨拙,笨拙查找方式加上递归,导致效率低下;
2、int型数组大小小与等于30万时,快速演算法中public static void sort(int[] number, int left, int right)方法和public static void provesortfirst(int[] number, int left, int right)方法与Arrays.sort()方法效率相当;
3、数组大小大于等于30万时,Arrays.sort()的分段选取partiton的优点逐渐体现,效率高;
4、sun公司jdk中排序算法与所见到的快速演算法原理几乎一样,递归的使用需要技巧才能体现更多的优势,jdk中递归的使用很值得学习啊(虽然原来也知道值得学习,现在更知道了,呵呵);
5、经过初步测试,自己实现sort(int [], String[]);方法比集合方法Collections.sort(ArrayList,new Comparator());效率要高不少,个人认为原因在于数组排序时的优势导致这样的结果;
这次比较细致的测试所获不小,纠正了以前的一些认识偏差,sort(int [], String[])方法有一定实用价值,尤其你要排序的集合(尤其有数字,字符串混合)达到万、10万的级别时候,效率高。
结论如下:
1、以前给出的QuickSort中三个方法,第一个和第二个效率相当,第三个方法thirdsort()效率比较差,以前认为它在查找轴/分段元素时有一定优点,可测试发现比较笨拙,笨拙查找方式加上递归,导致效率低下;
2、int型数组大小小与等于30万时,快速演算法中public static void sort(int[] number, int left, int right)方法和public static void provesortfirst(int[] number, int left, int right)方法与Arrays.sort()方法效率相当;
3、数组大小大于等于30万时,Arrays.sort()的分段选取partiton的优点逐渐体现,效率高;
4、sun公司jdk中排序算法与所见到的快速演算法原理几乎一样,递归的使用需要技巧才能体现更多的优势,jdk中递归的使用很值得学习啊(虽然原来也知道值得学习,现在更知道了,呵呵);
5、经过初步测试,自己实现sort(int [], String[]);方法比集合方法Collections.sort(ArrayList,new Comparator());效率要高不少,个人认为原因在于数组排序时的优势导致这样的结果;
这次比较细致的测试所获不小,纠正了以前的一些认识偏差,sort(int [], String[])方法有一定实用价值,尤其你要排序的集合(尤其有数字,字符串混合)达到万、10万的级别时候,效率高。
结论如下:
1、以前给出的QuickSort中三个方法,第一个和第二个效率相当,第三个方法thirdsort()效率比较差,以前认为它在查找轴/分段元素时有一定优点,可测试发现比较笨拙,笨拙查找方式加上递归,导致效率低下;
2、int型数组大小小与等于30万时,快速演算法中public static void sort(int[] number, int left, int right)方法和public static void provesortfirst(int[] number, int left, int right)方法与Arrays.sort()方法效率相当;
3、数组大小大于等于30万时,Arrays.sort()的分段选取partiton的优点逐渐体现,效率高;
4、sun公司jdk中排序算法与所见到的快速演算法原理几乎一样,递归的使用需要技巧才能体现更多的优势,jdk中递归的使用很值得学习啊(虽然原来也知道值得学习,现在更知道了,呵呵);
5、经过初步测试,自己实现sort(int [], String[]);方法比集合方法Collections.sort(ArrayList,new Comparator());效率要高不少,个人认为原因在于数组排序时的优势导致这样的结果;
这次比较细致的测试所获不小,纠正了以前的一些认识偏差,sort(int [], String[])方法有一定实用价值,尤其你要排序的集合(尤其有数字,字符串混合)达到万、10万的级别时候,效率高。
