Random ve OrderBy kullanmak iyi bir karıştırma algoritması mıdır?


164

Coding Horror'da çeşitli shuffle algoritmaları hakkında bir makale okudum . Bir yerde insanların bir listeyi karıştırmak için bunu yaptıklarını gördüm:

var r = new Random();
var shuffled = ordered.OrderBy(x => r.Next());

Bu iyi bir karıştırma algoritması mı? Tam olarak nasıl çalışıyor? Bunu yapmanın kabul edilebilir bir yolu var mı?

Yanıtlar:


205

Sevdiğim bir karıştırma yöntemi değil, çoğunlukla O (n) n'in bir O (n) karıştırmasının uygulanması kolay olduğunda iyi bir nedeni olmadığı gerekçesiyle. Sorudaki kod, temel olarak her bir öğeye rastgele (umarım benzersiz!) Bir sayı vererek ve daha sonra öğeleri bu sayıya göre sıralayarak çalışır.

Durstenfield'ın elementleri değiştiren Fisher-Yates shuffle varyantını tercih ediyorum .

Basit bir Shuffleuzatma yönteminin uygulanması temel olarak Fisher-Yates'in mevcut bir uygulamasını kullanarak çağrılmayı ToListveya ToArraygirdiyi içerir. ( RandomHayatı genel olarak daha güzel hale getirmek için bir parametre olarak geçin.) Etrafta çok sayıda uygulama var ... Muhtemelen bir yerde bir cevap aldım.

Böyle bir uzatma yöntemi ile ilgili güzel şey, o zaman gerçekten ne yapmaya çalıştığınız okuyucuya çok açık olacaktır.

EDIT: İşte basit bir uygulama (hata denetimi yok!):

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    T[] elements = source.ToArray();
    // Note i > 0 to avoid final pointless iteration
    for (int i = elements.Length-1; i > 0; i--)
    {
        // Swap element "i" with a random earlier element it (or itself)
        int swapIndex = rng.Next(i + 1);
        T tmp = elements[i];
        elements[i] = elements[swapIndex];
        elements[swapIndex] = tmp;
    }
    // Lazily yield (avoiding aliasing issues etc)
    foreach (T element in elements)
    {
        yield return element;
    }
}

DÜZENLEME: Aşağıdaki performans hakkındaki yorumlar, öğeleri karıştırdığımızda öğeleri gerçekten döndürebileceğimizi hatırlattı:

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    T[] elements = source.ToArray();
    for (int i = elements.Length - 1; i >= 0; i--)
    {
        // Swap element "i" with a random earlier element it (or itself)
        // ... except we don't really need to swap it fully, as we can
        // return it immediately, and afterwards it's irrelevant.
        int swapIndex = rng.Next(i + 1);
        yield return elements[swapIndex];
        elements[swapIndex] = elements[i];
    }
}

Bu artık sadece ihtiyaç duyduğu kadar iş yapacak.

Her iki durumda da, aşağıdaki Randomgibi kullandığınız örneğe dikkat etmeniz gerektiğini unutmayın:

  • RandomKabaca aynı anda iki örnek oluşturmak , aynı rasgele sayı dizisini verir (aynı şekilde kullanıldığında)
  • Random güvenli değil.

Ben bir makaleRandom bu konularda daha ayrıntılı anlatır ve çözümler sağlayan.


5
Küçük ama önemli, bunun gibi şeyler için söyleyeceğim şeyler StackOverflow'da her zaman bulabilmek güzel. Yani evet lütfen, isterseniz =)
Svish

9
Jon - Fisher-Yates açıklamanız, soruda verilen uygulamaya (naif sürüm) eşdeğerdir. Durstenfeld / Knuth, ödevle değil, azalan bir kümeden ve takastan seçerek O (n) 'ye ulaşır. Bu şekilde seçilen rasgele sayı tekrarlanabilir ve algoritma sadece O (n) alır.
tvanfosson

8
Muhtemelen benden haber almaktan bıkıyorsunuz, ancak birim testlerimde farkında olmak isteyebileceğiniz hafif bir problemle karşılaştım. ElementAt ile uzantıyı her seferinde çağıran güvenilir olmayan sonuçlar veren bir tuhaflık var. Testlerimde, bundan kaçınmak için kontrol etmeden önce sonucu gerçekleştiriyorum.
tvanfosson

3
@tvanfosson: Hiç hasta değil :) Ama evet, arayanlar bunun tembel olarak değerlendirildiğinin farkında olmalıdır.
Jon Skeet

4
Biraz geç, ancak lütfen aynı dosyaya source.ToArray();sahip olmanızı gerektirir using System.Linq;. Bunu yapmazsanız, şu hatayı alırsınız:'System.Collections.Generic.IEnumerable<T>' does not contain a definition for 'ToArray' and no extension method 'ToArray' accepting a first argument of type 'System.Collections.Generic.IEnumerable<T>' could be found (are you missing a using directive or an assembly reference?)
Powerlord

70

Bu Jon Skeet'in cevabına dayanıyor .

Bu cevapta, dizi karıştırılır ve ardından döndürülür yield. Net sonuç dizinin foreach süresi boyunca bellekte tutulması ve yineleme için gerekli olan nesnelerdir ve yine de maliyet başlangıçta - verim temelde boş bir döngüdür.

Bu algoritma, ilk üç öğenin seçildiği oyunlarda çok kullanılır ve diğerlerine ancak daha sonra ihtiyaç duyulur. Benim önerim yieldtakas olur olmaz sayılara. Bu, yineleme maliyetini O (1) (temel olarak yineleme başına 5 işlem) tutarken başlangıç ​​maliyetini düşürecektir. Toplam maliyet aynı kalacak, ancak karıştırmanın kendisi daha hızlı olacaktır. Bunun collection.Shuffle().ToArray()teorik olarak hiçbir fark yaratmayacağı durumlarda, ancak yukarıda belirtilen kullanım durumlarında başlatmayı hızlandıracaktır. Ayrıca, bu, algoritmayı sadece birkaç benzersiz öğeye ihtiyacınız olan durumlarda kullanışlı hale getirir. Örneğin, 52 desteden üç kart çıkarmanız gerekirse, çağırabilirsiniz deck.Shuffle().Take(3)ve yalnızca üç takas gerçekleşir (ancak tüm dizinin önce kopyalanması gerekir).

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    T[] elements = source.ToArray();
    // Note i > 0 to avoid final pointless iteration
    for (int i = elements.Length - 1; i > 0; i--)
    {
        // Swap element "i" with a random earlier element it (or itself)
        int swapIndex = rng.Next(i + 1);
        yield return elements[swapIndex];
        elements[swapIndex] = elements[i];
        // we don't actually perform the swap, we can forget about the
        // swapped element because we already returned it.
    }

    // there is one item remaining that was not returned - we return it now
    yield return elements[0]; 
}

Ah! Bu muhtemelen kaynaktaki tüm öğeleri döndürmez. N yinelemeleri için benzersiz olan rastgele bir sayıya güvenemezsiniz.
P Daddy

2
Zeki! (Ve bu 15 karakterden nefret ediyorum ...)
Svish

@P Daddy: Ha? Ayrıntılı düşünmek ister misiniz?
Svish

1
Veya> 0'ı> = 0 ile değiştirebilir ve zorunlu değildir (buna rağmen, fazladan bir RNG isabeti artı bir yedek atama)
FryGuy

4
Başlangıç ​​maliyeti, kaynak maliyeti olarak O (N) 'dir.
Dave Hillier

8

Skeet'in bu teklifinden başlayarak:

Sevdiğim bir karıştırma yöntemi değil, çoğunlukla O (n) n'in bir O (n) karıştırması kolay olduğunda iyi bir sebep olmadığı gerekçesiyle. Sorudaki kod, temel olarak her bir öğeye rastgele ( umarım benzersiz! ) Bir sayı vererek ve daha sonra öğeleri bu sayıya göre sıralayarak çalışır.

Umarım eşsiz olmasının nedenini biraz açıklayacağım !

Şimdi, gelen Enumerable.OrderBy :

Bu yöntem kararlı bir sıralama gerçekleştirir; yani, iki öğenin tuşları eşitse, öğelerin sırası korunur

Bu çok önemli! İki öğe aynı rastgele sayıyı "alırsa" ne olur? Dizide oldukları sırayla kalırlar. Şimdi, bunun gerçekleşme olasılığı nedir? Tam olarak hesaplamak zordur, ancak tam olarak bu problem olan Doğum Günü Sorunu vardır.

Şimdi, gerçek mi? Bu doğru mu?

Her zaman olduğu gibi, şüpheye düştüğünüzde, bazı program satırları yazın: http://pastebin.com/5CDnUxPG

Bu küçük kod bloğu, geriye doğru yapılan Fisher-Yates algoritmasını kullanarak 3 öğeden oluşan bir dizi belirli bir kez karıştırır, Fisher-Yates algoritması ileriye doğru yapılır ( wiki sayfasında iki sahte kod algoritması vardır ... Eşdeğer üretirler sonuçlar, ancak biri ilk öğeden son öğeye yapılırken diğeri son öğeden ilk öğeye yapılır), http://blog.codinghorror.com/the-danger-of-naivete/ ' nin naif yanlış algoritması ve .OrderBy(x => r.Next())ve .OrderBy(x => r.Next(someValue)).

Şimdi, Rastgele .

0'dan büyük veya 0'a eşit ve MaxValue'dan küçük bir 32 bit işaretli tam sayı.

bu yüzden

OrderBy(x => r.Next(int.MaxValue))

Bu sorunun var olup olmadığını test etmek için diziyi büyütebiliriz (çok yavaş bir şey) veya rastgele sayı üretecinin maksimum değerini azaltabiliriz ( int.MaxValue"özel" bir sayı değildir ... Sadece çok büyük bir sayıdır). Sonunda, algoritma, kararlılığı ile önyargılı değilse OrderBy, herhangi bir değer aralığı aynı sonucu vermelidir.

Program daha sonra 1 ... 4096 aralığında bazı değerleri test eder. Sonuçlara bakıldığında, düşük değerler (<128) için algoritmanın çok taraflı olduğu (% 4-8) oldukça açıktır. En az 3 değer ile ihtiyacınız var r.Next(1024). Diziyi büyütürseniz (4 veya 5), ​​o zaman bile r.Next(1024)yeterli değildir. Ben karıştırma ve matematik uzmanı değilim, ama dizi uzunluğunun her ekstra bit için, maksimum değerin 2 ekstra bit gerekir (çünkü doğum günü paradoks sqrt (rakamlar) bağlı olduğundan), bu yüzden maksimum değer 2 ^ 31 ise, dizileri 2 ^ 12/2 ^ 13 bite (4096-8192 öğe) kadar sıralayabilmeniz gerektiğini söyleyeceğim


İyi ifade edilmiş ve mükemmel bir şekilde orijinal soru ile ilgili bir sorun görüntüler. Bu Jon'un cevabı ile birleştirilmelidir.
TheSoftwareJedi

6

Muhtemelen çoğu amaç için uygundur ve neredeyse her zaman gerçekten rastgele bir dağıtım oluşturur (Random.Next () iki özdeş rasgele tamsayı ürettiği durumlar hariç).

Serinin her bir elemanına rastgele bir tamsayı atayarak, bu sırayı tamsayılarla sıralayarak çalışır.

Uygulamaların% 99.9'u için tamamen kabul edilebilir (yukarıdaki kenar kasasını kesinlikle kullanmanız gerekmedikçe). Ayrıca, skeet'in çalışma zamanına itirazı geçerlidir, bu nedenle uzun bir listeyi karıştırırsanız kullanmak istemeyebilirsiniz.


4

Bu daha önce birçok kez ortaya çıktı. StackOverflow üzerinde Fisher-Yates arayın.

İşte bu algoritma için yazdığım bir C # kod örneği . İsterseniz başka bir türde parametreleştirebilirsiniz.

static public class FisherYates
{
        //      Based on Java code from wikipedia:
        //      http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
        static public void Shuffle(int[] deck)
        {
                Random r = new Random();
                for (int n = deck.Length - 1; n > 0; --n)
                {
                        int k = r.Next(n+1);
                        int temp = deck[n];
                        deck[n] = deck[k];
                        deck[k] = temp;
                }
        }
}

2
Böyle Randombir statik değişken olarak kullanmamalısınız - Randomiş parçacığı için güvenli değildir. Bkz. Csharpindepth.com/Articles/Chapter12/Random.aspx
Jon Skeet

@Jon Skeet: elbette, bu meşru bir argüman. OTOH, OP doğru olmayan bir algoritma soruyordu, oysa bu doğrudur (çok iş parçacıklı kart karıştırma kullanım durumu dışında).
hughdbrown

1
Bu sadece OP'nin yaklaşımından "daha az yanlış" olduğu anlamına gelir. Bu, çok iş parçacıklı bir bağlamda güvenli bir şekilde kullanılamayacağını anlamadan kullanılması gereken kod anlamına gelmez ... bu, bahsetmediğiniz bir şeydir. Statik elemanların birden çok iş parçacığından güvenle kullanılabileceği konusunda makul bir beklenti vardır.
Jon Skeet

@Jon Skeet: Tabii, değiştirebilirim. Bitti. Üç buçuk yıl önce bir soruya geri dönüp OP'nin algoritmadan aşırı bir şey sormadığı zaman "Bu çok iş parçacıklı kullanım durumunu işlemediği için yanlış" dediğini düşünüyorum. Cevaplarımı yıllar boyunca gözden geçirin. Genellikle belirtilen gereksinimlerin ötesine geçen OP yanıtları verdim. Bunun için eleştirildim. Yine de OP'lerin olası tüm kullanımlara uygun cevaplar almasını beklemiyordum.
hughdbrown

Bu yanıtı hiç ziyaret ettim çünkü biri beni sohbette işaret etti. OP özellikle iş parçacığından bahsetmese de , olağandışı olduğu ve kodun birçok durum için değişiklik yapılmadan uygun olmadığı için statik bir yöntem iş parçacığı için güvenli olmadığında kesinlikle bahsetmeye değer olduğunu düşünüyorum . Yeni kodunuz iş parçacığı açısından güvenlidir - ancak yine de aynı boyuttaki iki koleksiyonu karıştırmak için aynı anda "kabaca" olarak birden çok iş parçacığından çağırdığınız gibi ideal değildir. Temel olarak, Randommakalemde belirtildiği gibi , kullanılacak bir acıdır.
Jon Skeet

3

Performans konusunda endişelenmiyorsanız, iyi bir karıştırma algoritması gibi görünüyor. Belirteceğim tek sorun, davranışının kontrol edilemediğidir, bu yüzden test etmekte zorlanabilirsiniz.

Olası bir seçenek, rastgele sayı üretecine (veya parametre olarak rastgele üretecine) parametre olarak geçirilecek bir tohuma sahip olmaktır, böylece daha fazla kontrole sahip olabilir ve daha kolay test edebilirsiniz.


3

Jon Skeet'in cevabının tamamen tatmin edici olduğunu gördüm, ancak müvekkilimin robo tarayıcısı herhangi Randombir güvenlik kusuru örneğini bildirecek . Bu yüzden takas ettim System.Security.Cryptography.RNGCryptoServiceProvider. Bir bonus olarak, bahsedilen iş parçacığı güvenliği sorununu giderir. Öte yandan, RNGCryptoServiceProviderkullanmaktan 300 kat daha yavaş olarak ölçülmüştür Random.

Kullanımı:

using (var rng = new RNGCryptoServiceProvider())
{
    var data = new byte[4];
    yourCollection = yourCollection.Shuffle(rng, data);
}

Yöntem:

/// <summary>
/// Shuffles the elements of a sequence randomly.
/// </summary>
/// <param name="source">A sequence of values to shuffle.</param>
/// <param name="rng">An instance of a random number generator.</param>
/// <param name="data">A placeholder to generate random bytes into.</param>
/// <returns>A sequence whose elements are shuffled randomly.</returns>
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, RNGCryptoServiceProvider rng, byte[] data)
{
    var elements = source.ToArray();
    for (int i = elements.Length - 1; i >= 0; i--)
    {
        rng.GetBytes(data);
        var swapIndex = BitConverter.ToUInt32(data, 0) % (i + 1);
        yield return elements[swapIndex];
        elements[swapIndex] = elements[i];
    }
}

3

Bir algoritma mı arıyorsunuz? ShuffleListSınıfımı kullanabilirsiniz :

class ShuffleList<T> : List<T>
{
    public void Shuffle()
    {
        Random random = new Random();
        for (int count = Count; count > 0; count--)
        {
            int i = random.Next(count);
            Add(this[i]);
            RemoveAt(i);
        }
    }
}

Ardından, şu şekilde kullanın:

ShuffleList<int> list = new ShuffleList<int>();
// Add elements to your list.
list.Shuffle();

O nasıl çalışır?

En 5 ilk tamsayılar bir başlangıç sıralı liste atalım: { 0, 1, 2, 3, 4 }.

Yöntem, öğelerin yumrularını sayarak başlar ve onu çağırır count . Daha sonra, counther adımda azalan değer ile 0ve arasında rastgele bir sayı alır countve listenin sonuna taşır.

Aşağıdaki adım adım örnekte, taşınabilecek öğeler italiktir , seçilen öğe kalındır :

0 1 2 3 4
0 1 2 3 4
0 1 2 4 3
0 1 2 4 3
1 2 4 3 0
1 2 4 3 0
1 2 3 0 4
1 2 3 0 4
2 3 0 4 1
2 3 0 4 1
3 0 4 1 2


O (n) değil. Tek başına O (n) 'dir.
paparazzo

Hmm, haklısın gibi görünüyor, benim hatam! O parçayı çıkaracağım.
SteeveDroz

1

Bu algoritma, listedeki her değer için yeni bir rastgele değer oluşturarak ve ardından listeyi bu rastgele değerlere göre sıralayarak karıştırılır. Bunu, bellek içi bir tabloya yeni bir sütun eklemek, ardından GUID'lerle doldurmak ve ardından bu sütuna göre sıralamak olarak düşünün. Bana etkili bir yol gibi görünüyor (özellikle lambda şekeri ile!)


1

Biraz ilgisiz, ama burada gerçekten rastgele zar rulo üretimi için ilginç bir yöntem (gerçekten aşırı olmasına rağmen, gerçekten uygulandı)!

Zar-O-Matic

Bunu burada yayınlamamın nedeni, kullanıcılarının gerçek zarlar üzerinde karıştırmak için algoritmalar kullanma fikrine nasıl tepki verdikleri hakkında bazı ilginç noktalar yapmasıdır. Tabii ki, gerçek dünyada, böyle bir çözüm sadece rasgeleliğin böyle büyük bir etkiye sahip olduğu ve belki de etkinin parayı etkilediği spektrumun gerçekten aşırı uçları içindir;).


1

Burada "Bu algoritma, bir listedeki her değer için yeni bir rastgele değer oluşturarak karıştırır ve listeyi bu rastgele değerlere göre düzenleyerek karıştırır" gibi çok sayıda yanıtın çok yanlış olabileceğini söyleyebilirim!

Bunun kaynak koleksiyonunun her öğesine rastgele bir değer atamadığını düşünürdüm. Bunun yerine, Quicksort gibi çalışan ve yaklaşık olarak n oturum açma kez bir karşılaştırma fonksiyonu çağıran bir sıralama algoritması olabilir. Bazı sıralama algoritmaları gerçekten bu karşılaştırma işlevinin kararlı olmasını ve her zaman aynı sonucu döndürmesini bekler!

IEnumerableSorter, örneğin quicksort'un her bir algoritma adımı için bir karşılaştırma işlevi çağırdığı ve işlevi her çağırdığında bu olamaz x => r.Next() bunları önbelleğe almadan her iki parametre olamaz!

Bu durumda, sıralama algoritmasını gerçekten bozabilir ve algoritmanın oluşturduğu beklentilerden çok daha kötü hale getirebilirsiniz. Tabii ki, sonunda istikrarlı hale gelecek ve bir şey iade edecektir.

Daha sonra hata ayıklama çıktısını yeni bir "İleri" işlevinin içine koyarak kontrol edebilirim. Reflektör'de nasıl çalıştığını hemen bulamadım.


1
Durum böyle değil: dahili geçersiz kılma geçersiz ComputeKeys (TElement [] öğeleri, int count); Bildirme Türü: System.Linq.EnumerableSorter <TElement, TKey> Assembly: System.Core, Sürüm = 3.5.0.0 Bu işlev, quicksort bunları sıralamadan önce belleği tüketen tüm anahtarlarla bir dizi oluşturur
Christian

Bunu bilmek iyi - yine de gelecekteki sürümlerde muhtemelen değişebilecek bir uygulama detayı!
Blorgbeard

-5

Tüm iş parçacıklarını temizle ve her yeni testte önbellek kullanarak kod üzerinde çalışmaya başlama zamanı,

İlk başarısız kod. LINQPad üzerinde çalışır. Bu kodu test etmek için takip ederseniz.

Stopwatch st = new Stopwatch();
st.Start();
var r = new Random();
List<string[]> list = new List<string[]>();
list.Add(new String[] {"1","X"});
list.Add(new String[] {"2","A"});
list.Add(new String[] {"3","B"});
list.Add(new String[] {"4","C"});
list.Add(new String[] {"5","D"});
list.Add(new String[] {"6","E"});

//list.OrderBy (l => r.Next()).Dump();
list.OrderBy (l => Guid.NewGuid()).Dump();
st.Stop();
Console.WriteLine(st.Elapsed.TotalMilliseconds);

list.OrderBy (x => r.Next ()) 38.6528 ms kullanır

list.OrderBy (x => Guid.NewGuid ()) 36,7634 ms kullanır (MSDN'den önerilir.)

ikinci seferden sonra her ikisi de aynı anda kullanılır.

DÜZENLEME: Intel Core i7 4@2.1GHz üzerinde TEST KODU, Ram 8 GB DDR3 @ 1600, HDD SATA 5200 rpm ile [Veri: www.dropbox.com/s/pbtmh5s9lw285kp/data]

using System;
using System.Runtime;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Threading;

namespace Algorithm
{
    class Program
    {
        public static void Main(string[] args)
        {
            try {
                int i = 0;
                int limit = 10;
                var result = GetTestRandomSort(limit);
                foreach (var element in result) {
                    Console.WriteLine();
                    Console.WriteLine("time {0}: {1} ms", ++i, element);
                }
            } catch (Exception e) {
                Console.WriteLine(e.Message);
            } finally {
                Console.Write("Press any key to continue . . . ");
                Console.ReadKey(true);
            }
        }

        public static IEnumerable<double> GetTestRandomSort(int limit)
        {
            for (int i = 0; i < 5; i++) {
                string path = null, temp = null;
                Stopwatch st = null;
                StreamReader sr = null;
                int? count = null;
                List<string> list = null;
                Random r = null;

                GC.Collect();
                GC.WaitForPendingFinalizers();
                Thread.Sleep(5000);

                st = Stopwatch.StartNew();
                #region Import Input Data
                path = Environment.CurrentDirectory + "\\data";
                list = new List<string>();
                sr = new StreamReader(path);
                count = 0;
                while (count < limit && (temp = sr.ReadLine()) != null) {
//                  Console.WriteLine(temp);
                    list.Add(temp);
                    count++;
                }
                sr.Close();
                #endregion

//              Console.WriteLine("--------------Random--------------");
//              #region Sort by Random with OrderBy(random.Next())
//              r = new Random();
//              list = list.OrderBy(l => r.Next()).ToList();
//              #endregion

//              #region Sort by Random with OrderBy(Guid)
//              list = list.OrderBy(l => Guid.NewGuid()).ToList();
//              #endregion

//              #region Sort by Random with Parallel and OrderBy(random.Next())
//              r = new Random();
//              list = list.AsParallel().OrderBy(l => r.Next()).ToList();
//              #endregion

//              #region Sort by Random with Parallel OrderBy(Guid)
//              list = list.AsParallel().OrderBy(l => Guid.NewGuid()).ToList();
//              #endregion

//              #region Sort by Random with User-Defined Shuffle Method
//              r = new Random();
//              list = list.Shuffle(r).ToList();
//              #endregion

//              #region Sort by Random with Parallel User-Defined Shuffle Method
//              r = new Random();
//              list = list.AsParallel().Shuffle(r).ToList();
//              #endregion

                // Result
//              
                st.Stop();
                yield return st.Elapsed.TotalMilliseconds;
                foreach (var element in list) {
                Console.WriteLine(element);
            }
            }

        }
    }
}

Sonuç Açıklaması: https://www.dropbox.com/s/9dw9wl259dfs04g/ResultDescription.PNG
Sonuç Durumu: https://www.dropbox.com/s/ewq5ybtsvesme4d/ResultStat.PNG

Sonuç:
Varsayalım: LINQ OrderBy (r.Next ()) ve OrderBy (Guid.NewGuid ()), İlk Çözümde Kullanıcı Tanımlı Karıştır Yönteminden daha kötü değildir.

Cevap: Bunlar çelişkidir.


1
İkinci seçenek değildir , doğru ve bu nedenle 's performanstır ilgisiz . Bu yine de rastgele bir sayı ile sipariş vermenin kabul edilebilir, verimli veya nasıl çalıştığı sorusuna cevap vermiyor. İlk çözümün doğruluk problemleri de var, ancak bir anlaşma kadar büyük değiller .
Servy

Maalesef, Quicksort of Linq OrderBy'nin daha iyi bir parametresinin ne olduğunu bilmek ister misiniz? Performansı test etmem gerekiyor. Ancak, int tipi sadece Guid dizesinden daha iyi hız var düşünüyorum ama değil. MSDN'nin neden önerdiğini anladım. Düzenlenen ilk çözüm performansı Random örneğiyle OrderBy ile aynıdır.
GMzo

Sorunu çözmeyen kodun performansını ölçmenin anlamı nedir? Performans, her ikisinin de çalıştığı iki çözüm arasında yapılması gereken bir husustur . Eğer çözüm çalışma varsa, o zaman yapabilirsiniz başlamak bunları karşılaştırmak.
Servy

Daha fazla veriyi test etmek için zamanım olması gerekiyor, o zaman bittiğinde, tekrar yayınlamaya söz veriyorum. Varsayıyorum: Linq OrderBy'nin ilk çözümden daha kötü olmadığını düşünüyorum. Görüş: Kullanımı ve anlaşılması kolaydır.
GMzo

Çok basit basit karıştırma algoritmalarından belirgin şekilde daha az verimlidir, ancak bir kez daha performans önemsizdir . Daha az performansa ek olarak, verileri güvenilir bir şekilde karıştırmazlar.
Servy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.