C#中的排序是将集合中的内容按特定顺序排列的过程。集合可以是数组、列表或任何其他数据组。该集合可能包含简单类型和复杂类型的元素。简单类型可以是整数、字符串、浮点数等的集合。复杂类型可以是用户定义类型的对象的集合,例如 Employee、Student 等。复杂类型通常是嵌套的,这意味着对象可能有多个属性。
示例
C# 提供了内置方法来对集合进行排序。无论是数组、列表还是任何通用集合,C# Sort() 方法都可以根据提供的比较器对其进行排序。在内部,.Net 实现使用快速排序算法对 C# 中的集合进行排序。我们将在本文的后续部分中对此进行更多讨论。
如前所述,.Net 框架使用快速排序方法对 C# 集合中的元素进行排序。那么,什么是快速排序?
快速排序遵循分而治之的策略。这意味着,排序算法选择一个主元元素并根据主元元素划分数组。小于枢轴的元素放置在其前面。大于枢轴的元素放置在其后面。这确保了主元元素已排序。此外,数组被分为两部分——小于主元的元素和大于主元的元素。接下来,该算法对两个数组都遵循相同的方法。
下面是一个示例。
未排序数组 – 18, 5, 16, 23, 50, 32
第 1 步(枢轴 = 32)– 18、5、16、23、32、50
步骤 2a
未排序数组 – 18、5、16、23
枢轴 = 23
部分排序数组 – 18, 5, 16, 23
步骤 2b
未排序数组 – 50
枢轴 = 50
部分排序数组 – 50
步骤 3a
未排序数组 – 18、5、16
枢轴 = 16
部分排序数组 – 5, 16, 18
排序数组 – 5、16、18、23、32、50
因此,快速排序有两个关键过程——选择枢轴和划分数组。算法的实现取决于主元的选择。它可以是第一个元素,也可以是最后一个元素,也可以是任意随机元素,也可以是数组的中位数。一旦分区完成并且枢轴被放置在正确的位置,算法就会被递归地调用分区数组,直到每个元素都被排序。
在C#中进行排序时,就出现了稳定快速排序和不稳定快速排序的概念。在稳定的快速排序中,如果两个元素相等,则它们在原始数组中的顺序将被保留。否则,它就处于不稳定的快速排序中。 C# 实现使用不稳定的快速排序。
在本文的这一部分,我们将主要关注 C# 中的两种类型的集合 - 数组和列表。我们将深入研究 C# 如何对数组和列表进行排序。下一节将尝试用一些例子来解释它。
让我们看看在 C# 中对数组进行排序的不同方式。
这是默认的 Sort() 方法。如果没有明确地将 Comparer 传递给该方法,C# 将使用升序排列元素。
代码:
using System; public class Program { public static void Main() { String[] strArray = {"I", "Am", "Learning", "Array", "Sorting","In", "C#"}; int[] intArray = {23, 76, 12, 43, 90, 30}; Array.Sort(strArray); Array.Sort(intArray); Console.WriteLine("Sorted String Array:\n"); DisplayArray(strArray); Console.WriteLine("\n\n\nSorted Integer Array:\n"); DisplayArray(intArray); } static void DisplayArray(string[] arr) { foreach (string a in arr) { Console.Write(a + "\t"); } } static void DisplayArray(int[] arr) { foreach (int a in arr) { Console.Write(a + "\t"); } } }
输出:
我们还可以为 Sort() 方法提供我们自己的自定义比较器。这将指示 C# 编译器使用自定义比较器而不是默认比较器。
要创建自定义比较器,我们需要从 IComparer 接口实现 Compare() 方法。下面的代码演示了如何创建一个比较器,以降序对元素进行排序。
我们创建了一个类,继承自 IComparer 接口,实现了 Compare() 方法并重写它以按降序比较元素。
代码:
using System; public class DescendingComparer : System.Collections.IComparer { public int Compare(Object a, Object b) { return (new System.Collections.CaseInsensitiveComparer()).Compare(b, a); } } public class Program { public static void Main() { String[] strArray = {"I", "Am", "Learning", "Array", "Sorting","In", "C#"}; int[] intArray = {23, 76, 12, 43, 90, 30}; Array.Sort(strArray, new DescendingComparer()); Array.Sort(intArray, new DescendingComparer()); Console.WriteLine("Sorted String Array in Descending Order:\n"); DisplayArray(strArray); Console.WriteLine("\n\n\nSorted Integer Array in Desc Order:\n"); DisplayArray(intArray); } static void DisplayArray(string[] arr) { foreach (string a in arr) { Console.Write(a + "\t"); } } static void DisplayArray(int[] arr) { foreach (int a in arr) { Console.Write(a + "\t"); } } }
输出:
C# also provides a way to sort one array using key values from another array. The example below has key-value pairs of first names and last names of people. We would sort them by both first and last names using the Sort() method.
Code:
using System; public class Program { public static void Main() { String[] firstNames = {"Tom", "Jack", "Anna", "Veronica", "Jessica", "Mike"}; String[] lastNames = {"Phelps", "Anderson", "Spectre", "Clarke", "Williams", "Fonseca"}; Array.Sort(firstNames, lastNames); Console.WriteLine("Sorted by First Names:\n"); DisplayArray(firstNames, lastNames); Array.Sort(lastNames, firstNames); Console.WriteLine("\n\nSorted by Last Names:\n"); DisplayArray(firstNames, lastNames); } static void DisplayArray(string[] arr1, string[] arr2) { for (int i = 0; i < arr1.Length; i++) { Console.WriteLine(arr1[i] + " " + arr2[i]); } } }
Output:
Let us look at the different ways in which we can sort a list in C#.
Note – To use Lists in C#, including the library System.Collections.Generic.This is the default sort() method. if no comparer is explicitly passed to the method, c# uses the ascending order to arrange the elements.
Code:
public class Program using System.Collections.Generic; { public static void Main() { String[] strArray = {"I", "Am", "Learning", "Array", "Sorting", "In", "C#"}; List<string> strList = new List<string>(strArray); int[] intArray = {23, 76, 12, 43, 90, 30}; List<int> intList = new List<int>(intArray); strList.Sort(); intList.Sort(); Console.WriteLine("Sorted String List:\n"); DisplayList(strList); Console.WriteLine("\n\n\nSorted Integer List:\n"); DisplayList(intList); } static void DisplayList(List<string> myList) { foreach (string a in myList) { Console.Write(a + "\t"); } } static void DisplayList(List<int> myList) { foreach (int a in myList) { Console.Write(a + "\t"); } } }
Output:
We can also provide our own custom comparer to the sort() method. This would instruct the c# compiler to use the custom comparer instead of the default one.
To create a custom comparer, we need to implement the Compare() method from the IComparer interface. The code below demonstrates how to create a comparer that would sort the elements in descending order.
We created a class, inherited it from the IComparer interface, implemented the Compare() method and overrode it to compare the elements in descending order.
Code:
using System; using System.Collections.Generic; public class LengthComparer : IComparer<string> { public int Compare(string a, string b) { return (a.Length.CompareTo(b.Length)); } } public class DigitSumComparer : IComparer<int> { public int Compare(int a, int b) { int sum_a = 0; int sum_b = 0; while (a > 0) { sum_a += (a % 10); a /= 10; } while (b > 0) { sum_b += (b % 10); b /= 10; } return (sum_a.CompareTo(sum_b)); } } public class Program { public static void Main() { LengthComparer lc = new LengthComparer(); DigitSumComparer dsc = new DigitSumComparer(); String[] strArray = {"I", "Am", "Learning", "Array", "Sorting", "In", "C#"}; List<string> strList = new List<string>(strArray); int[] intArray = {23, 76, 12, 43, 90, 30}; List<int> intList = new List<int>(intArray); strList.Sort(lc); intList.Sort(dsc); Console.WriteLine("Sorted String List by Length:\n"); DisplayList(strList); Console.WriteLine("\n\n\nSorted Integer List by Sum of Digits:\n"); DisplayList(intList); } static void DisplayList(List<string> myList) { foreach (string a in myList) { Console.Write(a + "\t"); } } static void DisplayList(List<int> myList) { foreach (int a in myList) { Console.Write(a + "\t"); } } }
Output:
Complex List Types are user-defined lists. To be more precise, they are lists of objects of user-defined classes. Being user-defined, the objects are a mixture of various primitive types. It is difficult to sort a complex list type. C# compiler expects each complex class to inherit from the IComparable interface and define the method CompareTo(). This method contains the instructions on how to compare the elements of the list for sorting.
In the example below, we define a user-defined class of Employees and sort the Employee objects based on their IDs.
Code:
using System; using System.Collections.Generic; public class Employee : IComparable<Employee> { public int id {get;set;} public string name{get;set;} public double salary{get;set;} public int CompareTo(Employee e) { return this.id.CompareTo(e.id); } } public class Program { public static void Main() { List<Employee> emps = new List<Employee>(); emps.Add(new Employee() {id = 123, name = "Tom Phelps", salary = 20000.00}); emps.Add(new Employee() {id = 897, name = "Jack Anderson", salary = 40050.50}); emps.Add(new Employee() {id = 342, name = "Anna Spectre", salary = 31030.89}); emps.Add(new Employee() {id = 219, name = "Veronica Clarke", salary = 66333.66}); emps.Add(new Employee() {id = 642, name = "Jessica Williams", salary = 50505.05}); emps.Add(new Employee() {id = 923, name = "Mike Fonseca", salary = 76543.21}); Console.WriteLine("Original Employee List:\n"); DisplayList(emps); emps.Sort(); Console.WriteLine("\n\nSorted Employee List by IDs:\n"); DisplayList(emps); } static void DisplayList(List<Employee> emp) { foreach (Employee e in emp) { Console.WriteLine("Id: " + e.id + ", Name: " + e.name + ", Salary: " + e.salary); } } }
Output:
Now, the obvious question that comes to mind is that what if we want to sort the objects of Employee class based on some other property? This is possible. We would need to implement the IComparer interface. Let us take a look at the example below to understand.
Code:
using System; using System.Collections.Generic; public class Employee { public int id {get;set;} public string name{get;set;} public double salary{get;set;} } public class SortByName : IComparer<Employee> { public int Compare(Employee e1, Employee e2) { return e1.name.CompareTo(e2.name); } } public class SortBySalary : IComparer<Employee> { public int Compare(Employee e1, Employee e2) { return e1.salary.CompareTo(e2.salary); } } public class Program { public static void Main() { SortByName sbn = new SortByName(); SortBySalary sbs = new SortBySalary(); List<Employee> emps = new List<Employee>(); emps.Add(new Employee() {id = 123, name = "Tom Phelps", salary = 20000.00}); emps.Add(new Employee() {id = 897, name = "Jack Anderson", salary = 40050.50}); emps.Add(new Employee() {id = 342, name = "Anna Spectre", salary = 31030.89}); emps.Add(new Employee() {id = 219, name = "Veronica Clarke", salary = 66333.66}); emps.Add(new Employee() {id = 642, name = "Jessica Williams", salary = 50505.05}); emps.Add(new Employee() {id = 923, name = "Mike Fonseca", salary = 76543.21}); emps.Sort(sbn); Console.WriteLine("Sorted Employee List by Names:\n"); DisplayList(emps); emps.Sort(sbs); Console.WriteLine("\n\nSorted Employee List by Salaries:\n"); DisplayList(emps); } static void DisplayList(List<Employee> emp) { foreach (Employee e in emp) { Console.WriteLine("Id: " + e.id + ", Name: " + e.name + ", Salary: " + e.salary); } } }
Output:
So, this article covered in-depth on how to sort collections in C#. We focused majorly on Arrays and Lists since these two covers all the primitive types as well. Once the concept of Sorting in C# is very well understood, it becomes easy to implement sorting in other collections such as Enumerations, Dictionaries, etc. After completing this article, it is recommended to explore the MSDN documentation for more implementations of Sorting in C#.
以上是C# 中的排序的详细内容。更多信息请关注PHP中文网其他相关文章!