麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

.NetFramework4.0內(nèi)部排序探索

2019-11-14 13:48:31
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

簡(jiǎn)介

一時(shí)好奇心起,想一窺.Net Framework 4.0內(nèi)部究竟是使用何種算法排序。以前聽(tīng)人說(shuō)Framework內(nèi)部是使用的快速排序,但究竟耳聽(tīng)為虛,眼見(jiàn)為實(shí)。主要通過(guò)JetBrains dotPeek 1.2作為工具反編譯Framework的代碼進(jìn)行查看,也參考了其他很多資料。本人才疏學(xué)淺,其中難免存在錯(cuò)誤,希望大家不吝指教。

數(shù)組

眾所周知,數(shù)組實(shí)質(zhì)上是Array類(lèi)的實(shí)例。呃,要是被代表了,可以通過(guò)如下方式驗(yàn)證:

  1. Snap1
  2. Snap1

數(shù)組排序方法

初一看,數(shù)組的排序方法似乎很多,如下圖:

Snap2

但是只要我們?cè)僬J(rèn)真分析一下,可以發(fā)現(xiàn)可以根據(jù)是否為泛型,是否帶關(guān)鍵字?jǐn)?shù)組將排序方法分成4類(lèi),其余的全是重載方法。即:

public static void Sort<T>(T[] array);public static void Sort(Array array);public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items);public static void Sort(Array keys[], Array items);

重載方法包含的參數(shù)有:

  • int index,從指定索引位置開(kāi)始排序
  • int length,從指定索引位置開(kāi)始,需要排序的元素的個(gè)數(shù)
  • ICompare<T> comparer,排序時(shí)進(jìn)行比較的對(duì)象
  • Comparison<T> comparison,排序時(shí)用于比較的委托

非泛型不帶關(guān)鍵字?jǐn)?shù)組排序方法

4種方法內(nèi)部探究

這一系列共有4個(gè)方法:

[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)][__DynamicallyInvokable]public static void Sort(Array array){  if (array == null)    throw new ArgumentNullException("array");  Array.Sort(array, null, array.GetLowerBound(0), array.Length, null);}
 
[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)][__DynamicallyInvokable][TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]public static void Sort(Array array, int index, int length){  Array.Sort(array, null, index, length, null);}
 
[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)][__DynamicallyInvokable]public static void Sort(Array array, IComparer comparer){  if (array == null)    throw new ArgumentNullException("array");  Array.Sort(array, null, array.GetLowerBound(0), array.Length, comparer);}
[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)][__DynamicallyInvokable][TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]public static void Sort(Array array, int index, int length, IComparer comparer){  Array.Sort(array, null, index, length, comparer);}  

比較這4個(gè)方法,發(fā)現(xiàn)其歸根到底都調(diào)用了非泛型不帶關(guān)鍵字?jǐn)?shù)組排序方法:

[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)][SecuritySafeCritical]public static void Sort(Array keys, Array items, int index, int length, IComparer comparer){  if (keys == null)    throw new ArgumentNullException("keys");  if (keys.Rank != 1 || items != null && items.Rank != 1)    throw new RankException(Environment.GetResourceString("Rank_MultiDimNotSupported"));  if (items != null && keys.GetLowerBound(0) != items.GetLowerBound(0))    throw new ArgumentException(Environment.GetResourceString("Arg_LowerBoundsMustMatch"));  if (index < keys.GetLowerBound(0) || length < 0)    throw new ArgumentOutOfRangeException(length < 0 ? "length" : "index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));  if (keys.Length - (index - keys.GetLowerBound(0)) < length || items != null && index - items.GetLowerBound(0) > items.Length - length)    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));  if (length <= 1 || (comparer == Comparer.Default || comparer == null) && Array.TrySZSort(keys, items, index, index + length - 1))    return;  object[] keys1 = keys as object[];  object[] items1 = null;  if (keys1 != null)    items1 = items as object[];  if (keys1 != null && (items == null || items1 != null))    new Array.SorterObjectArray(keys1, items1, comparer).Sort(index, length);  else    new Array.SorterGenericArray(keys, items, comparer).Sort(index, length);}

閱讀代碼,我們可以發(fā)現(xiàn)會(huì)首先嘗試Array的TrySZSort方法,成功則直接返回。接著當(dāng)關(guān)鍵字?jǐn)?shù)組為object[]且項(xiàng)數(shù)組為空或項(xiàng)數(shù)組也為object[]時(shí),將會(huì)調(diào)用SorterObjectArray的排序方法,否則調(diào)用SorterGenericArray的排序方法

TrySZSort方法

TrySZSort的方法代碼如下:

[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail), SecurityCritical][MethodImpl(MethodImplOptions.InternalCall)]PRivate static extern bool TrySZSort(Array keys, Array items, int left, int right);

可以發(fā)現(xiàn)該方法由CLR內(nèi)部實(shí)現(xiàn),但是好在現(xiàn)在CoreCLR已經(jīng)開(kāi)源了,我們可以通過(guò)CoreCLR大致了解到這個(gè)函數(shù)是做什么的。經(jīng)過(guò)查找,發(fā)現(xiàn)在一個(gè)名叫ArrayHelper的類(lèi)中發(fā)現(xiàn)該發(fā)現(xiàn),代碼如下:

FCIMPL4(FC_BOOL_RET, ArrayHelper::TrySZSort, ArrayBase * keys, ArrayBase * items, UINT32 left, UINT32 right)    FCALL_CONTRACT;    VALIDATEOBJECT(keys);    VALIDATEOBJECT(items);    _ASSERTE(keys != NULL);    // <TODO>@TODO: Eventually, consider adding support for single dimension arrays with    // non-zero lower bounds.  VB might care.  </TODO>    if (keys->GetRank() != 1 || keys->GetLowerBoundsPtr()[0] != 0)        FC_RETURN_BOOL(FALSE);    _ASSERTE(left <= right);    _ASSERTE(right < keys->GetNumComponents() || keys->GetNumComponents() == 0);    TypeHandle keysTH = keys->GetArrayElementTypeHandle();    const CorElementType keysElType = keysTH.GetVerifierCorElementType();    if (!CorTypeInfo::IsPrimitiveType_NoThrow(keysElType))        FC_RETURN_BOOL(FALSE);    if (items != NULL) {        TypeHandle itemsTH = items->GetArrayElementTypeHandle();        if (keysTH != itemsTH)            FC_RETURN_BOOL(FALSE);   // Can't currently handle sorting different types of arrays.    }    // Handle special case of a 0 element range to sort.    // Consider both Sort(array, x, x) and Sort(zeroLen, 0, zeroLen.Length-1);    if (left == right || right == 0xffffffff)        FC_RETURN_BOOL(TRUE);    switch(keysElType) {    case ELEMENT_TYPE_I1:        ArrayHelpers<I1>::IntrospectiveSort((I1*) keys->GetDataPtr(), (I1*) (items == NULL ? NULL : items->GetDataPtr()), left, right);        break;    case ELEMENT_TYPE_U1:    case ELEMENT_TYPE_BOOLEAN:        ArrayHelpers<U1>::IntrospectiveSort((U1*) keys->GetDataPtr(), (U1*) (items == NULL ? NULL : items->GetDataPtr()), left, right);        break;    case ELEMENT_TYPE_I2:        ArrayHelpers<I2>::IntrospectiveSort((I2*) keys->GetDataPtr(), (I2*) (items == NULL ? NULL : items->GetDataPtr()), left, right);        break;    case ELEMENT_TYPE_U2:    case ELEMENT_TYPE_CHAR:        ArrayHelpers<U2>::IntrospectiveSort((U2*) keys->GetDataPtr(), (U2*) (items == NULL ? NULL : items->GetDataPtr()), left, right);        break;    case ELEMENT_TYPE_I4:        ArrayHelpers<I4>::IntrospectiveSort((I4*) keys->GetDataPtr(), (I4*) (items == NULL ? NULL : items->GetDataPtr()), left, right);        break;    case ELEMENT_TYPE_U4:        ArrayHelpers<U4>::IntrospectiveSort((U4*) keys->GetDataPtr(), (U4*) (items == NULL ? NULL : items->GetDataPtr()), left, right);        break;            case ELEMENT_TYPE_R4:    {        R4 * R4Keys = (R4*) keys->GetDataPtr();        R4 * R4Items = (R4*) (items == NULL ? NULL : items->GetDataPtr());        // Comparison to NaN is always false, so do a linear pass         // and swap all NaNs to the front of the array        left = ArrayHelpers<R4>::NaNPrepass(R4Keys, R4Items, left, right);        if(left != right) ArrayHelpers<R4>::IntrospectiveSort(R4Keys, R4Items, left, right);        break;    };    case ELEMENT_TYPE_I8:        ArrayHelpers<I8>::IntrospectiveSort((I8*) keys->GetDataPtr(), (I8*) (items == NULL ? NULL : items->GetDataPtr()), left, right);        break;    case ELEMENT_TYPE_U8:        ArrayHelpers<U8>::IntrospectiveSort((U8*) keys->GetDataPtr(), (U8*) (items == NULL ? NULL : items->GetDataPtr()), left, right);        break;    case ELEMENT_TYPE_R8:    {        R8 * R8Keys = (R8*) keys->GetDataPtr();        R8 * R8Items = (R8*) (items == NULL ? NULL : items->GetDataPtr());        // Comparison to NaN is always false, so do a linear pass         // and swap all NaNs to the front of the array        left = ArrayHelpers<R8>::NaNPrepass(R8Keys, R8Items, left, right);        if(left != right) ArrayHelpers<R8>::IntrospectiveSort(R8Keys, R8Items, left, right);        break;    };    case ELEMENT_TYPE_I:    case ELEMENT_TYPE_U:        // 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.          FC_RETURN_BOOL(FALSE);    default:        _ASSERTE(!"Unrecognized primitive type in ArrayHelper::TrySZSort");        FC_RETURN_BOOL(FALSE);    }    FC_RETURN_BOOL(TRUE);FCIMPLEND

大致可以看出,該方法的作用是對(duì)Framework的基本類(lèi)型進(jìn)行排序,排序也使用了內(nèi)省排序。內(nèi)省排序詳見(jiàn)后面。

SorterObjectArray

我們來(lái)看一下SorterObjectArray的構(gòu)造函數(shù)及Sort方法:

private object[] keys;private object[] items;private IComparer comparer;internal SorterObjectArray(object[] keys, object[] items, IComparer comparer){    if (comparer == null)    {        comparer = Comparer.Default;    }    this.keys = keys;    this.items = items;    this.comparer = comparer;}

構(gòu)造函數(shù)很簡(jiǎn)單,僅僅賦值字段

internal void Sort(int left, int length){    if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)    {        this.IntrospectiveSort(left, length);        return;    }    this.DepthLimitedQuickSort(left, length + left - 1, 32);}

初看一下代碼 ,發(fā)現(xiàn)關(guān)鍵語(yǔ)句是BinaryCompatibility.TargetsAtLeast_Desktop_V4_5,其決定了究竟使用了哪種排序方式。從字面意思上是說(shuō)是否為桌面版本4.5及以上,經(jīng)過(guò)驗(yàn)證后也確實(shí)如此,但因?yàn)榕c主題關(guān)系不大,就不細(xì)說(shuō),僅簡(jiǎn)單說(shuō)下原理。

編譯器在編譯程序集時(shí),會(huì)加上TargetFramework特性,.Network Framework通過(guò)檢測(cè)該特性來(lái)確定框架版本,如下是4.0的一個(gè)程序集示例:

Snap3

SorterObjectArray的DepthLimitedQuickSort

DepthLimitedQuickSort從字面意思來(lái)看,是深度限制快速排序,其代碼如下:

private void DepthLimitedQuickSort(int left, int right, int depthLimit)            {                do                {                    if (depthLimit == 0)                    {                        try                        {                            this.Heapsort(left, right);                            break;                        }                        catch (IndexOutOfRangeException)                        {                            throw new ArgumentException(Environment.GetResourceString("Arg_BogusIComparer", new object[]                            {                                this.comparer                            }));                        }                        catch (Exception innerException)                        {                            throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), innerException);                        }                    }                    int num = left;                    int num2 = right;                    int median = Array.GetMedian(num, num2);                    try                    {                        this.SwapIfGreaterWithItems(num, median);                        this.SwapIfGreaterWithItems(num, num2);                        this.SwapIfGreaterWithItems(median, num2);                    }                    catch (Exception innerException2)                    {                        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), innerException2);                    }                    object obj = this.keys[median];                    do                    {                        try                        {                            while (this.comparer.Compare(this.keys[num], obj) < 0)                            {                                num++;                            }                            while (this.comparer.Compare(obj, this.keys[num2]) < 0)                            {                                num2--;                            }                        }                        catch (IndexOutOfRangeException)                        {                            throw new ArgumentException(Environment.GetResourceString("Arg_BogusIComparer", new object[]                            {                                this.comparer                            }));                        }                        catch (Exception innerException3)                        {                            throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), innerException3);                        }                        if (num > num2)                        {                            break;                        }                        if (num < num2)                        {                            object obj2 = this.keys[num];                            this.keys[num] = this.keys[num2];                            this.keys[num2] = obj2;                            if (this.items != null)                            {                                object obj3 = this.items[num];                                this.items[num] = this.items[num2];                                this.items[num2] = obj3;                            }                        }                        num++;                        num2--;                    }                    while (num <= num2);                    depthLimit--;                    if (num2 - left <= right - num)                    {                        if (left < num2)                        {                            this.DepthLimitedQuickSort(left, num2, depthLimit);                        }                        left = num;                    }                    else                    {                        if (num < right)                        {                            this.DepthLimitedQuickSort(num, right, depthLimit);                        }                        right = num2;                    }                }                while (left < right);            }

調(diào)用時(shí)深度為32,每調(diào)用一次,深度減1,深度大于0時(shí)使用快速排序,當(dāng)深度為0時(shí)即轉(zhuǎn)入堆排序。在使用快速排序時(shí),選取首、尾和首尾中間三個(gè)索引中取值為中間的對(duì)象作為主元。然后取左右兩邊較長(zhǎng)的序列進(jìn)入下一輪快速排序。

用到的其余代碼如下:

internal void SwapIfGreaterWithItems(int a, int b){    if (a != b && this.comparer.Compare(this.keys[a], this.keys[b]) > 0)    {        object obj = this.keys[a];        this.keys[a] = this.keys[b];        this.keys[b] = obj;        if (this.items != null)        {            object obj2 = this.items[a];            this.items[a] = this.items[b];            this.items[b] = obj2;        }    }}private void Swap(int i, int j){    object obj = this.keys[i];    this.keys[i] = this.keys[j];    this.keys[j] = obj;    if (this.items != null)    {        object obj2 = this.items[i];        this.items[i] = this.items[j];        this.items[j] = obj2;    }}
private void Heapsort(int lo, int hi){    int num = hi - lo + 1;    for (int i = num / 2; i >= 1; i--)    {        this.DownHeap(i, num, lo);    }    for (int j = num; j > 1; j--)    {        this.Swap(lo, lo + j - 1);        this.DownHeap(1, j - 1, lo);    }}private void DownHeap(int i, int n, int lo){    object obj = this.keys[lo + i - 1];    object obj2 = (this.items != null) ? this.items[lo + i - 1] : null;    while (i <= n / 2)    {        int num = 2 * i;        if (num < n && this.comparer.Compare(this.keys[lo + num - 1], this.keys[lo + num]) < 0)        {            num++;        }        if (this.comparer.Compare(obj, this.keys[lo + num - 1]) >= 0)        {            break;        }        this.keys[lo + i - 1] = this.keys[lo + num - 1];        if (this.items != null)        {            this.items[lo + i - 1] = this.items[lo + num - 1];        }        i = num;    }    this.keys[lo + i - 1] = obj;    if (this.items != null)    {        this.items[lo + i - 1] = obj2;    }}

SorterObjectArray的IntrospectiveSort

IntrospectiveSort的代碼如下:

private void IntrospectiveSort(int left, int length){    if (length < 2)    {        return;    }    try    {        this.IntroSort(left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(this.keys.Length));    }    catch (IndexOutOfRangeException)    {        IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(this.comparer);    }    catch (Exception innerException)    {        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), innerException);    }}private void IntroSort(int lo, int hi, int depthLimit){    while (hi > lo)    {        int num = hi - lo + 1;        if (num <= 16)        {            if (num == 1)            {                return;            }            if (num == 2)            {                this.SwapIfGreaterWithItems(lo, hi);                return;            }            if (num == 3)            {                this.SwapIfGreaterWithItems(lo, hi - 1);                this.SwapIfGreaterWithItems(lo, hi);                this.SwapIfGreaterWithItems(hi - 1, hi);                return;            }            this.InsertionSort(lo, hi);            return;        }        else        {            if (depthLimit == 0)            {                this.Heapsort(lo, hi);                return;            }            depthLimit--;            int num2 = this.PickPivotAndPartition(lo, hi);            this.IntroSort(num2 + 1, hi, depthLimit);            hi = num2 - 1;        }    }}private int PickPivotAndPartition(int lo, int hi){    int num = lo + (hi - lo) / 2;    this.SwapIfGreaterWithItems(lo, num);    this.SwapIfGreaterWithItems(lo, hi);    this.SwapIfGreaterWithItems(num, hi);    object obj = this.keys[num];    this.Swap(num, hi - 1);    int i = lo;    int num2 = hi - 1;    while (i < num2)    {        while (this.comparer.Compare(this.keys[++i], obj) < 0)        {        }        while (this.comparer.Compare(obj, this.keys[--num2]) < 0)        {        }        if (i >= num2)        {            break;        }        this.Swap(i, num2);    }    this.Swap(i, hi - 1);    return i;}

在其中用到的FloorLog2代碼如下:

internal static int FloorLog2(int n){    int num = 0;    while (n >= 1)    {        ++num;        n /= 2;    }    return num;}

其余用到的方法請(qǐng)參見(jiàn)上面的DepthLimitedQuickSort,初始深度為長(zhǎng)度的2的對(duì)數(shù)取下界的2倍,其流程圖如下:

Snap4

SorterObjectArray排序的總結(jié)

可以看到,不論是DepthLimitedQuickSort還是IntrospectiveSort,都是內(nèi)省排序的變種。內(nèi)省排序是一種混合排序算法,以快速排序開(kāi)始并在超過(guò)一定的遞歸深度后轉(zhuǎn)換為堆排序。解決了快速排序在最壞情況下時(shí)間復(fù)雜度變?yōu)镺(n2)的問(wèn)題。隨便說(shuō)一句,在STL中也使用了內(nèi)省排序。

至于遞歸深度的選擇,在Framework 4.5以上,是Snap7,以下是32。這正是O(n log n) 。對(duì)于32來(lái)說(shuō),2的32方是4G,而CLR上運(yùn)行的程序分配的內(nèi)存不為超過(guò)2G。(不要問(wèn)我是怎么知道的,我們的項(xiàng)目大約在超過(guò)1.2個(gè)G的時(shí)候崩潰過(guò),當(dāng)然在不同情況下最大可用內(nèi)存不一樣)

SorterGenericArray

SorterGenericArray與SorterObjectArray基本一樣,只是將在SorterObjectArray的索引器替換Array的GetValue和SetValue。就不再細(xì)說(shuō)了。

非泛型帶關(guān)鍵字?jǐn)?shù)組排序方法

從上面也可以看出,非泛型不帶關(guān)鍵字?jǐn)?shù)組排序方法本質(zhì)上正是調(diào)用的非泛型帶關(guān)鍵字?jǐn)?shù)組排序的public static void Sort(Array array, int index, int length, IComparer comparer)方法,而非泛型帶關(guān)鍵值數(shù)組的其余三個(gè)方法本質(zhì)也同樣是調(diào)用該方法,而該方法在前面已經(jīng)分析過(guò)了,就不再說(shuō)了。

泛型不帶關(guān)鍵字?jǐn)?shù)組排序方法

泛型不帶關(guān)鍵字?jǐn)?shù)組排序方法共5個(gè),而最終調(diào)用的是public static void Sort<T>(T[] array, int index, int length, IComparer<T> comparer)這個(gè)方法。該方法如下:

[SecuritySafeCritical][ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)][__DynamicallyInvokable]public static void Sort<T>(T[] array, int index, int length, IComparer<T> comparer){  if (array == null)    throw new ArgumentNullException("array");  if (index < 0 || length < 0)    throw new ArgumentOutOfRangeException(length < 0 ? "length" : "index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));  if (array.Length - index < length)    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));  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);}

查看ArraySortHelper<T>代碼,發(fā)現(xiàn)該類(lèi)代碼也與泛型不帶關(guān)鍵字?jǐn)?shù)組排序方法邏輯完全一致,就不再細(xì)說(shuō)了。

泛型帶關(guān)鍵字?jǐn)?shù)組排序方法

泛型帶關(guān)鍵字?jǐn)?shù)組排序方法共4個(gè),而最終調(diào)用的是public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length, IComparer<TKey> comparer)這個(gè)方法。該方法如下:

[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)][SecuritySafeCritical]public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length, IComparer<TKey> comparer){  if (keys == null)    throw new ArgumentNullException("keys");  if (index < 0 || length < 0)    throw new ArgumentOutOfRangeException(length < 0 ? "length" : "index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));  if (keys.Length - index < length || items != null && index > items.Length - length)    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));  if (length <= 1 || (comparer == null || comparer == Comparer<TKey>.Default) && Array.TrySZSort((Array) keys, (Array) items, index, index + length - 1))    return;  if (items == null)    Array.Sort<TKey>(keys, index, length, comparer);  else    ArraySortHelper<TKey, TValue>.Default.Sort(keys, items, index, length, comparer);}

該方法在items為空時(shí)直接調(diào)用泛型帶關(guān)鍵字?jǐn)?shù)組排序方法,在其他情況下調(diào)用ArraySortHelper<TKey, TValue>的排序方法。

查看ArraySortHelper<TKey, TValue>的代碼,發(fā)現(xiàn)該類(lèi)代碼也與泛型帶關(guān)鍵字?jǐn)?shù)組排序方法邏輯完全一致,就不再細(xì)說(shuō)了。

ArrayList

ArrayList這貨雖然現(xiàn)在很少用了,但是畢竟了曾風(fēng)光了一段時(shí)間,還是提一下,通過(guò)查看其代碼,發(fā)現(xiàn)底層還是調(diào)用的Array的非泛型不帶關(guān)鍵字?jǐn)?shù)組的排序方法。這也不奇怪,跟List一樣,底層用的都是數(shù)組。

public virtual void Sort(int index, int count, IComparer comparer){    if (index < 0)    {        throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));    }    if (count < 0)    {        throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));    }    if (this._size - index < count)    {        throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));    }    Array.Sort(this._items, index, count, comparer);    this._version++;}

List

跟ArrayList類(lèi)似,其底層調(diào)用的是Array的泛型不帶關(guān)鍵字?jǐn)?shù)組的排序方法。代碼如下:

public void Sort(int index, int count, IComparer<T> comparer){  if (index < 0)    ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);  if (count < 0)    ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);  if (this._size - index < count)    ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);  Array.Sort<T>(this._items, index, count, comparer);  ++this._version;}
[__DynamicallyInvokable]public void Sort(Comparison<T> comparison){  if (comparison == null)    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);  if (this._size <= 0)    return;  Array.Sort<T>(this._items, 0, this._size, (IComparer<T>) new Array.FunctorComparer<T>(comparison));}

Linq排序

OrderBy與OrderByDescending

通過(guò)查看代碼,發(fā)現(xiàn)OrderBy與OrderByDescending基本一致,都使用了OrderedEnumerable<TSource, TKey>類(lèi),代碼如下:

[__DynamicallyInvokable]public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector){  return (IOrderedEnumerable<TSource>) new OrderedEnumerable<TSource, TKey>(source, keySelector, (IComparer<TKey>) null, false);}[__DynamicallyInvokable]public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer){  return (IOrderedEnumerable<TSource>) new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, false);}[__DynamicallyInvokable]public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector){  return (IOrderedEnumerable<TSource>) new OrderedEnumerable<TSource, TKey>(source, keySelector, (IComparer<TKey>) null, true);}[__DynamicallyInvokable]public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer){  return (IOrderedEnumerable<TSource>) new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, true);}

而OrderedEnumerable<TSource, TKey>繼承自O(shè)rderedEnumerable<TElement>,OrderedEnumerable<TSource, TKey>中排序使用了EnumerableSorter<TElement, TKey>,而EnumerableSorter<TElement, TKey>繼承自EnumerableSorter<TElement>。在EnumerableSorter<TElement>我們可以發(fā)現(xiàn)排序的關(guān)鍵代碼:

internal int[] Sort(TElement[] elements, int count){  this.ComputeKeys(elements, count);  int[] map = new int[count];  for (int index = 0; index < count; ++index)    map[index] = index;  this.QuickSort(map, 0, count - 1);  return map;}private void QuickSort(int[] map, int left, int right){  do  {    int left1 = left;    int right1 = right;    int index1 = map[left1 + (right1 - left1 >> 1)];    while (true)    {      do      {        if (left1 >= map.Length || this.CompareKeys(index1, map[left1]) <= 0)        {          while (right1 >= 0 && this.CompareKeys(index1, map[right1]) < 0)            --right1;          if (left1 <= right1)          {            if (left1 < right1)            {              int num = map[left1];              map[left1] = map[right1];              map[right1] = num;            }            ++left1;            --right1;          }          else            break;        }        else          goto label_1;      }      while (left1 <= right1);      break;label_1:      ++left1;    }    if (right1 - left <= right - left1)    {      if (left < right1)        this.QuickSort(map, left, right1);      left = left1;    }    else    {      if (left1 < right)        this.QuickSort(map, left1, right);      right = right1;    }  }  while (left < right);}

原來(lái)是快速排序。

ThenBy和ThenByDescending

查看代碼,發(fā)現(xiàn)ThenBy和ThenByDescending基本一致,都是傳入IOrderedEnumerable<TSource>,返回其CreateOrderedEnumerable方法調(diào)用。

[__DynamicallyInvokable]public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector){ if (source == null) throw Error.ArgumentNull("source"); else    return source.CreateOrderedEnumerable<TKey>(keySelector, (IComparer<TKey>) null, false);}[__DynamicallyInvokable]public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer){ if (source == null) throw Error.ArgumentNull("source"); else    return source.CreateOrderedEnumerable<TKey>(keySelector, comparer, false);}[__DynamicallyInvokable]public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector){ if (source == null) throw Error.ArgumentNull("source"); else    return source.CreateOrderedEnumerable<TKey>(keySelector, (IComparer<TKey>) null, true);}[__DynamicallyInvokable]public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer){ if (source == null) throw Error.ArgumentNull("source"); else    return source.CreateOrderedEnumerable<TKey>(keySelector, comparer, true);}

而在上面,我們已經(jīng)發(fā)現(xiàn)了OrderBy與OrderByDescending都返回了OrderedEnumerable<TSource, TKey>,在其中找到CreateOrderedEnumerable方法。

IOrderedEnumerable<TElement> IOrderedEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending){  OrderedEnumerable<TElement, TKey> orderedEnumerable = new OrderedEnumerable<TElement, TKey>(this.source, keySelector, comparer, descending);  orderedEnumerable.parent = this;  return (IOrderedEnumerable<TElement>) orderedEnumerable;}

這說(shuō)明正是在前面排序的基礎(chǔ)上進(jìn)行再次排序。

參考資料

C#集合--數(shù)組 - On the road.... - 博客園

比較排序算法 - 匠心十年 - 博客園

Introsort - Wikipedia, the free encyclopedia:

一并予以感謝


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 久久91精品国产91久久yfo | 欧美精品免费一区二区三区 | 毛片免费观看完整版 | www久久久久久 | 亚州视频在线 | 国产精品久久久久久久久久久久久久久久 | 国产精品手机在线亚洲 | 精品成人在线观看 | 国产外围在线 | 久久精品无码一区二区三区 | 久久99精品久久久久久国产越南 | 欧美性受xxxx白人性爽 | 模特三级在线观看 | 嗯哈~不行好大h双性 | 在线播放h | 成人精品aaaa网站 | 日韩精品久久久久久 | 一级看片免费视频 | 国产精品成人亚洲一区二区 | 92看片淫黄大片欧美看国产片 | 主播粉嫩国产在线精品 | 4p一女两男做爰在线观看 | 久久久日韩av免费观看下载 | 国内毛片视频 | 中文字幕xxx | 911色_911色sss主站色播 | 吾色视频| 中国免费一级毛片 | 久久国产中文 | 亚洲精品久久久久www | 午夜精品福利视频 | 毛片国产| 高潮激情aaaaa免费看 | 亚洲va久久久噜噜噜久牛牛影视 | 国产人成精品一区二区三 | 久久不射电影 | 日韩视频一区二区三区四区 | 1024亚洲天堂 | 成人福利免费在线观看 | 羞羞视频免费网站含羞草 | 欧美三级日本三级少妇99 |