Il y avait une question posée sur la manière de trier une liste. Il y avait plusieurs méthodes de la liste de base.sort () à list.orderby (). Le plus risible était un rouleau-votre-selectionsort. J'ai rapidement voté cela, mais cela m'a fait penser; Ordery (), ne serait-il pas appliqué à une liste, ne serait-il pas appliqué à une liste, faites la même chose? myList.orderby (x => x.property) .tolist () produirait un itérateur qui trouve essentiellement la valeur minimale de la projection dans ce qui reste de la collecte et de rendement le rend le retourne. Lorsque vous traversez toute la liste, c'est une sélection de sélection. P>
qui m'a fait penser; Quels algorithmes effectuent les trieurs intégrés pour les listes, les licenciements, les énumérables, etc. Utilisez-le, et par extension, l'un d'entre eux devrait-il être évité pour les grandes collections? Une sorte de tri, car il reste trié par la clé, utiliserait probablement une insertion d'une seule passe sur chaque ajout; Trouvez le premier index avec une valeur supérieure à celle du nouveau et insérez-le avant. Les listes et les tableaux se font probablement effrayer efficacement, mais je ne connais pas l'algorithme réel derrière la sorte (). Nous avons discuté de l'ordre. p>
Ce que je sais ci-dessus semblerait indiquer que List.sort () ou Array.sort () sont les meilleures options pour une liste de taille connue et utiliser LINQ pour trier une liste de mémoire ou une matrice doit être découragée. Pour un ruisseau, il n'y a vraiment aucun autre moyen d'ordonner () l'énumérable; La perte de performance est atténuée par le fait que vous pouvez conserver les données comme un flux au lieu de devoir tout avant de le trier. P>
EDIT: P>
Le consensus général est que le tri () est plus rapide, étant donné une implémentation concrète d'une liste ou d'une matrice. Orderby est raisonnable mais plus lent, car il ajoute une complexité O (n) d'extraction d'une matrice de l'encombrement adopté. L'initialisation de la liste triée finit par être O (n ^ 2) en raison de ce qui est sous le capot. Morale de l'histoire, utilisez list.sort () au lieu de list.orderby () lorsque vous avez une liste réelle. P>
4 Réponses :
Un gland rapide à travers le réflecteur me dit que la liste des méthodes de tri rapide http: //fr.wikipedia. org / wiki / quicksort via System.Collections.Generic.GenericarraysHorthelper P>
SORTEDLIST utilise Array.BinySearch pour déterminer où insérer des trucs sur chaque ajout p>
Les énumérateurs n'ont pas de tri logique p>
Quicksort est un bon choix de tri pour la plupart des situations, bien qu'il puisse approcher O (n ^ 2) si vous êtes vraiment malchanceux avec les données d'entrée. p>
Si vous soupçonnez que vos données d'entrée soient un énorme em> pile de données dans une commande malchanceuse (déjà triée) pour QuicksTort, une astuce est de randomiser les données d'abord (qui est toujours bon marché), puis faire le tri sur les données randomisées. Il y a quelques astuces L'algorithme QuicksTort peut mettre en œuvre pour atténuer le problème du tri des données d'entrée déjà triées (ou presque triées), je ne sais pas si la mise en œuvre de la BCL fait l'une de ces. p>
Un moyen de savoir que les performances de chaque méthode consiste à le mesurer: résultat: p> Ceci indique que la performance de l'ordre est raisonnable, même pour de très grandes listes, mais ce n'est pas aussi rapide que l'utilisation de la méthode de tri intégrée sur une liste. Ceci est probablement parce que le code de commande est légèrement plus flexible - il faut un sélecteur de clé qui doit être évalué pour chaque élément. p> p>
Oui, vos hypothèses sentent bien. J'ai fait un petit test pour le confirmer.
sur les entiers 5000000, P>
data.Sort(); // 500 ms data = data.OrderBy(a => a).ToList(); // 5000 ms
Cela peut démontrer que les commandes ne sont pas bonnes à utiliser sur de grandes collections, mais éventuellement pas pour la raison pour laquelle j'ai énoncé. Apparemment, utiliser Orderby nécessite une connaissance de l'entièrement en-témoine, qui détruit la qualité de diffusion en continu des itérateurs de Linq non ordonnés.
énumérable.orderby () slurpe l'iEnumerable <> dans un tableau et utilise un tri rapide. O (n) exigences de stockage. C'est fait par une classe interne dans system.core.dll, Liste <>. Trier et array.sort Utilisez le tri rapide de la place. P>
TritedList <> a une complexité O (n) pour une insertion, dominant la complexité O (log (n)) de la recherche du point d'insertion. Donc, mettre n des articles non traités à ce qu'il coûtera O (n ^ 2). Soyeddicary <> utilise un arbre noir noir, offrant une complexité d'insertion O (log (n)). Ainsi, O (Nlog (n)) pour le remplir, comme un type rapide amorti. P> énumérableort
Comment se fait-il de choisir <> a O (n) pour insérer? Je penserais que le BinarySearch l'a fait O (journal (n))
@Andreas - il doit faire de la place à l'élément à insérer. Qui nécessite des éléments mobiles O (n). C'est un tableau sous le capot.
Hmm. Maintenant, je me demande, quelle sie-siedlist a utilisé une mise en œuvre de la liste liée à double sens avec une référence "Centre"? Approcher O (n) pour indexer un seul élément (vous pouvez commencer à l'une ou l'autre extrémité ou au centre et travaillez vers le "index" actuel), mais aussi o (n) à itérer ("Suivant" est bon marché), et l'insertion, donnée La recherche binaire O (logn) (vous pouvez commencer à partir du centre) serait constante (réaffectation de deux pointeurs) pour une complexité totale d'insertion de O (logn). Cela ferait une liste triée à double sens O (Nlogn) complexité pour remplir avec N éléments non traités.
@Keith: Le Big Oh a peu de regard avec la division de l'algorithme en deux. Le plus petit OH, vous obtiendrez d'une liste liée est complètement vaincu par la façon dont CPU Caches travaille sur des machines modernes. Qui est fortement optimisé pour charger des octets contigus de la mémoire de la RAM. Une liste liée a une localité de cache très médiocre, calant la CPU pour des centaines de cycles sur une cache-manquée. C'est pourquoi la liste <> est en fait un tableau sous le capot, pas une liste liée des livres de texte de structure de données traditionnels.
Keiths: Si vous le souhaitez O (LG N) Opérations sur un TritedList Code>, vous n'utiliseriez simplement pas un
trioddiction code>, puisque a un
sortidlist code> est réellement une liste de
keyvaluepair code> éléments.
Je pense que les sortes les plus intégrées utilisent une trace rapide. Si vous souhaitez accélérer, supprimez la vérification des limites. List.sort utilise également Array.sort interne.
@MIKAEL est correct, OrderBy () utilise également un tri rapide. @Keiths, vous pouvez heureusement parcourir le code source vous-même, il est accessible au public (et intégré à VS). EnumerAmerAsorter.Quicksort est le nom de la méthode Order Ordle utilise.
.NET Réflecteur à la rescousse à nouveau - Je dois l'aimer!
@MIKAEL: Vous ne pouvez pas tourner des limites à vérifier .net
@HENK: Je voulais dire, évitez les limites de la vérification des longueurs de collecte. Toutes les méthodes .sort () vérifient au début. Pour les systèmes critiques de temps, vous pouvez gagner du temps en la mettant en œuvre vous-même et en sautant la vérification de la longueur / de l'index.