系列三:C#表达式设计(IComparable和IComparer实现排序)

转自:http://hi.baidu.com/gghost/blog/item/63cc79dd17c24d325882dd1a.html

用List<T>的泛型方法作为试验对象

首先看看LIst<T>.Sort()方法

List<T>.Sort()方法有四种重载


说明
List.Sort ()
使用默认比较器对整个 List 中的元素进行排序。

由 .NET Compact Framework 支持。

List.Sort (泛型 Comparison)
使用指定的 System.Comparison 对整个 List 中的元素进行排序。

由 .NET Compact Framework 支持。

List.Sort (泛型 IComparer)
使用指定的比较器对整个 List 中的元素进行排序。

由 .NET Compact Framework 支持。

List.Sort (Int32, Int32, 泛型 IComparer)
使用指定的比较器对 List 中某个范围内的元素进行排序。

由 .NET Compact Framework 支持。

 

这次实现Sort()方法的第1,3种重载

public void Sort ()

此方法使用类型 T 的默认比较器 Comparer.Default 确定列表元素的顺序。Comparer.Default 属性检查类型 T 是否实现了 IComparable 泛型接口,如果实现了该接口,则使用该实现。否则,Comparer.Default 将检查类型 T 是否实现了 IComparable 接口。如果类型 T 未实现任一接口,则 Comparer.Default 将引发 InvalidOperationException。

此方法使用 System.Array.Sort,后者使用 QuickSort 算法。此实现执行不稳定排序;亦即,如果两元素相等,则其顺序可能不被保留。相反,稳定排序保留相等元素的顺序。

 

using System;

using System.Collections.Generic;

using System.Text;

/*您现在准备对员工数组列表(empList)进行排序,为了查看排序是否正常工作,

* 您需要随机地添加整数和Employee实例到它们各自的数组中。创建随机数,需要实例化Random类;

* 调用Random对象的Next()方法产生随机数。Next()方法是一个重载方法;一种版本允许您传递一个整数值,

* 表示您想要的最大随机数。在本例中,您将传递10来产生一个0到10之间的随机数:(译者注:参数为10,最大的随机数只能为9)

*

List<T>.Sort() 此方法使用类型 T 的默认比较器 Comparer.Default 确定列表元素的顺序。

* Comparer.Default 属性检查类型 T 是否实现了 IComparable 泛型接口,如果实现了该接口,则使用该实现。

* 否则,Comparer.Default 将检查类型 T 是否实现了 IComparable 接口。

* 如果类型 T 未实现任一接口,则 Comparer.Default 将引发 InvalidOperationException。

*/

namespace IComparable接口实现

{

    class Program

    {

        static void Main(string[] args)

        {

            List<Employee> employees = new List<Employee>(5);

            Random rd = new Random();

 

            for (int i = 0; i < 5; i++)

            {

                employees.Add(new Employee(rd.Next(10) + 100));

 

                Console.Write("{0} ", employees[i].ToString());

            }

            employees.Sort();//排序

            //employees.Sort(employees);

            Console.WriteLine();

            for (int i = 0; i < 5; i++)

            {

                Console.Write("{0} ", employees[i].ToString());

            }

                Console.ReadLine();

 

        }

    }

    #region Employee Class

    class Employee : IComparable<Employee>

    {

        private int emplID;

        public int EmoloyeeID

        {

            get

            {

                return emplID;

            }

        }

        public Employee(int id)

        {

            this.emplID = id;

        }

        public override string ToString()

        {

            return emplID.ToString();

        }

        public int CompareTo(Employee other)

        {

            return this.emplID.CompareTo(other.emplID);

        }

        public bool Equal(Employee other)

        {

            return this.emplID == other.emplID ? true : false;

        }

    }

    #endregion

 

}

public void Sort ( IComparer<T> comparer)

 

如果提供了 comparer,则 List 的元素是使用指定的 IComparer 实现进行排序的。

如果 comparer 为空引用(在 Visual Basic 中为 Nothing),则默认比较器 Comparer.Default 将检查类型 T 是否实现了 IComparable 泛型接口,如果实现了该接口,则使用该实现。否则,Comparer.Default 将检查类型 T 是否实现了 IComparable 接口。如果类型 T 未实现任一接口,则 Comparer.Default 将引发 InvalidOperationException。

此方法使用 System.Array.Sort,后者使用 QuickSort 算法。此实现执行不稳定排序;亦即,如果两元素相等,则其顺序可能不被保留。相反,稳定排序保留相等元素的顺序。

 

using System;

using System.Collections.Generic;

using System.Text;

 

namespace IComparer泛型接口实现

{

    class Program

    {

        static void Main(string[] args)

        {

            List<EmployeeClass> empList = new List<EmployeeClass>(2);

            Random r = new Random();

           

            EmployeeClass ec1 = new EmployeeClass(r.Next(100), r.Next(10));

            EmployeeClass ec2 = new EmployeeClass(r.Next(100), r.Next(10));

            EmployeeClass ec3 = new EmployeeClass(r.Next(100), r.Next(10));

            empList.Add(ec3);

            empList.Add(ec1);

            empList.Add(ec2);

            EmployeeCompareType ect = new EmployeeCompareType(EmployeeCompareType.CompareType.SEV);

            empList.Sort(ect);

            for (int i = 0; i < empList.Count; i++)

            {

                Console.WriteLine(empList[i].ToString());

            }

            Console.ReadLine();

           

        }

    }

    class EmployeeClass : IComparable<EmployeeClass>

    {

        private int empID;

        private int sevYear;

 

        public EmployeeClass(int empID, int sevYear)

        {

            this.empID = empID;

            this.sevYear = sevYear;

        }

        public int CompareTo(EmployeeClass ec2)

        {

            return empID.CompareTo(ec2.empID);

        }

        public override string ToString()

        {

            return string.Format("ID:{0,10:D}   Year of server:{1}", empID, sevYear);

        }

        public static int CompareToForType(EmployeeClass ec1, EmployeeClass ec2,EmployeeCompareType.CompareType whichtype)

 

        {

            switch (whichtype)

            {

                case EmployeeCompareType.CompareType.ID:

                    return ec1.empID.CompareTo(ec2.empID) ;

                   

                case EmployeeCompareType.CompareType.SEV:

                    return ec1.sevYear.CompareTo(ec2.sevYear);

                   

                default:

                    Console.WriteLine("Wrong CompareType");

                    return 100;

                   

            }

 

 

        }

      

 

    }

 

    class EmployeeCompareType : IComparer<EmployeeClass>

    {

        public enum CompareType

        {

            ID,

            SEV

        }

        public CompareType ComType = CompareType.ID;

        public EmployeeCompareType(CompareType ct)

        {

            this.ComType = ct;

        }

 

        public int Compare(EmployeeClass ec1, EmployeeClass ec2)

        {

            return EmployeeClass.CompareToForType(ec1, ec2, ComType);

          

 

        }

    }  

}

 

以下代码是我自己测试用

//定义一个泛型类型的比较类,实现了IComparer接口,排序时候直接把这个对象的实例传入sort()方法即可,IComparer 的角色是提供附加的比较机制。例如对于您可能需要提供几个字段或属性,在类中的顺序升序和降序在同一字段或两者
public class yulian:IComparer<hhh> 

{

    #region IComparer<hhh> 成员

    int IComparer<hhh>.Compare(hhh x, hhh y)
    {
        return x.m.CompareTo(y.m);
    }

    #endregion
}

//在需要进行排序的类型上实现IComparable接口,这样默认的sort()方法能直接调用进行排序

public class hhh:IComparable
{
    public string m = null;

    public hhh(string n)
    {
        m = n;
    }

    #region IComparable 成员,它是类型不安全方法,需要判断类型,并且还需要装箱和拆箱,不建议用

    public int CompareTo(object obj)
    {
        if((obj as hhh).m=="9")//故意设置9为最小元素,9排在第一位
            return 2;
        return this.m.CompareTo((obj as hhh).m);
    }

    #endregion
}

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        List<hhh> jihe = new List<hhh>();
        jihe.Add(new hhh("9"));
        jihe.Add(new hhh("5"));
        jihe.Add(new hhh("8"));
        jihe.Add(new hhh("6"));

        for (int i = 0; i < jihe.Count; i++)//读取未排序数据
        {
            Response.Write(jihe[i].m);
        }


        Response.Write("<br/>");
        jihe.Sort();//实现默认的排序,也就是在类型中实现了IComparable的方法
        for (int i = 0; i < jihe.Count; i++)
        {
            Response.Write(jihe[i].m);
        }

 

        Response.Write("<br/>");
        jihe.Sort(new yulian());//辅助类对数组进行的排序,也就是 IComparer的方法排序
        for (int i = 0; i < jihe.Count; i++)
        {
            Response.Write(jihe[i].m);
        }

 

posted @ 2011-01-23 13:31  yu_liantao  阅读(722)  评论(0)    收藏  举报