C# Array类---排序(长文慎入)

Array类使用 Quicksort 算法对数组中的元素进行排序。 Sort() 方法需要数组中的元素实现 IComparable 接口。 因为简单类型 如 System.String 和 System.Int32 实现了 IComparable 接口, 所以可以对包含这些类型的元素排序。

我们看个栗子:

string[] names = {
    "Zhang San",
    "Li Si",
    "Wang Er",
    "Ma Zi"
};

Array.Sort( names );  // core

foreach( string name in names )
{
    Console.WriteLine( name ); 
}

// 输出结果
Li Si
Ma Zi
Wang Er
Zhang San

在这个栗子中,数组名称包含 string 类型的元素, 这个数组可以排序。

 

如果对数组使用自定义类, 就必须实现 IComparable 接口。 这个接口只定义了一个方法 CompareTo(), 如果要比较的对象相等,该方法就返回0。 如果该实例应排在参数对象的前面,该方法就返回小于0的值。 如果该实例应排在参数对象的后面,该方法就返回大于 0 的值。

我写个例子,具体怎么应用,都在里面了:

public class Person : IComparable<Person>
    {
        // 看重点 CompareTo() 函数
        public int CompareTo(Person other)
        {
            if (other == null) return 1;

            if (this.Age == other.Age)
            {
                if (this.CreateTime > other.CreateTime) // 这里简易处理时间比较
                    return 1;
                else return -1;
            }
            else if (this.Age > other.Age)
            {
                return -1;
            }
            else
            {
                return 1;
            }   
        }

        // 下面的代码可以忽略不看
        public string Name { get; private set; }

        public int Age { get; private set; }

        public int CreateTime { get; private set; }

        public Person(string name, int age,  int createTime)
        {
            Name = name;
            Age  = age;
            CreateTime = createTime;
        }
    }

写个调用方法测试一下:

Person[] personArr = {
           new Person("张三",10, 5), // 入学时间我就简易下,用1-9的单个数字代替咯
           new Person("李四",11, 3), 
           new Person("王二",9,  3),
           new Person("麻子",12, 2),
           new Person("赵六",11, 2),
};

Array.Sort( personArr );

foreach( Person person in personArr )
{
    Console.WriteLine( "姓名:" + person.Name + ", 年龄:" + person.Age + " 入学时间:" + person.CreateTime );
}

// 输出结果
姓名:麻子, 年龄:12 入学时间:2
姓名:赵六, 年龄:11 入学时间:2
姓名:李四, 年龄:11 入学时间:3
姓名:张三, 年龄:10 入学时间:5
姓名:王二, 年龄:9 入学时间:3

上面的例子中, 我们希望年龄大的排前面,小的排后面。 这个是毋庸置疑的, 但是如果年龄相等了,我们又对入学时间做了一个比较, 当入学时间早则排前面, 否则就后面。 

如果 Person对象的排序方式与上述不同, 或者不能修改在数组中用做元素的类, 就可以实现 IComparer 接口或者 IComparer<T>接口。 这个接口定义了方法 Compare()。 要比较的类必须实现这两个接口之一, IComparer 接口独立于要比较的类。 这就是 Compare() 方法定义了两个要比较的参数的原因。其返回值与 IComparable 接口的 CompareTo()方法类似。

 

下面写个实现 IComparer<T> 的例子:

public class Person  // 注意这个类取消了 IComparable<T> 接口的实现
{
    public string Name { get; private set; }

    public int Age { get; private set; }

    public int CreateTime { get; private set; }

    public Person(string name, int age,  int createTime)
    {
         Name = name;
         Age  = age;
         CreateTime = createTime;
    }
}
public class PersonComparer : IComparer<Person> // 注意这个类实现了IComparer<T> 接口
{
    {
        public int Compare(Person x, Person y)
        {
            if (x == null && y == null) return 0;
            if (x == null) return 1;
            if (y == null) return -1;

            if (x.Age == y.Age)
            {
                if (x.CreateTime > y.CreateTime)
                    return 1;
                else return -1;
            }
            else if (x.Age > y.Age)
            {
                return -1;
            }
            else
            {
                return 1;
            }
      }
}

下面写调用代码:

Person[] personArr = {
           new Person("张三",10, 5), // 入学时间我就简易下,用1-9的单个数字代替咯
           new Person("李四",11, 3), 
           new Person("王二",9,  3),
           new Person("麻子",12, 2),
           new Person("赵六",11, 2),
};

Array.Sort( personArr, new PersonComparer() ); // core  look look 使劲 look

foreach( Person person in personArr )
{
    Console.WriteLine( "姓名:" + person.Name + ", 年龄:" + person.Age + " 入学时间:" + person.CreateTime );
}

// 输出结果
姓名:麻子, 年龄:12 入学时间:2
姓名:赵六, 年龄:11 入学时间:2
姓名:李四, 年龄:11 入学时间:3
姓名:张三, 年龄:10 入学时间:5
姓名:王二, 年龄:9 入学时间:3

这个例子实现的功能和前面的例子是一样的, 只不过一个是 person类自己实现了比较接口, 而后者单独继承比较接口来实现具体的比较逻辑。

 

注意: Aray类还提供了 Sort 方法,它需要将一个委托作为参数。 这个参数可以传递给方法,从而比较两个对象, 而不需要依赖 IComparable 或 IComparer 接口。 (具体怎么使用要等以后讲到委托的时候)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值