/// <summary> /// Sorts the matrix rows into ascending order, according to the <i>natural ordering</i> of the matrix values in the given column. /// The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa. /// To sort ranges use sub-ranging viewsd To sort columns by rows, use dice viewsd To sort descending, use flip views ... /// <p> /// <b>Example:</b> /// <table border="1" cellspacing="0"> /// <tr nowrap> /// <td valign="top"><i>4 x 2 matrix: <br> /// 7, 6<br> /// 5, 4<br> /// 3, 2<br> /// 1, 0 <br> /// </i></td> /// <td align="left" valign="top"> /// <p><i>column = 0;<br> /// view = quickSort(matrix,column);<br> /// Console.WriteLine(view); </i><i><br> /// ==> </i></p> /// </td> /// <td valign="top"> /// <p><i>4 x 2 matrix:<br> /// 1, 0<br> /// 3, 2<br> /// 5, 4<br> /// 7, 6</i><br> /// The matrix IS NOT SORTED.<br> /// The new VIEW IS SORTED.</p> /// </td> /// </tr> /// </table> /// /// @param matrix the matrix to be sorted. /// @param column the index of the column inducing the order. /// @return a new matrix view having rows sorted by the given column. /// <b>Note that the original matrix is left unaffected.</b> /// @throws IndexOutOfRangeException if <i>column %lt; 0 || column >= matrix.Columns</i>. /// </summary> public ObjectMatrix2D sort(ObjectMatrix2D matrix, int column) { if (column < 0 || column >= matrix.Columns) { throw new IndexOutOfRangeException("column=" + column + ", matrix=" + Formatter.Shape(matrix)); } int[] rowIndexes = new int[matrix.Rows]; // row indexes to reorder instead of matrix itself for (int i = rowIndexes.Length; --i >= 0;) { rowIndexes[i] = i; } ObjectMatrix1D col = matrix.ViewColumn(column); IntComparator comp = new IntComparator((a, b) => { IComparable av = (IComparable)(col[a]); IComparable bv = (IComparable)(col[b]); int r = av.CompareTo(bv); return(r < 0 ? -1 : (r > 0 ? 1 : 0)); }); RunSort(rowIndexes, 0, rowIndexes.Length, comp); // view the matrix according to the reordered row indexes // take all columns in the original order return(matrix.ViewSelection(rowIndexes, null)); }
/// <summary> /// Sorts the matrix slices into ascending order, according to the <i>natural ordering</i> of the matrix values in the given <i>[row,column]</i> position. /// The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa. /// To sort ranges use sub-ranging viewsd To sort by other dimensions, use dice viewsd To sort descending, use flip views ... /// <p> /// The algorithm compares two 2-d slices at a time, determinining whether one is smaller, equal or larger than the other. /// Comparison is based on the cell <i>[row,column]</i> within a slice. /// Let <i>A</i> and <i>B</i> be two 2-d slicesd Then we have the following rules /// <ul> /// <li><i>A < B iff A.Get(row,column) < B.Get(row,column)</i> /// <li><i>A == B iff A.Get(row,column) == B.Get(row,column)</i> /// <li><i>A > B iff A.Get(row,column) > B.Get(row,column)</i> /// </ul> /// /// @param matrix the matrix to be sorted. /// @param row the index of the row inducing the order. /// @param column the index of the column inducing the order. /// @return a new matrix view having slices sorted by the values of the slice view <i>matrix.viewRow(row).viewColumn(column)</i>. /// <b>Note that the original matrix is left unaffected.</b> /// @throws IndexOutOfRangeException if <i>row %lt; 0 || row >= matrix.Rows || column %lt; 0 || column >= matrix.Columns</i>. /// </summary> public ObjectMatrix3D sort(ObjectMatrix3D matrix, int row, int column) { if (row < 0 || row >= matrix.Rows) { throw new IndexOutOfRangeException("row=" + row + ", matrix=" + Formatter.Shape(matrix)); } if (column < 0 || column >= matrix.Columns) { throw new IndexOutOfRangeException("column=" + column + ", matrix=" + Formatter.Shape(matrix)); } int[] sliceIndexes = new int[matrix.Slices]; // indexes to reorder instead of matrix itself for (int i = sliceIndexes.Length; --i >= 0;) { sliceIndexes[i] = i; } ObjectMatrix1D sliceView = matrix.ViewRow(row).ViewColumn(column); IntComparator comp = new IntComparator((a, b) => { IComparable av = (IComparable)(sliceView[a]); IComparable bv = (IComparable)(sliceView[b]); int r = av.CompareTo(bv); return(r < 0 ? -1 : (r > 0 ? 1 : 0)); }); RunSort(sliceIndexes, 0, sliceIndexes.Length, comp); // view the matrix according to the reordered slice indexes // take all rows and columns in the original order return(matrix.ViewSelection(sliceIndexes, null, null)); }
public void ExistenceOfIntTreeTest() { InterfaceOfComparator <int> comparator = new IntComparator(); BinaryTree <int> tree = new BinaryTree <int>(comparator); Assert.IsTrue(tree.IsEmpty()); }
public void InsertToIntTreeTest() { InterfaceOfComparator <int> comparator = new IntComparator(); BinaryTree <int> tree = new BinaryTree <int>(comparator); tree.InsertElement(1); Assert.IsFalse(tree.IsEmpty()); }
public void IsElementExistInIntTreeTest() { InterfaceOfComparator <int> comparator = new IntComparator(); BinaryTree <int> tree = new BinaryTree <int>(comparator); tree.InsertElement(1); Assert.IsTrue(tree.IsElementExist(1)); }
/// <summary> /// Returns the index of the median of the three indexed integers. /// </summary> private static int med3(int a, int b, int c, IntComparator comp) { int ab = comp(a, b); int ac = comp(a, c); int bc = comp(b, c); return(ab < 0 ? (bc < 0 ? b : ac < 0 ? c : a) : (bc > 0 ? b : ac > 0 ? c : a)); }
/// <summary> /// Sorts the receiver according /// to the order induced by the specified comparatord All elements in the /// range must be <i>mutually comparable</i> by the specified comparator /// (that is, <i>c.CompareTo(e1, e2)</i> must not throw a /// <i>ClassCastException</i> for any elements <i>e1</i> and /// <i>e2</i> in the range).<p> /// /// The sorting algorithm is a tuned quicksort, /// adapted from Jon Ld Bentley and Md Douglas McIlroy's "Engineering a /// Sort Function", Software-Practice and Experience, Vold 23(11) /// Pd 1249-1265 (November 1993)d This algorithm offers n*log(n) /// performance on many data sets that cause other quicksorts to degrade to /// quadratic performance. /// /// <summary> /// <param name="from">the index of the first element (inclusive) to be</param> /// sorted. /// <param name="to">the index of the last element (inclusive) to be sorted.</param> /// <param name="c">the comparator to determine the order of the receiver.</param> /// <exception cref="ClassCastException">if the array contains elements that are not </exception> /// <i>mutually comparable</i> using the specified comparator. /// <exception cref="ArgumentException">if <i>fromIndex > toIndex</i> </exception> /// <exception cref="ArrayIndexOutOfRangeException">if <i>fromIndex < 0</i> or </exception> /// <i>toIndex > a.Length</i> /// <see cref="Comparator"></see> /// <exception cref="IndexOutOfRangeException">index is out of range (<i>_size()>0 && (from<0 || from>to || to>=_size())</i>). </exception> public virtual void QuickSortFromTo(int from, int to, IntComparator c) { int mySize = Size; CheckRangeFromTo(from, to, mySize); int[] myElements = GetElements(); Cern.Colt.Sorting.QuickSort(myElements, from, to + 1, c); SetElements(myElements); SetSizeRaw(mySize); }
/// <summary> /// Same as <see cref="Cern.Colt.Partitioning.Partition(int[], int, int, int[], int, int, int[])"/> /// except that it <i>synchronously</i> partitions the rows of the given matrix by the values of the given matrix column; /// This is essentially the same as partitioning a list of composite objects by some instance variable; /// In other words, two entire rows of the matrix are swapped, whenever two column values indicate so. /// <p> /// Let's say, a "row" is an "object" (tuple, d-dimensional point). /// A "column" is the list of "object" values of a given variable (field, dimension). /// A "matrix" is a list of "objects" (tuples, points). /// <p> /// Now, rows (objects, tuples) are partially sorted according to their values in one given variable (dimension). /// Two entire rows of the matrix are swapped, whenever two column values indicate so. /// <p> /// Note that arguments are not checked for validity. /// /// </summary> /// <param name="matrix"> /// the matrix to be partitioned. /// </param> /// <param name="rowIndexes"> /// the index of the i-th row; is modified by this method to reflect partitioned indexes. /// </param> /// <param name="rowFrom"> /// the index of the first row (inclusive). /// </param> /// <param name="rowTo"> /// the index of the last row (inclusive). /// </param> /// <param name="column"> /// the index of the column to partition on. /// </param> /// <param name="splitters"> /// the values at which the rows shall be split into intervals. /// Must be sorted ascending and must not contain multiple identical values. /// These preconditions are not checked; be sure that they are met. /// </param> /// <param name="splitFrom"> /// the index of the first splitter element to be considered. /// </param> /// <param name="splitTo"> /// the index of the last splitter element to be considered. /// The method considers the splitter elements<i>splitters[splitFrom] .d splitters[splitTo]</i>. /// </param> /// <param name="splitIndexes"> /// a list into which this method fills the indexes of rows delimiting intervals. /// Upon return <i>splitIndexes[splitFrom..splitTo]</i> will be set accordingly. /// Therefore, must satisfy <i>splitIndexes.Length >= splitters.Length</i>. /// </param> /// <example> /// <table border="1" cellspacing="0"> /// <tr nowrap> /// <td valign="top"><i>8 x 3 matrix:<br> /// 23, 22, 21<br> /// 20, 19, 18<br> /// 17, 16, 15<br> /// 14, 13, 12<br> /// 11, 10, 9<br> /// 8, 7, 6<br> /// 5, 4, 3<br> /// 2, 1, 0 </i></td> /// <td align="left" valign="top"> /// <p><i>column = 0;<br> /// rowIndexes = {0,1,2,.d,matrix.Rows-1}; /// rowFrom = 0;<br> /// rowTo = matrix.Rows-1;<br> /// splitters = {5,10,12}<br> /// c = 0; <br> /// d = splitters.Length-1;<br> /// partition(matrix,rowIndexes,rowFrom,rowTo,column,splitters,c,d,splitIndexes);<br> /// ==><br> /// splitIndexes == {0, 2, 3}<br> /// rowIndexes == {7, 6, 5, 4, 0, 1, 2, 3}</i></p> /// </td> /// <td valign="top"> /// The matrix IS NOT REORDERED.<br> /// Here is how it would look<br> /// like, if it would be reordered<br> /// accoring to <i>rowIndexes</i>.<br> /// <i>8 x 3 matrix:<br> /// 2, 1, 0<br> /// 5, 4, 3<br> /// 8, 7, 6<br> /// 11, 10, 9<br> /// 23, 22, 21<br> /// 20, 19, 18<br> /// 17, 16, 15<br> /// 14, 13, 12 </i></td> /// </tr> /// </table> /// </example> public static void Partition(DoubleMatrix2D matrix, int[] rowIndexes, int rowFrom, int rowTo, int column, double[] splitters, int splitFrom, int splitTo, int[] splitIndexes) { if (rowFrom < 0 || rowTo >= matrix.Rows || rowTo >= rowIndexes.Length) { throw new ArgumentException(); } if (column < 0 || column >= matrix.Columns) { throw new ArgumentException(); } if (splitFrom < 0 || splitTo >= splitters.Length) { throw new ArgumentException(); } if (splitIndexes.Length < splitters.Length) { throw new ArgumentException(); } // this one knows how to swap two row indexes (a,b) int[] g = rowIndexes; Swapper swapper = new Swapper((b, c) => { int tmp = g[b]; g[b] = g[c]; g[c] = tmp; }); // compare splitter[a] with columnView[rowIndexes[b]] DoubleMatrix1D columnView = matrix.ViewColumn(column); IntComparator comp = new IntComparator((a, b) => { double av = splitters[a]; double bv = columnView[g[b]]; return(av < bv ? -1 : (av == bv ? 0 : 1)); }); // compare columnView[rowIndexes[a]] with columnView[rowIndexes[b]] IntComparator comp2 = new IntComparator((a, b) => { double av = columnView[g[a]]; double bv = columnView[g[b]]; return(av < bv ? -1 : (av == bv ? 0 : 1)); }); // compare splitter[a] with splitter[b] IntComparator comp3 = new IntComparator((a, b) => { double av = splitters[a]; double bv = splitters[b]; return(av < bv ? -1 : (av == bv ? 0 : 1)); }); // generic partitioning does the main work of reordering row indexes Cern.Colt.Partitioning.GenericPartition(rowFrom, rowTo, splitFrom, splitTo, splitIndexes, comp, comp2, comp3, swapper); }
public void EnumeratorIntTest() { InterfaceOfComparator <int> comparator = new IntComparator(); BinaryTree <int> tree = new BinaryTree <int>(comparator); tree.InsertElement(1); tree.InsertElement(2); string elements = ""; foreach (int i in tree) { elements += i.ToString() + " "; } Assert.AreEqual("2 1 ", elements); }
static void Task4() { string[] str = Console.ReadLine().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); int[] allNums = new int[str.Length]; for (int i = 0; i < str.Length; i++) { allNums[i] = Convert.ToInt32(str[i]); } List <int> evenNums = new List <int>(); List <int> oddNums = new List <int>(); Func <int, bool> isEven = number => number % 2 == 0; for (int i = 0; i < allNums.Length; i++) { if (isEven(allNums[i])) { evenNums.Add(allNums[i]); } else { oddNums.Add(allNums[i]); } } IntComparator ic = new IntComparator(); Array.Sort(evenNums.ToArray(), ic); for (int i = 0; i < evenNums.Count; i++) { allNums[i] = evenNums[i]; } for (int i = evenNums.Count; i < allNums.Length; i++) { allNums[i] = oddNums[i - evenNums.Count]; } foreach (var n in allNums) { Console.Write(n + " "); } }
/// <summary> /// Sorts the vector into ascending order, according to the order induced by the specified comparator. /// The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa. /// The algorithm compares two cells at a time, determinining whether one is smaller, equal or larger than the other. /// To sort ranges use sub-ranging viewsd To sort descending, use flip views ... /// <p> /// <b>Example:</b> /// <pre> /// // sort by sinus of cells /// ObjectComparator comp = new ObjectComparator() { /// public int compare(Object a, Object b) { /// Object as = System.Math.Sin(a); Object bs = System.Math.Sin(b); /// return as %lt; bs ? -1 : as == bs ? 0 : 1; /// } /// }; /// sorted = quickSort(vector,comp); /// </pre> /// /// @param vector the vector to be sorted. /// @param c the comparator to determine the order. /// @return a new matrix view sorted as specified. /// <b>Note that the original vector (matrix) is left unaffected.</b> /// </summary> public ObjectMatrix1D sort(ObjectMatrix1D vector, IComparer <ObjectMatrix1D> c) { int[] indexes = new int[vector.Size]; // row indexes to reorder instead of matrix itself for (int i = indexes.Length; --i >= 0;) { indexes[i] = i; } IntComparator comp = new IntComparator((a, b) => { return(c.Compare((ObjectMatrix1D)vector[a], (ObjectMatrix1D)vector[b])); }); { }; RunSort(indexes, 0, indexes.Length, comp); return(vector.ViewSelection(indexes)); }
public void TestMethod1() { int[] array = new int[3]; array[0] = 4; array[1] = 6; array[2] = 2; InterfaceOfComparator <int> IntCompair = new IntComparator(); Sort <int> Bubblesort = new Sort <int>(); Bubblesort.BubbleSort(array, IntCompair); Assert.AreEqual(array[0], 2); Assert.AreEqual(array[1], 4); Assert.AreEqual(array[2], 6); }
/// <summary> /// Sorts the vector into ascending order, according to the <i>natural ordering</i>. /// The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa. /// To sort ranges use sub-ranging viewsd To sort descending, use flip views ... /// <p> /// <b>Example:</b> /// <table border="1" cellspacing="0"> /// <tr nowrap> /// <td valign="top"><i> 7, 1, 3, 1<br> /// </i></td> /// <td valign="top"> /// <p><i> ==> 1, 1, 3, 7<br> /// The vector IS NOT SORTED.<br> /// The new VIEW IS SORTED.</i></p> /// </td> /// </tr> /// </table> /// /// @param vector the vector to be sorted. /// @return a new sorted vector (matrix) viewd /// <b>Note that the original matrix is left unaffected.</b> /// </summary> public ObjectMatrix1D sort(ObjectMatrix1D vector) { int[] indexes = new int[vector.Size]; // row indexes to reorder instead of matrix itself for (int i = indexes.Length; --i >= 0;) { indexes[i] = i; } IntComparator comp = new IntComparator((a, b) => { IComparable av = (IComparable)(vector[a]); IComparable bv = (IComparable)(vector[b]); int r = av.CompareTo(bv); return(r < 0 ? -1 : (r > 0 ? 1 : 0)); }); RunSort(indexes, 0, indexes.Length, comp); return(vector.ViewSelection(indexes)); }
/// <summary> /// Performs a binary search on an already-sorted range: finds the last /// position where an element can be inserted without violating the ordering. /// </summary> /// <param name="first"> /// Beginning of the range. /// </param> /// <param name="last"> /// One past the end of the range. /// </param> /// <param name="x"> /// Element to be searched for. /// </param> /// <param name="comp"> /// Comparison function. /// </param> /// <returns> /// The largest index i such that, for every j in the range <code>[first, i)</code>, /// <code>comp.apply(array[j], x)</code> is <code>false</code>. /// </returns> private static int upper_bound(int first, int last, int x, IntComparator comp) { int len = last - first; while (len > 0) { int half = len / 2; int middle = first + half; if (comp(x, middle) < 0) { len = half; } else { first = middle + 1; len -= half + 1; } } return(first); }
/// <summary> /// Sorts the matrix rows according to the order induced by the specified comparator. /// The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa. /// The algorithm compares two rows (1-d matrices) at a time, determinining whether one is smaller, equal or larger than the other. /// To sort ranges use sub-ranging viewsd To sort columns by rows, use dice viewsd To sort descending, use flip views ... /// <p> /// <b>Example:</b> /// <pre> /// // sort by sum of values in a row /// ObjectMatrix1DComparator comp = new ObjectMatrix1DComparator() { /// public int compare(ObjectMatrix1D a, ObjectMatrix1D b) { /// Object as = a.zSum(); Object bs = b.zSum(); /// return as %lt; bs ? -1 : as == bs ? 0 : 1; /// } /// }; /// sorted = quickSort(matrix,comp); /// </pre> /// /// @param matrix the matrix to be sorted. /// @param c the comparator to determine the order. /// @return a new matrix view having rows sorted as specified. /// <b>Note that the original matrix is left unaffected.</b> /// </summary> public ObjectMatrix2D sort(ObjectMatrix2D matrix, ObjectMatrix1DComparator c) { int[] rowIndexes = new int[matrix.Rows]; // row indexes to reorder instead of matrix itself for (int i = rowIndexes.Length; --i >= 0;) { rowIndexes[i] = i; } ObjectMatrix1D[] views = new ObjectMatrix1D[matrix.Rows]; // precompute views for speed for (int i = views.Length; --i >= 0;) { views[i] = matrix.ViewRow(i); } IntComparator comp = new IntComparator((a, b) => { return(c(views[a], views[b])); }); RunSort(rowIndexes, 0, rowIndexes.Length, comp); // view the matrix according to the reordered row indexes // take all columns in the original order return(matrix.ViewSelection(rowIndexes, null)); }
/// <summary> /// Sorts the specified range of elements according to the order induced by the specified comparator. /// </summary> /// <param name="fromIndex"> /// The index of the first element (inclusive) to be sorted. /// </param> /// <param name="toIndex"> /// The index of the last element (exclusive) to be sorted. /// </param> /// <param name="c"> /// The comparator to determine the order of the generic data. /// </param> /// <param name="swapper"> /// The delegate that knows how to swap the elements at any two indexes (a,b). /// </param> public static void MergeSort(int fromIndex, int toIndex, IntComparator c, Swapper swapper) { /* * We retain the same method signature as quickSort. * Given only a comparator and swapper we do not know how to copy and move elements from/to temporary arrays. * Hence, in contrast to the JDK mergesorts this is an "in-place" mergesort, i.e. does not allocate any temporary arrays. * A non-inplace mergesort would perhaps be faster in most cases, but would require non-intuitive delegate objects... */ int length = toIndex - fromIndex; // Insertion sort on smallest arrays if (length < SMALL) { for (int i = fromIndex; i < toIndex; i++) { for (int j = i; j > fromIndex && (c(j - 1, j) > 0); j--) { swapper(j, j - 1); } } return; } // Recursively sort halves int mid = (fromIndex + toIndex) / 2; MergeSort(fromIndex, mid, c, swapper); MergeSort(mid, toIndex, c, swapper); // If list is already sorted, nothing left to do. This is an // optimization that results in faster sorts for nearly ordered lists. if (c(mid - 1, mid) <= 0) { return; } // Merge sorted halves inplace_merge(fromIndex, mid, toIndex, c, swapper); }
public DoubleMatrix3D Sort(DoubleMatrix3D matrix, Cern.Colt.Matrix.DoubleAlgorithms.DoubleMatrix2DComparator c) { int[] sliceIndexes = new int[matrix.Slices]; // indexes to reorder instead of matrix itself for (int i = sliceIndexes.Length; --i >= 0;) { sliceIndexes[i] = i; } DoubleMatrix2D[] views = new DoubleMatrix2D[matrix.Slices]; // precompute views for speed for (int i = views.Length; --i >= 0;) { views[i] = matrix.ViewSlice(i); } IntComparator comp = new IntComparator((a, b) => { return(c(views[a], views[b])); }); RunSort(sliceIndexes, 0, sliceIndexes.Length, comp); // view the matrix according to the reordered slice indexes // take all rows and columns in the original order return(matrix.ViewSelection(sliceIndexes, null, null)); }
public DoubleMatrix3D Sort(DoubleMatrix3D matrix, int row, int column) { if (row < 0 || row >= matrix.Rows) { throw new IndexOutOfRangeException("row=" + row + ", matrix=" + Formatter.Shape(matrix)); } if (column < 0 || column >= matrix.Columns) { throw new IndexOutOfRangeException("column=" + column + ", matrix=" + Formatter.Shape(matrix)); } int[] sliceIndexes = new int[matrix.Slices]; // indexes to reorder instead of matrix itself for (int i = sliceIndexes.Length; --i >= 0;) { sliceIndexes[i] = i; } DoubleMatrix1D sliceView = matrix.ViewRow(row).ViewColumn(column); IntComparator comp = new IntComparator((a, b) => { double av = sliceView[a]; double bv = sliceView[b]; if (Double.IsNaN(av) || Double.IsNaN(bv)) { return(CompareNaN(av, bv)); // swap NaNs to the end } return(av < bv ? -1 : (av == bv ? 0 : 1)); } ); RunSort(sliceIndexes, 0, sliceIndexes.Length, comp); // view the matrix according to the reordered slice indexes // take all rows and columns in the original order return(matrix.ViewSelection(sliceIndexes, null, null)); }
protected void RunSort(int fromIndex, int toIndex, IntComparator c, Cern.Colt.Swapper swapper) { Cern.Colt.GenericSorting.QuickSort(fromIndex, toIndex, c, swapper); }
protected void RunSort(int[] a, int fromIndex, int toIndex, IntComparator c) { Cern.Colt.Sorting.QuickSort(a, fromIndex, toIndex, c); }
/// <summary> /// Sorts the specified range of elements according to the order induced by the specified comparator. /// </summary> /// <param name="fromIndex"> /// The index of the first element (inclusive) to be sorted. /// </param> /// <param name="toIndex"> /// The index of the last element (exclusive) to be sorted. /// </param> /// <param name="c"> /// The comparator to determine the order of the generic data. /// </param> /// <param name="swapper"> /// The delegate that knows how to swap the elements at any two indexes (a,b). /// </param> public static void QuickSort(int fromIndex, int toIndex, IntComparator c, Swapper swapper) { quickSort1(fromIndex, toIndex - fromIndex, c, swapper); }
/// <summary> /// Transforms two consecutive sorted ranges into a single sorted /// range. The initial ranges are <code>[first, middle)</code> /// and <code>[middle, last)</code>, and the resulting range is /// <code>[first, last)</code>. /// Elements in the first input range will precede equal elements in the /// second. /// </summary> private static void inplace_merge(int first, int middle, int last, IntComparator comp, Swapper swapper) { if (first >= middle || middle >= last) { return; } if (last - first == 2) { if (comp(middle, first) < 0) { swapper(first, middle); } return; } int firstCut; int secondCut; if (middle - first > last - middle) { firstCut = first + ((middle - first) / 2); secondCut = lower_bound(middle, last, firstCut, comp); } else { secondCut = middle + ((last - middle) / 2); firstCut = upper_bound(first, middle, secondCut, comp); } // rotate(firstCut, middle, secondCut, swapper); // is manually inlined for speed (jitter inlining seems to work only for small call depths, even if methods are "static private") // speedup = 1.7 // begin inline int first2 = firstCut; int middle2 = middle; int last2 = secondCut; if (middle2 != first2 && middle2 != last2) { int first1 = first2; int last1 = middle2; while (first1 < --last1) { swapper(first1++, last1); } first1 = middle2; last1 = last2; while (first1 < --last1) { swapper(first1++, last1); } first1 = first2; last1 = last2; while (first1 < --last1) { swapper(first1++, last1); } } // end inline middle = firstCut + (secondCut - middle); inplace_merge(first, firstCut, middle, comp, swapper); inplace_merge(middle, secondCut, last, comp, swapper); }
/// <summary> /// Sorts the specified sub-array into ascending order. /// </summary> private static void quickSort1(int off, int len, IntComparator comp, Swapper swapper) { // Insertion sort on smallest arrays if (len < SMALL) { for (int i = off; i < len + off; i++) { for (int j = i; j > off && (comp(j - 1, j) > 0); j--) { swapper(j, j - 1); } } return; } // Choose a partition element, v int m = off + (len / 2); // Small arrays, middle element if (len > SMALL) { int l = off; int n = off + len - 1; if (len > MEDIUM) { // Big arrays, pseudomedian of 9 int s = len / 8; l = med3(l, l + s, l + (2 * s), comp); m = med3(m - s, m, m + s, comp); n = med3(n - (2 * s), n - s, n, comp); } m = med3(l, m, n, comp); // Mid-size, med of 3 } // Establish Invariant: v* (<v)* (>v)* v* int a = off, b = a, c = off + len - 1, d = c; while (true) { int comparison; while (b <= c && ((comparison = comp(b, m)) <= 0)) { if (comparison == 0) { if (a == m) { m = b; // moving target; DELTA to JDK !!! } else if (b == m) { m = a; // moving target; DELTA to JDK !!! } swapper(a++, b); } b++; } while (c >= b && ((comparison = comp(c, m)) >= 0)) { if (comparison == 0) { if (c == m) { m = d; // moving target; DELTA to JDK !!! } else if (d == m) { m = c; // moving target; DELTA to JDK !!! } swapper(c, d--); } c--; } if (b > c) { break; } if (b == m) { m = d; // moving target; DELTA to JDK !!! } else if (c == m) { m = c; // moving target; DELTA to JDK !!! } swapper(b++, c--); } // Swap partition elements back to middle int n1 = off + len; int s1 = Math.Min(a - off, b - a); vecswap(swapper, off, b - s1, s1); s1 = Math.Min(d - c, n1 - d - 1); vecswap(swapper, b, n1 - s1, s1); // Recursively sort non-partition-elements if ((s1 = b - a) > 1) { quickSort1(off, s1, comp, swapper); } if ((s1 = d - c) > 1) { quickSort1(n1 - s1, s1, comp, swapper); } }