ãã®ãããæåã«ã.NETã®æåã®ããŒãžã§ã³ã§ã¯ããã©ã«ãã®ã¯ã€ãã¯ãœãŒãã¢ã«ãŽãªãºã ã䜿çšããŸãã ãããã£ãŠãã¯ã€ãã¯ãœãŒããžã®å°ããªäœè«ïŒ
å©ç¹ïŒ
- æéã®ïŒå®éã®ïŒæ±çšå éšãœãŒãã¢ã«ãŽãªãºã ã®1ã€ã
- å®è£ ãç°¡åã
- æäœã«å¿ èŠãªã®ã¯OïŒlognïŒè¿œå ã¡ã¢ãªã®ã¿ã§ãïŒææªã®å Žåã®æ¹åãããååž°ã¢ã«ãŽãªãºã ã§ã¯ãªããOïŒnïŒã¡ã¢ãªïŒã
- ãã£ãã·ã³ã°ãšä»®æ³ã¡ã¢ãªã¡ã«ããºã ã«é©ããŠããŸãã
çæïŒ
- ãµããŒãèŠçŽ ã®éžæã倱æãããšãé床ãOïŒn 2 ïŒã«å€§å¹ ã«äœäžããŸããããã¯ãå ¥åã倱æãããšçºçããå¯èœæ§ããããŸãã ããã¯ãåºå®çãªæ¹æ³ã§ã¯ãªããã©ã³ãã ã«ãµããŒãèŠçŽ ãéžæããããšã§åé¿ã§ããŸãã
- ã¢ã«ãŽãªãºã ã®åçŽãªå®è£ ã§ã¯ãOïŒnïŒãã¹ããããååž°åŒã³åºããè¡ãå¿ èŠããããããã¹ã¿ãã¯ãªãŒããŒãããŒãšã©ãŒãçºçããå¯èœæ§ããããŸãã ååž°åŒã³åºããé åã®2ã€ã®éšåã®ãã¡å°ããæ¹ããœãŒãããããã ãã®é«åºŠãªå®è£ ã§ã¯ãååž°ã®æ·±ãã¯OïŒlognïŒãè¶ ããªãããšãä¿èšŒãããŸãã
- äžå®å®-å®å®æ§ãå¿ èŠãªå Žåã¯ãããŒãå±éããå¿ èŠããããŸãã
ã¯ã€ãã¯ãœãŒãã¢ã«ãŽãªãºã ã®åçŽãªå®è£ ã¯ã次ã®ããã«ãªããŸãã
çŽ æŽãªQuickSort
public void QuickSort(int left, int right) { int l = left; int r = right; int avg = array[(l + r) / 2)]; do { while (array[l] < avg) ++l; while (array[r] > avg) --r; if (l <= r) { if (l < r) { int temp = array[l]; array[l] = array[r]; array[r] = temp; } ++l; --r; } } while (l <= r); if (left < r) QuickSort(left, r); if (l < right) QuickSort(l, right); }
äžèšã®ãœãŒãã¢ã«ãŽãªãºã ã«ã¯ã次ã®æ¬ ç¹ããããŸãã
- ãµããŒãèŠçŽ ã¯é åã®äžå€®ãšããŠéžæããããããåžžã«æ倧ã«ãªãå¯èœæ§ããããŸãããã®çµæãé åã¯é·ãn-1ããã³1ã®2ã€ã®éšåã«åå²ãããã¢ã«ãŽãªãºã é床ã¯OïŒn 2 ïŒã«äœäžããŸãã
- äžèšã®æ¡ä»¶äžã§ã¯ãååž°ã®æ·±ãã¯OïŒnïŒã«éããŸãããã®çµæãnã倧ããå ŽåããœãããŠã§ã¢ã¹ã¿ãã¯ããªãŒããŒãããŒããå¯èœæ§ããããŸãã
- ã¢ã«ãŽãªãºã ã¯äžå®å®ã§ããã€ãŸããåãå€ãæã€èŠçŽ ãå€æŽããŸãã æ°å€ã®äžŠã¹æ¿ãã®äŸã§ã¯ãããã¯äœã®åœ±é¿ããããŸãããããªããžã§ã¯ãã®é åãããããã£ã§äžŠã¹æ¿ãããšãSortã¡ãœããã®ããã€ãã®åŒã³åºãã®çµæãé åºãç°ãªãèŠçŽ ã®é åãååŸããããããããã¯éèŠã§ãã
.NETã§ã®å®è£ ãæ€èšããŸãã
.NET 1.0
ããã§ã¯ã.NET 1.0ã§äœãèµ·ãããèŠãŠã¿ãŸãããã å ã«é²ããšãç¹ã«ãŠãŒã¶ãŒãéèŠãªã¿ã€ãã®å Žåãããã§ã¯äœãè¯ããã®ã衚瀺ãããªãããšãäºåã«èšããŸã...ïŒç¹ã«äžè¬åã®æ¬ åŠã®ããïŒ
public static void Sort(Array array) { Array.Sort(array, (Array) null, array.GetLowerBound(0), array.Length, (IComparer) null); } public static void Sort(Array keys, Array items, int index, int length, IComparer comparer) { if (length > 1) { if (comparer == Comparer.Default || comparer == null) { if(TrySZSort(array, null, index, index + length - 1)) { return; } } object[] keys1 = keys as object[]; object[] items1 = (object[]) null; if (keys1 != null) items1 = items as object[]; if (keys1 != null && (items == null || items1 != null)) new Array.SorterObjectArray(keys1, items1, comparer).QuickSort(index, index + length - 1); else new Array.SorterGenericArray(keys, items, comparer).QuickSort(index, index + length - 1); }
ãããŠä»ãSorterObjectArrayã¯ã©ã¹ãšSorterGenericArrayã¯ã©ã¹èªäœïŒ
ãœãŒã¿ãŒãªããžã§ã¯ãé
å
private class SorterObjectArray { private object[] keys; private object[] items; private IComparer comparer; public SorterObjectArray(object[] keys, object[] items, IComparer comparer) { if (comparer == null) comparer = (IComparer)Comparer.Default; this.keys = keys; this.items = items; this.comparer = comparer; } public virtual void QuickSort(int left, int right) { do { int left1 = left; int right1 = right; object obj1 = this.keys[left1 + right1 >> 1]; do { while (this.comparer.Compare(this.keys[left1], obj1) < 0) ++left1; while (this.comparer.Compare(obj1, this.keys[right1]) < 0) --right1; if (left1 <= right1) { if (left1 < right1) { object obj2 = this.keys[left1]; this.keys[left1] = this.keys[right1]; this.keys[right1] = obj2; if (this.items != null) { object obj3 = this.items[left1]; this.items[left1] = this.items[right1]; this.items[right1] = obj3; } } ++left1; --right1; } else break; } while (left1 <= right1); if (right1 - left <= right - left1) { if (left < right1) this.QuickSort(left, right1); left = left1; } else { if (left1 < right) this.QuickSort(left1, right); right = right1; } } while (left < right); } }
SorterGenericArray
private class SorterGenericArray { private Array keys; private Array items; private IComparer comparer; public SorterGenericArray(Array keys, Array items, IComparer comparer) { if (comparer == null) comparer = (IComparer)Comparer.Default; this.keys = keys; this.items = items; this.comparer = comparer; } public virtual void QuickSort(int left, int right) { do { int num1 = left; int num2 = right; object obj1 = this.keys.GetValue(num1 + num2 >> 1); do { while (this.comparer.Compare(this.keys.GetValue(num1), obj1) < 0) ++num1; while (this.comparer.Compare(obj1, this.keys.GetValue(num2)) < 0) --num2; if (num1 <= num2) { if (num1 < num2) { object obj2 = this.keys.GetValue(num1); this.keys.SetValue(this.keys.GetValue(num2), num1); this.keys.SetValue(obj2, num2); if (this.items != null) { object obj3 = this.items.GetValue(num1); this.items.SetValue(this.items.GetValue(num2), num1); this.items.SetValue(obj3, num2); } } ++num1; --num2; } else break; } while (num1 <= num2); if (num2 - left <= right - num1) { if (left < num2) this.QuickSort(left, num2); left = num1; } else { if (num1 < right) this.QuickSort(num1, right); right = num2; } } while (left < right); } }
ããã§äœãèµ·ãã£ãŠããã®ã§ããããïŒ æ¬¡ã®ã³ãŒã
object[] keys1 = keys as object[]; object[] items1 = (object[]) null; if (keys1 != null) items1 = items as object[];
ããã¯é åã®å ±åæ£ã䜿çšããè©Šã¿ã«éããŸãããããã¯ãåãã®ãšãããåç §åã«å¯ŸããŠã®ã¿æ©èœããŸãã åç §åã«ã¯SorterObjectArrayã¯ã©ã¹ã䜿çšãããéèŠãªåã«ã¯SorterGenericArrayã䜿çšãããŠããããšãããããŸãã ãããããããã®ã¯ã©ã¹ã¯ã©ã®ããã«ç°ãªãã®ã§ããããïŒ ã芧ã®ãšãããé åã®èŠçŽ ã«ã¢ã¯ã»ã¹ããæ¹æ³ã®ã¿ãç°ãªããŸãã éèŠãªåã®å ŽåãGetValueã¡ãœãããšSetValueã¡ãœããã䜿çšãããŸããããåãã®ããã«éåžžã«é ãã§ã...æŽæ°ã®é åã¯éåžžã«é·ãæéãœãŒããããŸãïŒçµå±ãæŽæ°ã¯éèŠãªã¿ã€ãã§ãïŒã ããïŒ æŽæ°ã®é åã¯ãè¿ éãã€éåžžã«è¿ éã«ãœãŒããããŸãã 次ã®ã³ãŒãããã¹ãŠã§ã
if (length > 1) { if (comparer == Comparer.Default || comparer == null) { if(TrySZSort(array, null, index, index + length - 1)) return; } }
èå³æ·±ãã®ã¯Array.TrySZSortã¡ãœããã§ãã ãã®ã¡ãœããã¯ãC ++ã§CLRèªäœã«å®è£ ãããŠãããã€ãã£ãã®äžŠã¹æ¿ãã®å®è£ ãåŒã³åºããŸãã ããã«ãèŠçŽ ã®æ¯èŒã«æšæºããžãã¯ã䜿çšããå Žåãã€ãŸãcomparer == Comparer.Default ||ã®å Žåãããªããã£ãåã«å¯ŸããŠæ©èœããŸãã æ¯èŒå== nullã
ãã€ãã£ãå®è£ ã¯æ¬¡ã®ãšããã§ãã
ãã€ãã£ãTrySZSort
FCIMPL4(INT32, ArrayHelper::TrySZSort, ArrayBase * keys, ArrayBase * items, UINT32 left, UINT32 right) // if (keys->GetRank() != 1 || keys->GetLowerBoundsPtr()[0] != 0) return FALSE; // TypeHandle keysTH = keys->GetElementTypeHandle(); // const CorElementType keysElType = keysTH.GetSigCorElementType(); if (!CorTypeInfo::IsPrimitiveType(keysElType)) return FALSE; if (items != NULL) { TypeHandle itemsTH = items->GetElementTypeHandle(); if (keysTH != itemsTH) return FALSE; // Can't currently handle sorting different types of arrays. } // if (left == right || right == 0xffffffff) return TRUE; // ++. switch(keysElType) { case ELEMENT_TYPE_I1: // 1- (sbyte) ArrayHelpers<I1>::QuickSort((I1*) keys->GetDataPtr(), (I1*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_U1: // 1- (byte) case ELEMENT_TYPE_BOOLEAN: // (bool) ArrayHelpers<U1>::QuickSort((U1*) keys->GetDataPtr(), (U1*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_I2: // 2- (short) ArrayHelpers<I2>::QuickSort((I2*) keys->GetDataPtr(), (I2*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_U2: // 2- (ushort) case ELEMENT_TYPE_CHAR: // (char) ArrayHelpers<U2>::QuickSort((U2*) keys->GetDataPtr(), (U2*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_I4: // 4- (int) ArrayHelpers<I4>::QuickSort((I4*) keys->GetDataPtr(), (I4*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_U4: // 4- (uint) ArrayHelpers<U4>::QuickSort((U4*) keys->GetDataPtr(), (U4*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_R4: // 4- (float) ArrayHelpers<R4>::QuickSort((R4*) keys->GetDataPtr(), (R4*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_I8: // 8- (long) ArrayHelpers<I8>::QuickSort((I8*) keys->GetDataPtr(), (I8*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_U8: // 8- (ulong) ArrayHelpers<U8>::QuickSort((U8*) keys->GetDataPtr(), (U8*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_R8: // 8- (double) ArrayHelpers<R8>::QuickSort((R8*) keys->GetDataPtr(), (R8*) (items == NULL ? NULL : items->GetDataPtr()), left, right); break; case ELEMENT_TYPE_I: // (IntPtr) case ELEMENT_TYPE_U: // (UIntPtr) // In V1.0, IntPtr & UIntPtr are not fully supported types. They do // not implement IComparable, so searching & sorting for them should // fail. In V1.1 or V2.0, this should change. return FALSE; default: return FALSE; } return TRUE; }
ãã€ãã£ãQuickSort
// - template <class KIND> class ArrayHelpers { static void QuickSort(KIND keys[], KIND items[], int left, int right) { do { int i = left; int j = right; KIND x = keys[(i + j) >> 1]; do { while (Compare(keys[i], x) < 0) i++; while (Compare(x, keys[j]) < 0) j--; if (i > j) break; if (i < j) { KIND key = keys[i]; keys[i] = keys[j]; keys[j] = key; if (items != NULL) { KIND item = items[i]; items[i] = items[j]; items[j] = item; } } i++; j--; } while (i <= j); if (j - left <= right - i) { if (left < j) QuickSort(keys, items, left, j); left = i; } else { if (i < right) QuickSort(keys, items, i, right); right = j; } } while (left < right); } };
ã芧ã®ãšããããã€ãã£ããœãŒãã¯ããªããã£ãåã«å¯ŸããŠã®ã¿æ©èœããŸãã ãããã«ã¯ããã¹ãŠã®æ°å€ã¿ã€ã+è«ç+æåãå«ãŸããŸãã ãŸããéèŠãªãŠãŒã¶ãŒã¿ã€ãã®å Žåããã¹ãŠãåããããã»ã©é ãåäœããŸãã
ãœãŒãã¢ã«ãŽãªãºã èªäœã®å®è£ ãæ€èšããŸãã ãã€ãã£ãå®è£ ãšéèŠãªåã®å®è£ ã®äž¡æ¹ã䌌ãŠãããããSorterObjectArrayã¯ã©ã¹ã§ã®å®è£ ãæ€èšããŸãã
1.é åã®äžå€®ã¯åžžã«ãµããŒãèŠçŽ ãšããŠäœ¿çšãããŸãã
object obj1 = this.keys[left1 + right1 >> 1];
å ¥åããŒã¿ãå°ãªããšãã¢ã«ãŽãªãºã ã®å®è¡æéã2次ã«ãªãå¯èœæ§ããããããããã¯è¯ããããŸããã ããã«ãåŒnum1 + num2 >> 1ã䜿çšããŠäžå€®ãååŸããŸããããã«ãããintåã®ãªãŒããŒãããŒãçºçããå¯èœæ§ããããŸãã Javaã®ãã€ããªæ€çŽ¢ããã³ãœãŒãã¢ã«ãŽãªãºã ã§ãåããšã©ãŒãçºçããŸããïŒ ãã°ãžã®ãªã³ã¯ ïŒã
.NETã®å°æ¥ã®ããŒãžã§ã³ã§ãããããã«ããã®æ¬ é¥ã¯ä¿®æ£ãããŸãã
2.ã¹ã¿ãã¯ãªãŒããŒãããŒãåé¿ããããã«ããã®å®è£ ã¯ååž°ã®1ã€ã®åå²ãæé€ããæé©åãæäŸããŸããé åãåå²ããåŸãèŠã€ãã£ãäž¡æ¹ã®ãµãã¢ã¬ã€ã«å¯ŸããŠããŒãã£ã·ã§ã³ããã·ãŒãžã£ãååž°çã«åŒã³åºã代ããã«ãå°ãããµãã¢ã¬ã€ã«å¯ŸããŠã®ã¿ååž°åŒã³åºããè¡ããã倧ãããµãã¢ã¬ã€ãã«ãŒãã§åŠçãããŸãåãããã·ãŒãžã£ã³ãŒã«å ã å¹çã®èŠ³ç¹ããèŠããšãå¹³åçãªã±ãŒã¹ã«ã¯å®è³ªçã«éãã¯ãããŸãããè¿œå ã®ååž°åŒã³åºãã®ãªãŒããŒãããã³ã¹ããšããµãã¢ã¬ã€ãšã«ãŒãã®é·ããæ¯èŒããçµç¹ã¯ã»ãŒåãã§ãã ããããååž°ã®æ·±ãã¯ãã©ããªç¶æ³ã§ãlog 2 nãè¶ ããææªã®å Žåãéåããåé¢ã®å Žåãéåžž2以äžã«ãªããŸãããã¹ãŠã®åŠçã¯ãæåã®ååž°ã¬ãã«ã®ãµã€ã¯ã«ã§è¡ãããŸãã
.NET 2.0
æ°ããå®è£ ã«ã¯å°ããªå€æŽãå ããããŸããã äžè¬åã¯.NET 2.0ã§ç»å Žãããããäžè¬åããã䞊ã¹æ¿ããªãã·ã§ã³ãæäŸããŸãã
public static void Sort<T>(T[] array, int index, int length, IComparer<T> comparer) { // TrySZSort . // Int32.CompareTo "<" ">". if (length <= 1 || (comparer == null || comparer == Comparer<T>.Default) && Array.TrySZSort((Array) array, (Array) null, index, index + length - 1)) return; ArraySortHelper<T>.Default.Sort(array, index, length, comparer); }
ãããŠãããããœãŒãããå®éã®æ¹æ³ã§ã
ã¯ã€ãã¯ãœãŒã
private static void SwapIfGreaterWithItems(T[] keys, IComparer<T> comparer, int a, int b) { if (a == b || comparer.Compare(keys[a], keys[b]) <= 0) return; T obj = keys[a]; keys[a] = keys[b]; keys[b] = obj; } internal static void QuickSort(T[] keys, int left, int right, IComparer<T> comparer) { do { int index1 = left; int index2 = right; int index3 = index1 + (index2 - index1 >> 1); ArraySortHelper<T>.SwapIfGreaterWithItems(keys, comparer, index1, index3); ArraySortHelper<T>.SwapIfGreaterWithItems(keys, comparer, index1, index2); ArraySortHelper<T>.SwapIfGreaterWithItems(keys, comparer, index3, index2); T obj1 = keys[index3]; do { while (comparer.Compare(keys[index1], obj1) < 0) ++index1; while (comparer.Compare(obj1, keys[index2]) < 0) --index2; if (index1 <= index2) { if (index1 < index2) { T obj2 = keys[index1]; keys[index1] = keys[index2]; keys[index2] = obj2; } ++index1; --index2; } else break; } while (index1 <= index2); if (index2 - left <= right - index1) { if (left < index2) ArraySortHelper<T>.QuickSort(keys, left, index2, comparer); left = index1; } else { if (index1 < right) ArraySortHelper<T>.QuickSort(keys, index1, right, comparer); right = index2; } } while (left < right); }
æ±åã®ååšã«ãããããããçµã¿èŸŒã¿ããªããã£ãåã®æé©åã¯ãŸã ããã«ãããšèšãããã¹ãã§ãïŒéçºè ã®ã³ââã¡ã³ããåç §ïŒã ã€ãŸããããªããã£ãåã¯äŸç¶ãšããŠãã€ãã£ãã®äžŠã¹æ¿ãã䜿çšããŸãã
åç §èŠçŽ ã¯ãé åã®äžå€®ã§ã¯ãªããé åã®æåãäžå€®ãããã³æåŸã®èŠçŽ ã®äžå€®å€ã«ãªããŸããã
int index3 = index1 + (index2 - index1 >> 1); // ArraySortHelper<T>.SwapIfGreaterWithItems(keys, comparer, index1, index3); ArraySortHelper<T>.SwapIfGreaterWithItems(keys, comparer, index1, index2); ArraySortHelper<T>.SwapIfGreaterWithItems(keys, comparer, index3, index2); T obj1 = keys[index3];
ããã«ãäžå€®ãåŒindex1 +ïŒindex2-index1 >> 1ïŒã§èšç®ãããããã«ãªãããªãŒããŒãããŒã«é¢é£ãããšã©ãŒãæé€ãããŸãã
ãã以å€ã®å Žåããã¹ãŠã¯ãŸã å€æŽãããŠããŸããã
äœè«ã§ãã ãæŽæ°ã®é åãéé ã«äžŠã¹æ¿ããå¿ èŠããããŸãã ã©ãããŸããïŒ
äžèšã®ãã¹ãŠãèãããšã次ã®ã³ãŒã
Array.Sort(a); Array.Reverse(a);
ç§ã®ã³ã³ãã¥ãŒã¿ãŒã§ã¯çŽ3åé«éã«åäœããŸã
Array.Sort(a, (x, y) => -x.CompareTo(y))
Array.Reverseã¡ãœãããäžè¬åãããŠããªããšããäºå®ã«æ··ä¹±ããå¯èœæ§ããããŸããã€ãŸããæå³ã®ããã¿ã€ãïŒããã±ãŒãžããã³GetValueãSetValueã¡ãœããïŒã§ãã£ãããšåäœããŸããããã®å®è£ ãèŠããšãçµã¿èŸŒã¿ã®æå³ã®ããã¿ã€ãã®æé©åãã€ãŸã次ã®ãããªãã€ãã£ãã®Array.TrySZReverseã¡ãœãããåŒã³åºããŸãã
é
template <class KIND> static void Reverse(KIND array[], UINT32 index, UINT32 count) { if (count == 0) { return; } UINT32 i = index; UINT32 j = index + count - 1; while(i < j) { KIND temp = array[i]; array[i] = array[j]; array[j] = temp; i++; j--; } } };
äžè¬çã«ãæšæºã©ã€ãã©ãªã§ã®æé©åã¯ãé ã ã§åŸ ã£ãŠããŸãã
ãšããã§ããã®ã¡ãœããã®äžè¬åãããããŒãžã§ã³ããªãããšã¯éåžžã«å¥åŠã§ãã Enumerableã®æ¡åŒµã¡ãœãããšããŠReverseã¡ãœããããããŸããããã®æ¬ ç¹ã¯ããããé©åã§ãªãããšã§ãã ãŠãŒã¶ãŒã«ãšã£ãŠéèŠãªåã®é åã§Array.ReverseãåŒã³åºããšãåžžã«èªåãã¯ã·ã³ã°ãçºçããããšãããããŸããã
.NET 3.0-.NET 4.0
ã¢ã«ãŽãªãºã ã¯å€æŽãããŠããŸããã
.NET 4.5
ãããã楜ãã¿ãå§ãŸããŸãïŒ
ãã ããã¢ã«ãŽãªãºã ã®æ€èšã«ç§»ãåã«ã.NET 4.5ã®å±éã«ã€ããŠããã€ã説æããå¿ èŠããããŸãã ç¶æ³ãå®å šã«ç解ããã«ã¯ããã®èšäºãèªãããšããå§ãããŸãïŒæ®å¿µãªãããè±èªã§ïŒã VS 2012ãã€ãŸã.NET 4.5ãã€ã³ã¹ããŒã«ãããšã4ã€ã®ãã¬ãŒã ã¯ãŒã¯ã®ã¢ã»ã³ããªã眮ãæããããŸãã å®éãããã¯ãçŸåš.NET 4ã§èšè¿°ããŠããå Žåã§ãã.NET 4.5ãã«ãã䜿çšããŠããããšãæå³ããŸãã èå³æ·±ãããšã«ã4.5ãã€ã³ã¹ããŒã«ããåã«1ã€ã®ãœãŒãã¢ã«ãŽãªãºã ã䜿çšããã€ã³ã¹ããŒã«åŸã«å¥ã®ã¢ã«ãŽãªãºã ã䜿çšãããšããã¹ãŠãç¥ããªããã¡ã«çºçããŸãã
å®éã«äœãèµ·ãã£ãŠããããç解ããã«ã¯ã.NET 4.5ã®ã³ãŒããèŠãŠãã ããã
public void Sort(T[] keys, int index, int length, IComparer<T> comparer) { if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) ArraySortHelper<T>.IntrospectiveSort(keys, index, length, comparer); else ArraySortHelper<T>.DepthLimitedQuickSort(keys, index, length + index - 1, comparer, 32); }
ã芧ã®ãšããããã®ã¡ãœããã¯ãã©ã®.NETã§äœæ¥ããŠãããããã§ãã¯ããŸãã4.5ã®å Žåã¯IntrospectiveSortã䜿çšãã4.0ã®å Žåã¯DepthLimitedQuickSortã䜿çšããŸãã
VS2012ãã€ã³ã¹ããŒã«ããåã«ãDepthLimitedQuickSortã.NET 4.0ã§äœ¿çšããã䞊ã¹æ¿ããšã©ã®ããã«ç°ãªããã調ã¹ãŠã¿ãŸãããããã®ã¡ãœããã®ã³ãŒããèŠãŠã¿ãŸãããã
DepthLimitedQuickSort
internal static void DepthLimitedQuickSort(T[] keys, int left, int right, IComparer<T> comparer, int depthLimit) { while (depthLimit != 0) { int index1 = left; int index2 = right; int index3 = index1 + (index2 - index1 >> 1); ArraySortHelper<T>.SwapIfGreater(keys, comparer, index1, index3); ArraySortHelper<T>.SwapIfGreater(keys, comparer, index1, index2); ArraySortHelper<T>.SwapIfGreater(keys, comparer, index3, index2); T obj1 = keys[index3]; do { while (comparer.Compare(keys[index1], obj1) < 0) ++index1; while (comparer.Compare(obj1, keys[index2]) < 0) --index2; if (index1 <= index2) { if (index1 < index2) { T obj2 = keys[index1]; keys[index1] = keys[index2]; keys[index2] = obj2; } ++index1; --index2; } else break; } while (index1 <= index2); --depthLimit; if (index2 - left <= right - index1) { if (left < index2) ArraySortHelper<T>.DepthLimitedQuickSort(keys, left, index2, comparer, depthLimit); left = index1; } else { if (index1 < right) ArraySortHelper<T>.DepthLimitedQuickSort(keys, index1, right, comparer, depthLimit); right = index2; } if (left >= right) return; } ArraySortHelper<T>.Heapsort(keys, left, right, comparer); }
ã芧ã®ãšãããããã¯1ã€ãé€ããŠåãã¯ã€ãã¯ãœãŒãã§ããå垰深床ïŒããã©ã«ãã§ã¯32ïŒã䜿ãæãããšãã¢ã«ãŽãªãºã ã¯ãã©ããããœãŒãã«åãæ¿ãããŸãã
ãããŠãããã«ãã©ãããåã®ãœãŒãèªäœããããŸãïŒ
ããŒããœãŒã
private static void Heapsort(T[] keys, int lo, int hi, IComparer<T> comparer) { int n = hi - lo + 1; for (int i = n / 2; i >= 1; --i) ArraySortHelper<T>.DownHeap(keys, i, n, lo, comparer); for (int index = n; index > 1; --index) { ArraySortHelper<T>.Swap(keys, lo, lo + index - 1); ArraySortHelper<T>.DownHeap(keys, 1, index - 1, lo, comparer); } } private static void DownHeap(T[] keys, int i, int n, int lo, IComparer<T> comparer) { T x = keys[lo + i - 1]; for (; i <= n / 2; { int num; i = num;}) { num = 2 * i; if (num < n && comparer.Compare(keys[lo + num - 1], keys[lo + num]) < 0) ++num; if (comparer.Compare(x, keys[lo + num - 1]) < 0) keys[lo + i - 1] = keys[lo + num - 1]; else break; } keys[lo + i - 1] = x; }
DepthLimitedQuickSortã¢ã«ãŽãªãºã ã¯ãIntroSortã«ãããŸããã
IntrosortããŸãã¯å ççãœãŒãã¯ã1997幎ã«David Musserã«ãã£ãŠææ¡ããããœãŒãã¢ã«ãŽãªãºã ã§ãã ååž°ã®æ·±ããäºåå®çŸ©ãããã¬ãã«ãè¶ ãããšãã¯ã€ãã¯ãœãŒãã䜿çšããŠãã©ããããœãŒãã«åãæ¿ãããŸãã ãã®ã¢ãããŒãã¯ãäž¡æ¹ã®æ¹æ³ã®é·æããææªã®å Žåã®OïŒn log nïŒããã³ã¯ã€ãã¯ãœãŒãã«å¹æµããããã©ãŒãã³ã¹ãšçµã¿åãããŸãã äž¡æ¹ã®ã¢ã«ãŽãªãºã ã¯æ¯èŒã䜿çšããããããã®ã¢ã«ãŽãªãºã ã¯æ¯èŒã«åºã¥ããœãŒãã®ã¯ã©ã¹ã«ãå±ããŸãã
ããã§ã¯ãIntrospectiveSortã§äœãèµ·ãã£ãŠããã®ãèŠãŠã¿ãŸãããã å®éãããã¯åãå ççãªãœãŒãã§ãããããæé©åãããŠããŸãã ã¡ãªã¿ã«ãMSDNã¯ãŸã é«éãœãŒãã䜿çšããŠãããšèšã£ãŠããŸãã
IntroSort
private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, IComparer<T> comparer) { for (; hi > lo; {int num; hi = num - 1;}) { int num = hi - lo + 1; if (num <= 16) // 16 { if (num == 1) // break; if (num == 2) // { ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi); break; } else if (num == 3) // { ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi - 1); ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi); ArraySortHelper<T>.SwapIfGreater(keys, comparer, hi - 1, hi); break; } else { ArraySortHelper<T>.InsertionSort(keys, lo, hi, comparer); // break; } } else if (depthLimit == 0) // { ArraySortHelper<T>.Heapsort(keys, lo, hi, comparer); // break; } else // { --depthLimit; num = ArraySortHelper<T>.PickPivotAndPartition(keys, lo, hi, comparer); ArraySortHelper<T>.IntroSort(keys, num + 1, hi, depthLimit, comparer); } } }
PickPivotAndPartition
// private static int PickPivotAndPartition(T[] keys, int lo, int hi, IComparer<T> comparer) { int index = lo + (hi - lo) / 2; ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, index); ArraySortHelper<T>.SwapIfGreater(keys, comparer, lo, hi); ArraySortHelper<T>.SwapIfGreater(keys, comparer, index, hi); T obj = keys[index]; ArraySortHelper<T>.Swap(keys, index, hi - 1); int i = lo; int j = hi - 1; while (i < j) { do ; while (comparer.Compare(keys[++i], obj) < 0); do ; while (comparer.Compare(obj, keys[--j]) < 0); if (i < j) ArraySortHelper<T>.Swap(keys, i, j); else break; } ArraySortHelper<T>.Swap(keys, i, hi - 1); return i; }
æ¿å
¥ãœãŒã
// private static void InsertionSort(T[] keys, int lo, int hi, IComparer<T> comparer) { for (int index1 = lo; index1 < hi; ++index1) { int index2 = index1; T x; for (x = keys[index1 + 1]; index2 >= lo && comparer.Compare(x, keys[index2]) < 0; --index2) keys[index2 + 1] = keys[index2]; keys[index2 + 1] = x; } }
é åã§ã®äžŠã¹æ¿ãã«ã¯ãæ¿å ¥äžŠã¹æ¿ããã¯ã€ãã¯äžŠã¹æ¿ãããã©ããã䞊ã¹æ¿ããšãã䞊ã¹æ¿ããæ··åšããŠããŸãã
Introsortã䜿çšãããšãå®éã®ã¿ã¹ã¯ã§ã¯ããŒã¿ãéšåçã«é åºä»ããããæ¿å ¥ã«ãããœãŒãããã®ãããªããŒã¿ã§éåžžã«è¿ éã«æ©èœããããšãããã£ãŠãããããããã©ãŒãã³ã¹ã«ãã©ã¹ã®å¹æããããŸãã
æ§èœæ¯èŒ
Javaãšã®æ¯èŒ
ãœãŒãã®ç¹ã§ã¯ãJavaã¯.NETãšã¯ãŸã£ããç°ãªããŸãã ãã ããJavaã®.NETãšåæ§ã«ãã¢ã«ãŽãªãºã ãå€æŽãããŠããŸãã
ãåãã®ããã«ãé«éãœãŒãã¯äžå®å®ã§ãããããã¯åç §ã¿ã€ãããœãŒãããå Žåã®æ¬ ç¹ã§ãã Javaã¯ããªããžã§ã¯ãã®ãããªãã®ãã§ããããããã®åé¡ã¯æªåãããããåç §ãœãŒãã®ãœãŒãã«ã¯ããŒãžãœãŒãã䜿çšãããŸãã ãã®äžŠã¹æ¿ãã¯å ç¢ã§ãããææªã®å ŽåOïŒn lognïŒã®å®è¡æéãä¿èšŒããŸãããOïŒnïŒã®è¿œå ã¡ã¢ãªãå¿ èŠã§ãã
å®å®æ§ã®åé¡ã¯åç §åã®ã¿ã«é¢ä¿ãããããããªããã£ãã§ã¯ãåãããŒãæã€èŠçŽ ãå€æŽãããã©ããã¯é¢ä¿ãããŸããã ãã®ãããJavaã¯æ¹åãããã¯ã€ãã¯ãœãŒãã¢ã«ãŽãªãºã DualPivotQuicksortã䜿çšããŠãããªããã£ãããœãŒãããŸãã éåžžã®ã¯ã€ãã¯ãœãŒãã¯ãã©ã³ãã ãªèŠçŽ PãéžæããŠé åã2ã€ã®ã»ã°ã¡ã³ãã«åå²ããŸãã次ã«ãPããå°ããèŠçŽ ããã¹ãŠæåã®ã»ã°ã¡ã³ãã«ãæ®ãã2çªç®ã®ã»ã°ã¡ã³ãã«åãŸãããã«é åã䞊ã¹æ¿ããŸãã ãã®åŸãã¢ã«ãŽãªãºã ã¯æåãš2çªç®ã®ã»ã°ã¡ã³ãã§ååž°çã«ç¹°ãè¿ãããŸãã DualPivotQuicksortã¯ãé åã2ã€ã§ã¯ãªã3ã€ã®ã»ã°ã¡ã³ãã«åå²ããŸãã ãã®çµæã移åããé åèŠçŽ ã®æäœæ°ãå€§å¹ ã«åæžãããŸãã
Java 7ã§ã¯ãåç §åããœãŒãããã¢ã«ãŽãªãºã ãTimSortã«å€æŽãããŸããã
Timsortã¯ã2002幎ã«Tim Petersãå ¬éãããæ¿å ¥ãœãŒããšããŒãžãœãŒããçµã¿åããããã€ããªãããœãŒãã¢ã«ãŽãªãºã ã§ãã Timsortã¯çŸåšãPythonãOpenJDK 7ã®æšæºã®ãœãŒãã¢ã«ãŽãªãºã ã§ãããAndroid JDK 1.5ã«å®è£ ãããŠããŸãã ã¢ã«ãŽãªãºã ã®äž»ãªã¢ã€ãã¢ã¯ãçŸå®ã®äžçã§ã¯ããœãŒããããããŒã¿é åã«é åºä»ããµãé åãå«ãŸããããšãå€ããšããããšã§ãã ãã®ãããªããŒã¿ã«ãããTimsortã¯å€ãã®ãœãŒãã¢ã«ãŽãªãºã ãããå€§å¹ ã«é«éã§ãã
ãã£ã ãœãŒãã¯é«éã§ãããã©ã³ãã ããŒã¿ã§ã¯é«éãœãŒããããçŽ30ïŒ å£ã£ãŠããŸãã
2ã€ã®ãã¬ãŒã ã¯ãŒã¯ã§ã®ãœãŒãã®å®è£ ã«ããããã®éããã©ãæããŸããïŒ ã¡ã¢ãªã«è²»ããå¿ èŠã®ããå®éã®ã¿ã¹ã¯ã«å®å®æ§ãæ¬åœã«å¿ èŠãªã®ããããã¯Javaã§ã©ã®ããã«è¡ãããã®ãïŒ ãŸãã¯ã.NETã§è¡ãããŠããé床ãšã¡ã¢ãªã®ç¯çŽãšåŒãæãã«ãå®å®æ§ãªãã§å®è¡ã§ããŸããïŒ å人çã«ã¯ã.NETãéžæããŸããå®å®æ§ã¯ãçºçããç¹å®ã®ã¿ã¹ã¯ã§ã®ã¿å¿ èŠã§ãããããã»ã©é »ç¹ã§ã¯ãªããããå°ãªããšã4幎以äžã¯ç«ã¡äžãã£ãŠããªãããã§ããåé¡ã¯ããã°ã©ãã®è©ã«ãããå¯èœæ§ããããŸããå®å®ãããœãŒãã¢ã«ãŽãªãºã ãå®è£ ããããšã¯é£ãããªããšæããŸãã
ãããã«
ããããããã¹ãŠã®ããã°ã©ããŒã.NETã«ã€ããŠãã®ãããªè©³çŽ°ãå¿ èŠãšããããã§ã¯ãããŸãããã圌ãã®ç¥èã¯èª°ãå·ã€ããªããšæããŸããæŽç·Žãããã€ã³ã¿ãã¥ã¢ãŒã¯ãé¢æ¥ã§ã®ãœãŒãã«ã€ããŠè³ªåããããšãã§ããŸããäžè¬çã«ãèªãã§ãããŠããããšãããã®èšäºãã圹ã«ç«ãŠã°å¹žãã§ãã