private static void Merge(IComparable[] src, IComparable[] dst, int lo, int mid, int hi) { // precondition: src[lo .. mid] and src[mid+1 .. hi] are sorted subarrays Debug.Assert(OrderHelper.IsSorted(src, lo, mid)); Debug.Assert(OrderHelper.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 (OrderHelper.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(OrderHelper.IsSorted(dst, lo, hi)); }
/// <summary> /// Rearranges the array in ascending order, using the natural order.</summary> /// <param name="a">a the array to be sorted</param> /// public static void Sort(IComparable[] 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 && OrderHelper.Less(a[j], a[j - h]); j -= h) { OrderHelper.Exch(a, j, j - h); } } Debug.Assert(IsHsorted(a, h)); h /= 3; } Debug.Assert(OrderHelper.IsSorted(a)); }
/// <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(IComparable[] a) { int N = a.Length; for (int i = 1; i < N; i++) { // binary search to determine index j at which to insert a[i] IComparable v = a[i]; int lo = 0, hi = i; while (lo < hi) { int mid = lo + (hi - lo) / 2; if (OrderHelper.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(OrderHelper.IsSorted(a)); }
/// <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(IComparable[] 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 (OrderHelper.Less(a[i], a[i - 1])) { OrderHelper.Exch(a, i, i - 1); exchanges++; } } if (exchanges == 0) return; // insertion sort with half-exchanges for (int i = 2; i < N; i++) { IComparable v = a[i]; int j = i; while (OrderHelper.Less(v, a[j - 1])) { a[j] = a[j - 1]; j--; } a[j] = v; } Debug.Assert(OrderHelper.IsSorted(a)); }
// stably merge a[lo..mid] with a[mid+1..hi] using aux[lo..hi] private static void merge(IComparable[] a, IComparable[] 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 (OrderHelper.Less(aux[j], aux[i])) { a[k] = aux[j++]; } else { a[k] = aux[i++]; } } }
/*************************************************************************** * Index mergesort. ***************************************************************************/ // stably merge a[lo .. mid] with a[mid+1 .. hi] using aux[lo .. hi] private static void merge(IComparable[] a, int[] index, int[] aux, int lo, int mid, int hi) { // copy to aux[] for (int k = lo; k <= hi; k++) { aux[k] = index[k]; } // merge back to a[] int i = lo, j = mid + 1; for (int k = lo; k <= hi; k++) { if (i > mid) { index[k] = aux[j++]; } else if (j > hi) { index[k] = aux[i++]; } else if (OrderHelper.Less(a[aux[j]], a[aux[i]])) { index[k] = aux[j++]; } else { index[k] = aux[i++]; } } }
/// <summary> /// Rearranges the subarray a[lo..hi] in ascending order, using a generic comparator.</summary> /// <param name="a">a the array</param> /// <param name="lo">lo left endpoint</param> /// <param name="hi">hi right endpoint</param> /// <param name="comparator">comparator the comparator specifying the order</param> /// public static void Sort <T>(T[] a, int lo, int hi, Comparer <T> comparator) { for (int i = lo; i <= hi; i++) { for (int j = i; j > lo && OrderHelper.Less(a[j], a[j - 1], comparator); j--) { OrderHelper.Exch <T>(a, j, j - 1); } } Debug.Assert(OrderHelper.IsSorted(a, lo, hi, comparator)); }
/*************************************************************************** * Check if array is H sorted - useful for debugging. ***************************************************************************/ // is the array h-sorted? private static bool IsHsorted(IComparable[] a, int h) { for (int i = h; i < a.Length; i++) { if (OrderHelper.Less(a[i], a[i - h])) { return(false); } } return(true); }
/// <summary> /// Rearranges the subarray a[lo..hi] in ascending order, using the natural order.</summary> /// <param name="a">a the array to be sorted</param> /// <param name="lo">lo left endpoint</param> /// <param name="hi">hi right endpoint</param> /// public static void Sort(IComparable[] a, int lo, int hi) { for (int i = lo; i <= hi; i++) { for (int j = i; j > lo && OrderHelper.Less(a[j], a[j - 1]); j--) { OrderHelper.Exch(a, j, j - 1); } } Debug.Assert(OrderHelper.IsSorted(a, lo, hi)); }
/// <summary> /// Rearranges the array in ascending order, using the natural order.</summary> /// <param name="a">a the array to be sorted</param> /// public static void Sort(IComparable[] a) { int N = a.Length; for (int i = 0; i < N; i++) { for (int j = i; j > 0 && OrderHelper.Less(a[j], a[j - 1]); j--) { OrderHelper.Exch(a, j, j - 1); } Debug.Assert(OrderHelper.IsSorted(a, 0, i)); } Debug.Assert(OrderHelper.IsSorted(a)); }
/// <summary> /// Rearranges the array in ascending order, using a comparator.</summary> /// <param name="a">a the array</param> /// <param name="comparator">comparator the comparator specifying the order</param> /// public static void Sort(object[] a, System.Collections.Comparer comparator) { int N = a.Length; for (int i = 0; i < N; i++) { for (int j = i; j > 0 && OrderHelper.Less(a[j], a[j - 1], comparator); j--) { OrderHelper.Exch(a, j, j - 1); } Debug.Assert(OrderHelper.IsSorted(a, 0, i, comparator)); } Debug.Assert(OrderHelper.IsSorted(a, comparator)); }
/// <summary> /// Rearranges the array in ascending order, using a comparator.</summary> /// <param name="a">a the array</param> /// <param name="c">c the comparator specifying the order</param> /// public static void Sort <T>(T[] a, Comparer <T> c) { int N = a.Length; for (int i = 0; i < N; i++) { int min = i; for (int j = i + 1; j < N; j++) { if (OrderHelper.Less <T>(a[j], a[min], c)) { min = j; } } OrderHelper.Exch(a, i, min); Debug.Assert(OrderHelper.IsSorted(a, 0, i, c)); } Debug.Assert(OrderHelper.IsSorted(a, c)); }
/// <summary> /// Rearranges the array in ascending order, using the natural order.</summary> /// <param name="a">a the array to be sorted</param> /// public static void Sort(IComparable[] a) { int N = a.Length; for (int i = 0; i < N; i++) { int min = i; for (int j = i + 1; j < N; j++) { if (OrderHelper.Less(a[j], a[min])) { min = j; } } OrderHelper.Exch(a, i, min); Debug.Assert(OrderHelper.IsSorted(a, 0, i)); } Debug.Assert(OrderHelper.IsSorted(a)); }
private static void Sort(IComparable[] src, IComparable[] dst, int lo, int hi) { // if (hi <= lo) return; if (hi <= lo + CUTOFF) { Insertion.Sort(dst, lo, hi); return; } int mid = lo + (hi - lo) / 2; Sort(dst, src, lo, mid); Sort(dst, src, mid + 1, hi); if (!OrderHelper.Less(src[mid + 1], src[mid])) { Array.Copy(src, lo, dst, lo, hi - lo + 1); return; } Merge(src, dst, lo, mid, hi); }
/// <summary> /// Returns a permutation that gives the elements in the array in ascending order, /// while not changing the original array a[]</summary> /// <param name="a">a the array</param> /// <returns>a permutation <c>p[]</c> such that <c>a[p[0]]</c>, <c>a[p[1]]</c>, /// ..., <c>a[p[N-1]]</c> are in ascending order</returns> /// public static int[] IndexSort(int[] 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 && OrderHelper.Less(a[index[j]], a[index[j - 1]]); j--) { OrderHelper.Exch(index, j, j - 1); } } return(index); }
private static void Sort <T>(T[] src, T[] dst, int lo, int hi, Comparer <T> comparator) { // if (hi <= lo) return; if (hi <= lo + CUTOFF) { Insertion.Sort(dst, lo, hi, comparator); return; } int mid = lo + (hi - lo) / 2; Sort(dst, src, lo, mid, comparator); Sort(dst, src, mid + 1, hi, comparator); if (!OrderHelper.Less(src[mid + 1], src[mid], comparator)) { Array.Copy(src, lo, dst, lo, hi - lo + 1); return; } Merge(src, dst, lo, mid, hi, comparator); }
// 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(IComparable[] a, int lo, int hi) { int i = lo; int j = hi + 1; IComparable v = a[lo]; while (true) { // find item on lo to swap while (OrderHelper.Less(a[++i], v)) { if (i == hi) { break; } } // find item on hi to swap while (OrderHelper.Less(v, a[--j])) { if (j == lo) { break; // redundant since a[lo] acts as sentinel } } // check if pointers cross if (i >= j) { break; } OrderHelper.Exch(a, i, j); } // put partitioning item v at a[j] OrderHelper.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(IComparable[] a, IComparable[] aux, int lo, int mid, int hi) { // precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays Debug.Assert(OrderHelper.IsSorted(a, lo, mid)); Debug.Assert(OrderHelper.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 (OrderHelper.Less(aux[j], aux[i])) { a[k] = aux[j++]; } else { a[k] = aux[i++]; } } // postcondition: a[lo .. hi] is sorted Debug.Assert(OrderHelper.IsSorted(a, lo, hi)); }
// return the index of the median element among a[i], a[j], and a[k] private static int median3(IComparable[] a, int i, int j, int k) { return(OrderHelper.Less(a[i], a[j]) ? (OrderHelper.Less(a[j], a[k]) ? j : OrderHelper.Less(a[i], a[k]) ? k : i) : (OrderHelper.Less(a[k], a[j]) ? j : OrderHelper.Less(a[k], a[i]) ? k : i)); }
private static void Sort(IComparable[] a, int lo, int hi) { int N = hi - lo + 1; // cutoff to insertion sort if (N <= CUTOFF) { Insertion.Sort(a, lo, hi); return; } // use median-of-3 as partitioning element else if (N <= 40) { int m = median3(a, lo, lo + N / 2, hi); OrderHelper.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); OrderHelper.Exch(a, ninther, lo); } // Bentley-McIlroy 3-way partitioning int i = lo, j = hi + 1; int p = lo, q = hi + 1; IComparable v = a[lo]; while (true) { while (OrderHelper.Less(a[++i], v)) { if (i == hi) { break; } } while (OrderHelper.Less(v, a[--j])) { if (j == lo) { break; } } // pointers cross if (i == j && OrderHelper.Eq(a[i], v)) { OrderHelper.Exch(a, ++p, i); } if (i >= j) { break; } OrderHelper.Exch(a, i, j); if (OrderHelper.Eq(a[i], v)) { OrderHelper.Exch(a, ++p, i); } if (OrderHelper.Eq(a[j], v)) { OrderHelper.Exch(a, --q, j); } } i = j + 1; for (int k = lo; k <= p; k++) { OrderHelper.Exch(a, k, j--); } for (int k = hi; k >= q; k--) { OrderHelper.Exch(a, k, i++); } Sort(a, lo, j); Sort(a, i, hi); }