/// <summary> /// quicksort the subarray a[lo .. hi] using 3-way partitioning /// </summary> /// <param name="a"></param> /// <param name="lo"></param> /// <param name="hi"></param> private static void sort(T[] a, int lo, int hi) { if (hi <= lo) { return; } int lt = lo, gt = hi; T v = a[lo]; int i = lo; while (i <= gt) { int cmp = a[i].CompareTo(v); if (cmp < 0) { SortingHelper <T> .exch(a, lt ++, i ++); } else if (cmp > 0) { SortingHelper <T> .exch(a, i, gt --); } else { i++; } } // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi]. sort(a, lo, lt - 1); sort(a, gt + 1, hi); Debug.Assert(SortingHelper <T> .isSorted(a, lo, hi)); }
/** * Rearranges the array in ascending order, using the natural order. * @param a the array to be sorted */ public static void Sort(T[] a) { int n = a.Length; // 3x+1 increment sequence: 1, 4, 13, 40, 121, 364, 1093, ... int h = 1; while (h < n / 3) { h = 3 * h + 1; } while (h >= 1) { // h-sort the array for (int i = h; i < n; i++) { for (int j = i; j >= h && SortingHelper <T> .less(a[j], a[j - h]); j -= h) { SortingHelper <T> .exch(a, j, j - h); } } Debug.Assert(isHSorted(a, h)); h /= 3; } Debug.Assert(SortingHelper <T> .isSorted(a)); }
private const int CUTOFF = 7; // cutoff to insertion sort // This class should not be instantiated. private static void merge(T[] src, T[] dst, int lo, int mid, int hi) { // precondition: src[lo .. mid] and src[mid+1 .. hi] are sorted subarrays Debug.Assert(SortingHelper <T> .isSorted(src, lo, mid)); Debug.Assert(SortingHelper <T> .isSorted(src, mid + 1, hi)); int i = lo, j = mid + 1; for (int k = lo; k <= hi; k++) { if (i > mid) { dst[k] = src[j++]; } else if (j > hi) { dst[k] = src[i++]; } else if (SortingHelper <T> .less(src[j], src[i])) { dst[k] = src[j++]; // to ensure stability } else { dst[k] = src[i++]; } } // postcondition: dst[lo .. hi] is sorted subarray Debug.Assert(SortingHelper <T> .isSorted(dst, lo, hi)); }
private static void merge(T[] a, T[] aux, int lo, int mid, int hi) { // copy to aux[] for (int k = lo; k <= hi; k++) { aux[k] = a[k]; } // merge back to a[] int i = lo, j = mid + 1; for (int k = lo; k <= hi; k++) { if (i > mid) { a[k] = aux[j++]; // this copying is unneccessary } else if (j > hi) { a[k] = aux[i++]; } else if (SortingHelper <T> .less(aux[j], aux[i])) { a[k] = aux[j++]; } else { a[k] = aux[i++]; } } }
/// <summary> /// Provides a static method for sorting an array using an optimized binary insertion sort with half exchanges. /// The sorting algorithm is stable and uses O(1) extra memory. /// /// This implementation makes ~ n lg n compares for any array of length n. /// However, in the worst case, the running time is quadratic because the number of array accesses can be proportional to n^2 (e.g, if the array is reverse sorted). /// As such, it is not suitable for sorting large arrays(unless the number of inversions is small). /// </summary> /// <param name="a">array to sort</param> public static void Sort(T[] a) { int n = a.Length; for (int i = 1; i < n; i++) { // binary search to determine index j at which to insert a[i] var v = a[i]; int lo = 0, hi = i; while (lo < hi) { int mid = lo + (hi - lo) / 2; if (SortingHelper <T> .less(v, a[mid])) { hi = mid; } else { lo = mid + 1; } } // insetion sort with "half exchanges" // (insert a[i] at index j and shift a[j], ..., a[i-1] to right) for (int j = i; j > lo; --j) { a[j] = a[j - 1]; } a[lo] = v; } Debug.Assert(SortingHelper <T> .isSorted(a)); }
/** * Rearranges the array in ascending order, using the natural order. * @param a the array to be sorted */ public static void Sort(T[] a) { var aux = new T[a.Length]; sort(a, aux, 0, a.Length - 1); Debug.Assert(SortingHelper <T> .isSorted(a)); }
private static void sort(T[] src, T[] dst, int lo, int hi) { // if (hi <= lo) return; if (hi <= lo + CUTOFF) { insertionSort(dst, lo, hi); return; } int mid = lo + (hi - lo) / 2; sort(dst, src, lo, mid); sort(dst, src, mid + 1, hi); // if (!less(src[mid+1], src[mid])) { // for (int i = lo; i <= hi; i++) dst[i] = src[i]; // return; // } // using System.arraycopy() is a bit faster than the above loop if (!SortingHelper <T> .less(src[mid + 1], src[mid])) { Array.Copy(src, lo, dst, lo, hi - lo + 1); return; } merge(src, dst, lo, mid, hi); }
/// <summary> /// Rearranges the array in ascending order, using the natural order. /// </summary> /// <param name="a">the array to be sorted</param> public static void Sort(T[] a) { StdRandom.shuffle(a); sort(a, 0, a.Length - 1); Debug.Assert(SortingHelper <T> .isSorted(a)); }
public static void shuffle <T>(T[] objarr) where T : IComparable <T> { int N = objarr.Length; for (int i = 0; i < N; i++) { SortingHelper <T> .exch(objarr, i, i + uniform(N - i)); } }
public static void shuffle(int[] iarr) { int N = iarr.Length; for (int i = 0; i < N; i++) { SortingHelper <int> .exch(iarr, i, i + uniform(N - i)); } }
// sort from a[lo] to a[hi] using insertion sort private static void insertionSort(T[] a, int lo, int hi) { for (int i = lo; i <= hi; i++) { for (int j = i; j > lo && SortingHelper <T> .less(a[j], a[j - 1]); j--) { SortingHelper <T> .exch(a, j, j - 1); } } }
// is the array h-sorted? private static bool isHSorted(T[] a, int h) { for (int i = h; i < a.Length; i++) { if (SortingHelper <T> .less(a[i], a[i - h])) { return(false); } } return(true); }
/// <summary> /// Rearranges the subarray a[lo..hi) in ascending order, using a comparator. /// </summary> /// <param name="a">the array</param> /// <param name="lo">left endpoint (inclusive)</param> /// <param name="hi">right endpoint (exclusive)</param> /// <param name="comparator">the comparator specifying the order</param> public static void Sort(T[] a, int lo, int hi, IComparer <T> comparator) { for (int i = lo; i < hi; i++) { for (int j = i; j > lo && SortingHelper <T> .less(a[j], a[j - 1], comparator); j--) { SortingHelper <T> .exch(a, j, j - 1); } } Debug.Assert(SortingHelper <T> .isSorted(a, lo, hi, comparator)); }
// quicksort the subarray from a[lo] to a[hi] private static void sort(T[] a, int lo, int hi) { if (hi <= lo) { return; } int j = partition(a, lo, hi); sort(a, lo, j - 1); sort(a, j + 1, hi); Debug.Assert(SortingHelper <T> .isSorted(a, lo, hi)); }
/// <summary> /// Rearranges the array in ascending order, using a comparator. /// </summary> /// <param name="a">the array</param> /// <param name="comparator">the comparator specifying the order</param> public static void Sort(T[] a, IComparer <T> comparator) { int n = a.Length; for (int i = 0; i < n; i++) { for (int j = i; j > 0 && SortingHelper <T> .less(a[j], a[j - 1], comparator); j--) { SortingHelper <T> .exch(a, j, j - 1); } Debug.Assert(SortingHelper <T> .isSorted(a, 0, i, comparator)); } Debug.Assert(SortingHelper <T> .isSorted(a, comparator)); }
/// <summary> /// Rearranges the array in ascending order, using the natural order. /// </summary> /// <param name="a">the array to be sorted</param> public static void Sort(T[] a) { int n = a.Length; var aux = new T[n]; for (int len = 1; len < n; len *= 2) { for (int lo = 0; lo < n - len; lo += len + len) { int mid = lo + len - 1; int hi = Math.Min(lo + len + len - 1, n - 1); merge(a, aux, lo, mid, hi); } } Debug.Assert(SortingHelper <T> .isSorted(a)); }
/** * Rearranges the array in ascending order, using the natural order. * @param a the array to be sorted */ public static void Sort(T[] a) { int n = a.Length; for (int i = 0; i < n; i++) { int min = i; for (int j = i + 1; j < n; j++) { if (SortingHelper <T> .less(a[j], a[min])) { min = j; } } SortingHelper <T> .exch(a, i, min); Debug.Assert(SortingHelper <T> .isSorted(a, 0, i)); } Debug.Assert(SortingHelper <T> .isSorted(a)); }
// return a permutation that gives the elements in a[] in ascending order // do not change the original array a[] /** * Returns a permutation that gives the elements in the array in ascending order. * @param a the array * @return a permutation {@code p[]} such that {@code a[p[0]]}, {@code a[p[1]]}, * ..., {@code a[p[n-1]]} are in ascending order */ //public static int[] IndexSort(IComparable<T>[] a) public static int[] IndexSort(T[] a) { int n = a.Length; int[] index = new int[n]; for (int i = 0; i < n; i++) { index[i] = i; } for (int i = 0; i < n; i++) { for (int j = i; j > 0 && SortingHelper <T> .less(a[index[j]], a[index[j - 1]]); j--) { SortingHelper <int> .exch(index, j, j - 1); } } return(index); }
// partition the subarray a[lo..hi] so that a[lo..j-1] <= a[j] <= a[j+1..hi] // and return the index j. private static int partition(T[] a, int lo, int hi) { int i = lo; int j = hi + 1; T v = a[lo]; while (true) { // find item on lo to swap while (SortingHelper <T> .less(a[++i], v)) { if (i == hi) { break; } } // find item on hi to swap while (SortingHelper <T> .less(v, a[--j])) { if (j == lo) { break; // redundant since a[lo] acts as sentinel } } // check if pointers cross if (i >= j) { break; } SortingHelper <T> .exch(a, i, j); } // put partitioning item v at a[j] SortingHelper <T> .exch(a, lo, j); // now, a[lo .. j-1] <= a[j] <= a[j+1 .. hi] return(j); }
// stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi] private static void merge(T[] a, T[] aux, int lo, int mid, int hi) { // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays Debug.Assert(SortingHelper <T> .isSorted(a, lo, mid)); Debug.Assert(SortingHelper <T> .isSorted(a, mid + 1, hi)); // copy to aux[] for (int k = lo; k <= hi; k++) { aux[k] = a[k]; } // merge back to a[] int i = lo, j = mid + 1; for (int k = lo; k <= hi; k++) { if (i > mid) { a[k] = aux[j++]; } else if (j > hi) { a[k] = aux[i++]; } else if (SortingHelper <T> .less(aux[j], aux[i])) { a[k] = aux[j++]; } else { a[k] = aux[i++]; } } // postcondition: a[lo .. hi] is sorted Debug.Assert(SortingHelper <T> .isSorted(a, lo, hi)); }
/// <summary> /// Rearranges the array in ascending order, using the natural order. /// </summary> /// <param name="a">the array to be sorted</param> public static void Sort(T[] a) { int n = a.Length; // put smallest element in position to serve as sentinel int exchanges = 0; for (int i = n - 1; i > 0; i--) { if (SortingHelper <T> .less(a[i], a[i - 1])) { SortingHelper <T> .exch(a, i, i - 1); exchanges++; } } if (exchanges == 0) { return; } // insertion sort with half-exchanges for (int i = 2; i < n; i++) { var v = a[i]; int j = i; while (SortingHelper <T> .less(v, a[j - 1])) { a[j] = a[j - 1]; j--; } a[j] = v; } Debug.Assert(SortingHelper <T> .isSorted(a)); }
/// <summary> /// Searches <paramref name="i"/> within <paramref name="iarr"/> integer array. /// </summary> /// <param name="i">value</param> /// <param name="iarr">array</param> /// <returns>array index if element found, otherwise -1.</returns> public static int Rank(int i, int[] iarr) { Debug.Assert(SortingHelper <int> .isSorted(iarr)); return(IndexOf(iarr, i)); }
private static void sort(T[] a, int lo, int hi) { int n = hi - lo + 1; // cutoff to insertion sort if (n <= INSERTION_SORT_CUTOFF) { insertionSort(a, lo, hi); return; } // use median-of-3 as partitioning element else if (n <= MEDIAN_OF_3_CUTOFF) { int m = median3(a, lo, lo + n / 2, hi); SortingHelper <T> .exch(a, m, lo); } // use Tukey ninther as partitioning element else { int eps = n / 8; int mid = lo + n / 2; int m1 = median3(a, lo, lo + eps, lo + eps + eps); int m2 = median3(a, mid - eps, mid, mid + eps); int m3 = median3(a, hi - eps - eps, hi - eps, hi); int ninther = median3(a, m1, m2, m3); SortingHelper <T> .exch(a, ninther, lo); } // Bentley-McIlroy 3-way partitioning int i = lo, j = hi + 1; int p = lo, q = hi + 1; T v = a[lo]; while (true) { while (SortingHelper <T> .less(a[++i], v)) { if (i == hi) { break; } } while (SortingHelper <T> .less(v, a[--j])) { if (j == lo) { break; } } // pointers cross if (i == j && SortingHelper <T> .eq(a[i], v)) { SortingHelper <T> .exch(a, ++p, i); } if (i >= j) { break; } SortingHelper <T> .exch(a, i, j); if (SortingHelper <T> .eq(a[i], v)) { SortingHelper <T> .exch(a, ++p, i); } if (SortingHelper <T> .eq(a[j], v)) { SortingHelper <T> .exch(a, --q, j); } } i = j + 1; for (int k = lo; k <= p; k++) { SortingHelper <T> .exch(a, k, j --); } for (int k = hi; k >= q; k--) { SortingHelper <T> .exch(a, k, i ++); } sort(a, lo, j); sort(a, i, hi); }
// return the index of the median element among a[i], a[j], and a[k] private static int median3(T[] a, int i, int j, int k) { return(SortingHelper <T> .less(a[i], a[j]) ? (SortingHelper <T> .less(a[j], a[k]) ? j : SortingHelper <T> .less(a[i], a[k]) ? k : i) : (SortingHelper <T> .less(a[k], a[j]) ? j : SortingHelper <T> .less(a[k], a[i]) ? k : i)); }
/// <summary> /// Rearranges the array in ascending order, using the natural order. /// </summary> /// <param name="a">the array to be sorted</param> public static void Sort(T[] a) { T[] aux = (T[])a.Clone(); sort(aux, a, 0, a.Length - 1); Debug.Assert(SortingHelper <T> .isSorted(a)); }