C#学习笔记 排序与查找

IComparable接口和IComparer接口

为了能够对数据项进行排序,就要确定两个数据项在列表中的相对位置,也就是要确定两个对象的“大小”关系。一般来说有如下两种方式来定义大小关系:
第一种方式是针对对象本身。为了使对象自己能够执行比较操作,该对象必须实现IComparable接口,即至少具有一个CompareTo()成员。
System.IComparable接口中有一个方法,如下:

	int CompareTo(object obj);

它根据当前对象与要比较的对象的“大小”来返回一个正数、0或一个负数。
所有的简单值类型(如intdoubledecimal等)、枚举和字符串类,都实现该接口;用户定义的任何类型,只要类型值是有序的,都可以实现该接口。
第二种方式是提供一个外部比较器。为了能够比较对象的大小,可以提供一个比较器,比较器实现了ICompare接口。
System.Collections.IComparer接口中有一个方法,如下:

	int Compare(object obj1, object obj2);

它根据第一个对象与第二个对象的“大小”来返回一个正数、0或一个负数。例如:

	int Compare(object obj1, object obj2){
    
    
		return (abj1 as Book).price - (obj2 as Book).price;
	}

上面这段代码表示按照书的价格的大小顺序升序排序。其中小于0的值表示第1的对象“小于”第2个对象,等于0表示两个对象“大小相等”,正数则表示第1个对象“大于”第2个对象。

使用Array类进行排序和查找

System.Array类是用于对数组进行排序和搜索的类。Array类提供了Sort()BinarySearch(),可用于排序及查找,另外,还提供了Reverse()方法进行反序。

1.Array.Sort()及Reverse

Array.Sort()方法可以实现对一维数组的排序。常用的有以下几种形式:

	public static void Sort(Array);	// 对数组元素排序, 每个元素要求实现IComparable
	public static void Sort(Array keys, Array values);	// 根据keys数组对values排序
	public static void Sort(Array, IComparer);	// 对数组排序, 使用外部比较器
	public static void Sort(Array keys, Array values, IComparer);	// 根据keys数组对values排序, 排序时, 使用外部比较器

Array.Reverse()方法,可以用来对整个数组顺序进行反转:

	public static void Reverse(Array);	// 对数组排序, 每个元素要求实现IComparable

2.Array.Sort()的泛型方法

Array.Sort()方法还有一个泛型方法,Sort<T>(T[])。它还可以带IComparer<T>参数,除此外,还可以带一个Comparsiom委托,该委托的原型是:

public delegate int Comparsion<in T>(T x, T y);

写委托参数的简便方法是使用Lambda表达式,例如:

	Array.Sort<Person>(people, (p1, p2) => p1.Age - p2.Age);

表示对人的数组按年龄从小到大排序。

3.Array.BinarySearch()

Array.BinarySearch()方法可以实现在已经排序的一堆数组中进行元素查找,常用的有以下几种形式:

	public static int BinarySearch(Array, object);	// 在数组中进行查找对象object
	public static int BinarySearch(Array, object, IComparer);	// 使用外部比较器

使用BinarySearch()要注意:在执行BinarySearch()之前必须先对数组进行排序。
示例:

using System;
public class Test
{
    
    
	public static void Main(string[] args){
    
    
		string[] ary = {
    
     "Apple", "Pearl", "Banana", "Carrot" };
		Show(ary);

		Array.Sort(ary);
		Show(ary);
		int it = Array.BinarySearch(ary, "Pearl");
		Console.WriteLine(it);
		Array.Reverse(ary);
		Show(ary);
	}
	public static void Show(object[] ary){
    
    
		foreach (object obj in ary)
			Console.Write(obj + " ");
		Console.WriteLine();
	}
}

运行结果:
在这里插入图片描述

集合类中的排序和查找

集合类中也有一些机制进行排序和查找,例如:

  • ① 许多类中有Contains()方法进行查找。
  • ② 许多类中的ToArray()方法,可以将它转成数组,再进行排序及查找。
  • ③ 可以从其他集合构造一个新的ArrayList及SortedList对象,再进行排序及查找。

1.ArrayList的Sort( )及BinarySearch( )

ArrayList中的方法有关排序及查找,常见的有:

	public virtual void Sort();
	public virtual void Sort(IComparer);
	public virtual int BinarySearch(object);
	public virtual int BinarySearch(object, IComparer);

对于一个集合类,可以构造一个ArrayList实例:

	public ArrayList(ICollection);

这个构造方法中,将一个集合类的对象进行复制,并生成一个ArrayList类。
ArrayList还提供Adapter()方法,可以将其他IList对象包含在ArrayList中。

	public static ArrayList Adapter(IList);

Adapter不复制IList的内容,它只为IList创建ArrayList包装;因此,对IList进行更改也会影响ArrayList。可以用此方法来使用ArrayList类提供一般的ReverseBinarySearchSort方法。但是,通过此包装执行这些一般操作比直接在IList上应用这些操作效率要低。

2.SortedList

SortedList类的对象,在加入元素时,就会自动排序。
可以通过创建一个SortedList实例,来将一个IDictionary对象(包括SortedList对象)进行元素的复制,并且进行排序。

public class Test
{
    
    
	static void Main(string[] args) {
    
    
		Person[] Persons = {
    
    
			new Person("Liu", true, 21),
			new Person("Zhang", true, 18),
			new Person("Tang", false, 23),
			new Person("Lu", false, 21)
		};
		Random rnd = new Random();
		SortedList list1 = new SortedList();
		foreach (Person r in Persons)
			list1.Add(r.ToString(), "Room:" + rnd.Next(1000));
		Person.PrintKeysAndValues(list1);

		SortedList list2 = new SortedList(list1, new MyComparer());
		Console.WriteLine("111111111111111");
		Person.PrintKeysAndValues(list2);
	}
}

public struct Person : IComparable
{
    
    
	public string Name;
	public bool Sex;
	public int Age;
	public Person(string name, bool sex, int age) {
    
    
		this.Name = name;
		this.Sex = sex;
		this.Age = age;
	}

	public int CompareTo(object obj) {
    
    
		if (!(obj is Person))
			throw new System.ArgumentException();
		Person rec = (Person)obj;
		if (this.Age > rec.Age) return 1;
		else if (this.Age == rec.Age) return 0;
		return -1;
	}
	public override string ToString() {
    
    
		return "Name: " + Name + "; Sex: " + Sex + "; Age: " + Age;
	}
	public static void PrintKeysAndValues(SortedList myList) {
    
    
		IDictionaryEnumerator myEnumerator = myList.GetEnumerator();
		while (myEnumerator.MoveNext())
			Console.WriteLine("{0}:\t\t{1}", myEnumerator.Key, myEnumerator.Value);
		Console.WriteLine();
	}
}

public class MyComparer : IComparer
{
    
    
	public int Compare(object obj1, object obj2) {
    
    
		if (!(obj1 is Person) || !(obj2 is Person))
			throw new System.ArgumentException();
		Person rec1 = (Person)obj1;
		Person rec2 = (Person)obj2;
		return rec1.Name.ToLower().CompareTo(rec2.Name.ToLower());
	}
}

猜你喜欢

转载自blog.csdn.net/qq_45349225/article/details/114297339
今日推荐