简体   繁体   English

.NET的`Array.Sort()`方法使用的排序算法是一种稳定的算法吗?

[英]Is the sorting algorithm used by .NET's `Array.Sort()` method a stable algorithm?

.NET的Array.Sort()方法使用的排序算法是一种稳定的算法吗?

From MSDN : 来自MSDN

This implementation performs an unstable sort; 此实现执行不稳定的排序; that is, if two elements are equal, their order might not be preserved. 也就是说,如果两个元素相等,则可能不会保留它们的顺序。 In contrast, a stable sort preserves the order of elements that are equal. 相反,稳定的排序保留了相等元素的顺序。

The sort uses introspective sort. 排序使用内省排序。 (Quicksort in version 4.0 and earlier of the .NET framework). (Quicksort在4.0及更早版本的.NET框架中)。

If you need a stable sort, you can use Enumerable.OrderBy . 如果需要稳定排序,可以使用Enumerable.OrderBy

Adding to Rasmus Faber's answer 加入Rasmus Faber的回答 ......

Sorting in LINQ, via Enumerable.OrderBy and Enumerable.ThenBy , is a stable sort implementation, which can be used as an alternative to Array.Sort . LINQ中的排序,通过Enumerable.OrderByEnumerable.ThenBy ,是一个稳定的排序实现,可以用作Array.Sort的替代。 From Enumerable.OrderBy documentation over at MSDN : 来自MSDN上的Enumerable.OrderBy文档

This method performs a stable sort; 该方法执行稳定的排序; that is, if the keys of two elements are equal, the order of the elements is preserved. 也就是说,如果两个元素的键相等,则保留元素的顺序。 In contrast, an unstable sort does not preserve the order of elements that have the same key. 相反,不稳定的排序不会保留具有相同键的元素的顺序。

Also, any unstable sort implementation, like that of Array.Sort , can be stabilized by using the position of the elements in the source sequence or array as an additional key to serve as a tie-breaker. 此外,任何不稳定的排序实现(如Array.Sort )都可以通过使用源序列或数组中元素的位置作为附加键来稳定,以作为平局。 Below is one such implementation, as a generic extension method on any single-dimensional array and which turns Array.Sort into a stable sort: 下面是一个这样的实现,作为任Array.Sort数组上的通用扩展方法,并将Array.Sort转换为稳定的排序:

using System;
using System.Collections.Generic;

public static class ArrayExtensions {

    public static void StableSort<T>(this T[] values, Comparison<T> comparison) {
        var keys = new KeyValuePair<int, T>[values.Length];
        for (var i = 0; i < values.Length; i++)
            keys[i] = new KeyValuePair<int, T>(i, values[i]);
        Array.Sort(keys, values, new StabilizingComparer<T>(comparison));
    }

    private sealed class StabilizingComparer<T> : IComparer<KeyValuePair<int, T>> 
    {
        private readonly Comparison<T> _comparison;

        public StabilizingComparer(Comparison<T> comparison) {
            _comparison = comparison;
        }

        public int Compare(KeyValuePair<int, T> x, 
                           KeyValuePair<int, T> y) {
            var result = _comparison(x.Value, y.Value);
            return result != 0 ? result : x.Key.CompareTo(y.Key);
        }
    }
}

Below is a sample program using StableSort from above: 以下是使用上面的StableSort的示例程序:

static class Program 
{
    static void Main() 
    {
        var unsorted = new[] {
            new Person { BirthYear = 1948, Name = "Cat Stevens" },
            new Person { BirthYear = 1955, Name = "Kevin Costner" },
            new Person { BirthYear = 1952, Name = "Vladimir Putin" },
            new Person { BirthYear = 1955, Name = "Bill Gates" },
            new Person { BirthYear = 1948, Name = "Kathy Bates" },
            new Person { BirthYear = 1956, Name = "David Copperfield" },
            new Person { BirthYear = 1948, Name = "Jean Reno" },
        };

        Array.ForEach(unsorted, Console.WriteLine);

        Console.WriteLine();
        var unstable = (Person[]) unsorted.Clone();
        Array.Sort(unstable, (x, y) => x.BirthYear.CompareTo(y.BirthYear));
        Array.ForEach(unstable, Console.WriteLine);

        Console.WriteLine();
        var stable = (Person[]) unsorted.Clone();
        stable.StableSort((x, y) => x.BirthYear.CompareTo(y.BirthYear));
        Array.ForEach(stable, Console.WriteLine);
    }
}

sealed class Person 
{
    public int BirthYear { get; set; }
    public string Name { get; set; }

    public override string ToString() {
        return string.Format(
            "{{ BirthYear = {0}, Name = {1} }}", 
            BirthYear, Name);
    }
}

Below is the output from the sample program above (running on a machine with Windows Vista SP1 and .NET Framework 3.5 SP1 installed): 以下是上述示例程序的输出(在安装了Windows Vista SP1和.NET Framework 3.5 SP1的计算机上运行):

{ BirthYear = 1948, Name = Cat Stevens }
{ BirthYear = 1955, Name = Kevin Costner }
{ BirthYear = 1952, Name = Vladimir Putin }
{ BirthYear = 1955, Name = Bill Gates }
{ BirthYear = 1948, Name = Kathy Bates }
{ BirthYear = 1956, Name = David Copperfield }
{ BirthYear = 1948, Name = Jean Reno }

{ BirthYear = 1948, Name = Jean Reno }
{ BirthYear = 1948, Name = Kathy Bates }
{ BirthYear = 1948, Name = Cat Stevens }
{ BirthYear = 1952, Name = Vladimir Putin }
{ BirthYear = 1955, Name = Bill Gates }
{ BirthYear = 1955, Name = Kevin Costner }
{ BirthYear = 1956, Name = David Copperfield }

{ BirthYear = 1948, Name = Cat Stevens }
{ BirthYear = 1948, Name = Kathy Bates }
{ BirthYear = 1948, Name = Jean Reno }
{ BirthYear = 1952, Name = Vladimir Putin }
{ BirthYear = 1955, Name = Kevin Costner }
{ BirthYear = 1955, Name = Bill Gates }
{ BirthYear = 1956, Name = David Copperfield }

As other answers have stated, Array.Sort isn't stable. 正如其他答案所述,Array.Sort不稳定。 However, the LINQ OrderBy methods (and OrderByDescending etc) are stable, which can be very useful. 但是,LINQ OrderBy方法(和OrderByDescending等) 稳定的,这可能非常有用。

No, it isn't : 不,它不是

This method uses the QuickSort algorithm. 此方法使用QuickSort算法。 This implementation performs an unstable sort 此实现执行不稳定的排序

UPDATE: This code not stabilizing Array.Sort (ensure that the elements are always sorted in the same order): 更新:此代码不稳定Array.Sort(确保元素始终按相同顺序排序):

public static class ComparisonExtensions
{
    public static Comparison<T> WithGetHashCode<T>(this Comparison<T> current)
    {
        return (x, y) =>
        {
            var result = current(x, y);
            if (result == 0)
                return x.GetHashCode() - y.GetHashCode();
            return result;
        };
    }
}

Use: 使用:

Comparison<Person> comparison = (x, y) => x.BirthYear.CompareTo(y.BirthYear);
Array.Sort(unstable, comparison.WithGetHashCode());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM