• 排序陷阱 List.Sort Linq.OrderBy


    C#框架里面主要提供了两种排序方式:Array.Sort Linq.Orderby。
    List.Sort排序简介
    有许多猿猴对Sort原理进行了剖析,Sort排序实际上分为两部分,基于ClR内部排序,基于算法:深度限制快速排序(DepthLimitQuickSort)。基于CLR排序是针对内置类型排序;深度限制快速排序是先快速排序,达到一定深度时,更改为堆排序。核心代码如下:
    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);
    }
    说明:
      1 使用Sort排序时,有可能会打破数组列表的基本顺序。在数据相同的项具有不同含义时,不能使用Sort排序。
      2 Array.Sort和List.Sort采用的是同一个排序方法。
     
    Linq.Orderby排序简介
    Orderby使用的快速排序,它不会破坏数组列表的基本顺序。排序核心代码如下:
    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);
    }
    说明:
    1 一般情况下,业务相关的排序过程是不存在相同情况的。所以这个排序陷阱可以忽略
    2 如果需要多个阶段的排序实现最终逻辑,且存在排序的位置相同情况时,不建议使用Array.Sort
  • 相关阅读:
    [转载]vue中全局和局部引入批量组件方法
    [转]详解在vue-test-utils中mock全局对象
    [转]imageMagick 在nodejs中报错Error: spawn identify ENOENT的解决方案
    使用 dva 如何配置异步加载路由组件
    dva.js 上手
    [转]axios的兼容性处理
    【转】链接伪类(:hover)CSS背景图片有闪动BUG
    【转】 svn: Server sent unexpected return value (403 Forbidden) in response to CHECKOUT request for-解决方法
    vue 路由相同路径跳转报错
    新手小白第一次与后端联调
  • 原文地址:https://www.cnblogs.com/foreverme/p/5803149.html
Copyright © 2020-2023  润新知