C#内建接口:IComparable, Array.Sort()底层实现原理。

目录

一、介绍

二、示例

注意:Array.Sort(people);调用了CompareTo方法 

Array.Sort()底层实现原理。

注意:WriteLine输出会调用ToString

三、笔试题实战


一、介绍

IComparable是一个接口,它定义了一个用于比较对象的方法CompareTo。在C#中,IComparable接口可以被实现,以便在需要比较对象的场合使用,例如在排序算法中。

二、示例

以下是一个实现了IComparable接口的C#代码示例:

using System;

public class Person : IComparable<Person>
{
    public string Name { get; set; }
    public int Age { get; set; }

    public int CompareTo(Person other)
    {
        if (other == null) return 1;

        // Compare the age first
        int result = Age.CompareTo(other.Age);

        // If the ages are equal, compare the names
        if (result == 0)
        {
            result = Name.CompareTo(other.Name);
        }

        return result;
    }
}

// Usage:
var people = new Person[] {
    new Person { Name = "Alice", Age = 25 },
    new Person { Name = "Bob", Age = 30 },
    new Person { Name = "Charlie", Age = 20 }
};

Array.Sort(people);

foreach (var person in people)
{
    Console.WriteLine("{0} ({1})", person.Name, person.Age);
}

在上面的代码中,我们定义了一个Person类,它实现了IComparable<Person>接口,并实现了CompareTo方法。在CompareTo方法中,我们首先按照年龄进行比较,如果年龄相同,则按照名字进行比较。

在主函数中,我们定义了一个包含三个Person对象的数组,并使用Array.Sort方法对数组进行排序。由于Person类实现了IComparable接口,因此Array.Sort方法可以根据CompareTo方法对数组进行排序。最后,我们使用foreach循环打印排序后的结果。

注意:Array.Sort(people);调用了CompareTo方法 

Array.Sort(people)会调用实现了IComparable<T>接口的类的CompareTo方法来进行排序。在上面的示例代码中,我们实现了Person类的CompareTo方法,因此Array.Sort(people)会调用Person类的CompareTo方法来比较Person对象的大小,并进行排序。具体来说,Array.Sort方法在排序时会将数组中的元素两两比较,使用CompareTo方法来确定它们的大小关系,然后进行交换,直到整个数组排序完成。因此,在使用Array.Sort方法对实现了IComparable<T>接口的类的数组进行排序时,CompareTo方法会被自动调用。

Array.Sort()底层实现原理。

C#中的Array.Sort()方法使用的是一种优化过的快速排序算法来对数组进行排序。具体的底层实现原理如下:

  1. 首先,选择数组中的一个元素作为基准值(pivot)。

  2. 将数组划分为两个子数组,一个子数组中的元素都小于等于基准值,另一个子数组中的元素都大于基准值。这个过程称为分区(partitioning)。

  3. 对两个子数组递归地重复步骤1和步骤2,直到每个子数组只包含一个元素或为空。

  4. 最后,通过递归地将子数组合并起来,即可得到完全有序的数组。

在实现上,Array.Sort()方法会根据数组的类型选择不同的算法和优化策略。对于值类型数组,会使用基元排序(primitive sort)算法,该算法会尽可能地使用位操作和特定的比较函数来提高性能。对于引用类型数组,会使用基于比较器(comparer)的排序算法,该算法使用自定义的比较器来进行元素比较。

Array.Sort()方法的性能较高,并且在大多数情况下都能提供较好的排序效果。然而,如果需要对自定义类型的数组进行排序,建议实现IComparable接口或使用自定义的比较器来指定排序规则,以确保排序的正确性和一致性。

升级一下代码:我们可以在Person类中重写ToString方法来输出Person对象的字符串表示形式,从而在输出people数组时使用。下面是一个示例代码:

using System;

public class Person : IComparable<Person>
{
    public string Name { get; set; }
    public int Age { get; set; }

    public int CompareTo(Person other)
    {
        if (other == null) return 1;

        // Compare the age first
        int result = Age.CompareTo(other.Age);

        // If the ages are equal, compare the names
        if (result == 0)
        {
            result = Name.CompareTo(other.Name);
        }

        return result;
    }

    public override string ToString()
    {
        return $"{Name} ({Age})";
    }
}

// Usage:
var people = new Person[] {
    new Person { Name = "Alice", Age = 25 },
    new Person { Name = "Bob", Age = 30 },
    new Person { Name = "Charlie", Age = 20 }
};

Array.Sort(people);

foreach (var person in people)
{
    Console.WriteLine(person);
}

在上面的代码中,我们在Person类中重写了ToString方法,以便输出Person对象的字符串表示形式。在主函数中,我们定义了一个包含三个Person对象的数组,并使用Array.Sort方法对数组进行排序。然后,我们使用foreach循环遍历排序后的数组,并输出每个Person对象的字符串表示形式,这里会自动调用ToString方法。因此,在输出people数组时,我们可以重写ToString方法来定制输出的格式。

注意:WriteLine输出会调用ToString

当我们使用Console.WriteLine输出一个对象时,会自动调用该对象的ToString方法来获取它的字符串表示形式,并输出到控制台。如果该对象没有重写ToString方法,则默认使用该对象的完全限定类型名作为字符串表示形式。

下面是一个示例代码,演示了Console.WriteLine如何调用对象的ToString方法:

using System;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// Usage:
var person = new Person { Name = "Alice", Age = 25 };
Console.WriteLine(person);

在上面的代码中,我们定义了一个Person类,并创建了一个Person对象。然后,我们使用Console.WriteLine输出该对象。由于Person类没有重写ToString方法,因此默认使用Person类的完全限定类型名作为该对象的字符串表示形式。因此,输出的结果为:"Person"。

如果我们在Person类中重写ToString方法,可以自定义该对象的字符串表示形式。例如,下面的代码重写了Person类的ToString方法:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override string ToString()
    {
        return $"{Name} ({Age})";
    }
}

// Usage:
var person = new Person { Name = "Alice", Age = 25 };
Console.WriteLine(person);

在上面的代码中,我们在Person类中重写了ToString方法,将该对象的字符串表示形式设置为"Name (Age)"的格式。因此,输出的结果为:"Alice (25)"。

综上所述,当我们使用Console.WriteLine输出一个对象时,会自动调用该对象的ToString方法来获取它的字符串表示形式,并输出到控制台。如果我们希望自定义该对象的字符串表示形式,可以在类中重写ToString方法。

三、笔试题实战

网易互娱雷火事业群笔试-游戏研发工程师(第二批)

1.

矩形排序

【注意:本题按通过的Case比例给分】

给定N个矩形,每个矩形宽W米高H米

请按以下规则将这N个矩形排序,输出排序后的矩形列表

排序规则:
面积小的矩形排在面积大的矩形前面
面积相同的矩形,按照宽高比排序,宽高比大的矩形排在宽高比小的矩形前面
宽高比的定义为 min(W/H, H/W)
面积和宽高比都相同的矩形,按照宽排序,宽度更小的矩形排在宽度更大的矩形前面
 

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32M,其他语言64M

输入描述:

每组输入两行输入

第一行是一个整数N (0 < N <= 100)

第二行是2*N个整数,分别是每个矩形的宽W和高H,(0 < W,H <= 100)

输出描述:

每组数据输出一行,2*N个整数,分别是排序后的每个矩形的宽W和高H

示例1

输入例子:

2
2 2 1 1

输出例子:

1 1 2 2
using System;

class Rectangle : IComparable<Rectangle>
{
    public int width;
    public int height;

    public Rectangle(int w, int h)
    {
        width = w;
        height = h;
    }

    public int CompareTo(Rectangle other)
    {
        int area = width * height;
        int otherArea = other.width * other.height;

        if (area != otherArea)
        {
            return area - otherArea;
        }

        double aspectRatio = Math.Min((double)width / height, (double)height / width);
        double otherAspectRatio = Math.Min((double)other.width / other.height, (double)other.height / other.width);

        if (aspectRatio != otherAspectRatio)
        {
            return otherAspectRatio.CompareTo(aspectRatio);
        }

        return width - other.width;
    }

    public override string ToString()
    {
        return width + " " + height;
    }
}

class Program
{
    static void Main(string[] args)
    {
        int n = int.Parse(Console.ReadLine());
        string[] input = Console.ReadLine().Split();

        Rectangle[] rectangles = new Rectangle[n];

        for (int i = 0; i < n; i++)
        {
            int w = int.Parse(input[i * 2]);
            int h = int.Parse(input[i * 2 + 1]);
            rectangles[i] = new Rectangle(w, h);
        }

        Array.Sort(rectangles);

        for (int i = 0; i < n; i++)
        {
            Console.Write(rectangles[i] + " ");
        }
    }
}

首先定义了一个 Rectangle 类来表示矩形,并实现了 IComparable 接口用于比较两个矩形的大小关系。

CompareTo 方法中,首先比较矩形面积大小,如果面积不同则直接比较面积大小。如果面积相同,则计算矩形的宽高比,宽高比大的矩形排在前面。如果宽高比也相同,则比较矩形的宽度大小。

Main 方法中,读入输入并创建 Rectangle 对象数组。调用 Array.Sort 方法进行排序,最后输出排序后的结果。

注意在输出时需要重写 ToString 方法来返回矩形的宽高字符串表示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傻Q爱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值