// 排序算法的实现 publicstaticvoidsort(Comparable[] a){ int N = a.length; aux = new Comparable[N]; for (int sz = 1; sz < N; sz = 2*sz) // sz 子数组大小 for (int lo = 0; lo + sz < N; lo += 2*sz) merge(a, lo, lo + sz -1, Math.min(lo+2*sz-1, N-1)); }
privatestaticintpartition(Comparable[] a, int lo, int hi){ // 选取标志位数值,这里选取左起第0位 Comparable flag = a[lo]; // 定义左右指针,分别是标志位和右上限+1,两边都预留了1位冗余,因为下面要做前置自增减运算 int i = lo, j = hi + 1; while (true) { // 左指针自增,当元素值大于标志时停止 // 这里统一采用前置自增减,为的是先计算后使用,保证比较的数值和后面交换的索引是及时对应的 while (less(a[++i], flag)) // 检测左指针是否到达右上限,若到达也停止 if (i == hi) break; // 右指针自减,当元素值小于标志时停止 while (less(flag, a[--j])) // 检测右指针是否到达左下限,若到达也停止 if (j == lo) break; // 检测左右指针是否相交,若相交退出循环 if (i >= j) break; // 交换左右指针所在的元素,即可保证左边区域一直比标志小,右边区域一直比标志大 exch(a, i, j); } // 循环结束时j所指元素肯定是小于标志的,所以交换它俩,保证标志左侧元素始终小于标志 // 如果标志位定的右起第0位hi 这里就要交换i exch(a, lo, j); // 返回最终标志所在索引,即正确的位置,也就是切分点 return j; }
privatestaticvoidsort(Comparable[] a, int lo, int hi){ if (hi <= lo) return; // 递归出口,上下限交接时退出 int lt = lo, i = lo + 1, gt = hi; Comparable flag = a[lo]; while (i <= gt) { if (less(a[i], flag)) exch(a, lt++, i++); elseif (less(flag, a[i])) exch(a, gt--, i); else i++; }
publicclassHeap{ // 排序算法的实现 publicstaticvoidsort(Comparable[] a){ int N = a.length; // 构造堆 for (int k = N/2; k >= 1; k--) { sink(a, k, N); } // 排序 while (N > 1) { exch(a, N--, 1); sink(a, 1, N); } }
privatestaticvoidsink(Comparable[] a, int k, int N){ while (k <= N/2) { int j = 2*k; if (j < N && less(a, j, j+1)) j++; if (less(a, k, j)) { exch(a, k, j); k = j; } else { break; } } }
// 比较前者是否小于后者 privatestaticbooleanless(Comparable[] a, int i, int j){ i--; j--; // 构造二叉堆的数组是基1的,这里要减去(对a[0]至a[N-1]操作) return a[i].compareTo(a[j]) < 0; }
// 交换数组中两个位置的元素 privatestaticvoidexch(Comparable[] a, int i, int j){ i--; j--; // 构造二叉堆的数组是基1的,这里要减去(对a[0]至a[N-1]操作) Comparable t = a[i]; a[i] = a[j]; a[j] = t; }
// 打印数组 privatestaticvoidshow(Comparable[] a){ for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } System.out.println(); }