Internal working of the Sort() and CompareTo() methods

懵懂的女人 提交于 2019-12-01 21:42:42

Let's start with the basic idea.

What is the purpose of CompareTo?

What is 42 to 1337. Is 42... greater than, less than or equal to 1337?

This question and its answer are modeled by the CompareTo method in the IComparable<T> and IComparable interfaces. For A.CompareTo(B), the method can return:

  • A is greater than B: an integer value greater than 0.
  • A is less than B: an integer value less than 0.
  • A is equal to B: an integer value equal to 0.

And of course, IComparable is not limited to integers. You can implement IComparable to compare any two objects that you think should be comparable. For example, strings:

What is "Armadillo" to "Zodiac": Is "Armadillo"... greater than, less than or equal to "Zodiac"?

The answer depends on your definition of greater than, less than and equal to. For strings the usual order is that a word that would occur later in the dictionary is greater than a word that occurs earlier.

How does CompareTo help sorting?

Okay, now you know how you can compare any two objects. This is useful for many algorithms, but mostly sorting and ordering algorithms. Take for example a very simple sorting algorithm: stupid sort. The idea is:

Look at two adjacent elements in your array, A and B.
When A <= B: go forward to the next pair.
When A > B: swap A and B, and go back to the previous pair.
When we reach the end, we're done.

You see, to get sorted there must be a way to determine which of the two elements is the greater one. That's where IComparable<T> comes into play.

public static void StupidSort<T>(T[] array)
            where T : IComparable<T>
{
    int index = 0;
    while (index < array.Length)
    {
        if (index == 0 ||
            array[index - 1].CompareTo(array[index]) <= 0)
        {
            index++;
        }
        else
        {
            Swap(array, index - 1, index);
            index--;
        }
    }
}

What happens when CompareTo would always return 1?

You can of course program CompareTo to return anything you want. But if you screw up, then your method no longer answers the question what is this to obj? Always returning a 1 would mean that for any A and B, A is always greater than B. That's like saying: 20 is greater than 10 and 10 is greater than 20. It does not make sense, and the result is that any sorting you do will also not make any sense. Garbage in... garbage out.

The rules of the game are, for three given objects A, B and C:

  • A.CompareTo(A) must return 0 (A is equal to A).
  • If A.CompareTo(B) returns 0, then B.CompareTo(A) returns 0 (If A is equal to B, then B is equal to A).
  • If A.CompareTo(B) returns 0, and B.CompareTo(C) returns 0, then A.CompareTo(C) returns 0 (If A is equal to B, and B is equal to C, then A is equal to C).
  • If A.CompareTo(B) returns a value greater than 0, then B.CompareTo(A) returns a value less than 0 (If A is greater than B, then B is less than A).
  • If A.CompareTo(B) returns a value less than 0, then B.CompareTo(A) returns a value greater than 0 (If A is less than B, then B is greater than A).
  • If A.CompareTo(B) returns a value greater than 0, and B.CompareTo(C) returns a value greater than 0, then A.CompareTo(C) returns a value greater than 0 (If A is greater than B, and B is greater than C, then A is greater than C).
  • If A.CompareTo(B) returns a value less than 0, and B.CompareTo(C) returns a value less than 0, then A.CompareTo(C) returns a value less than 0 (If A is less than B, and B is less than C, then A is less than C).
  • null is always less than any non-null object.

If your implementation doesn't adhere to these (simple and logical) principles, then sorting algorithms can literally do anything, and probably don't give the results you expect.

When you want to compare a to b, you say:

int result=a.CompareTo(b);

ie, the first comparison operand is this and the second one is the parameter passed to the function.

Then when you sort the array, regardless of the algorithm used you have to compare elements together, sending them as this and obj to object.CompareTo (or viable overloads of this function).

The sorting method is independent of the CompareTo method. I'm not sure what sorting algorithm is used but I'd guess it's something like a quick sort (obv not a bubble sort). If you're interested in those algorithms Wikipedia documents them in detail.

The CompareTo method is simply a means to compare objects of the same type. It's defined for many of the common .NET types to begin with and can be overriden to do comparisons between custom objects (things you create). Basically you call it from an object of type A passing it a second object of type A and the return value indicates if the two are equal or if one is greater than the other.

It's best to think of CompareTo as a utility function. It exists so you can do custom comparisons using the sorting methods provided with common .NET data structures. Without something like it, you would have to write the sorting algorithm yourself in order to compare types that you've created. It's purpose is simply to make sorting methods reusable/extensible.

In short, Sort takes two elements of your ArrayList, and calls CompareTo for the first elements, and pass second element as an argument, like this:

element1.CompareTo(element2)

CompareTo returns negative value if element1 is less that element2, 0 if they are equal, positive value otherwise. Sort uses this return value to, uhm, do some sorting. Then it repeats this process for next two elements, does some more sorting, and so on until ArrayList is sorted. Search for "sorting algorithm" to get more info about this process.

There are different sort algorithms. However, no matter what there are points where an algorithm must decide which element is greater, which is when CompareTo is called.

a.CompareTo(b) < 0;

If a and b are Integers (or in pseudocode), you could also use:

a < b

I think you will find the a < b notation in a lot of pseudocode or integer sort algorithm examples. CompareTo method of IComparable<T> is an object-oriented implementation - or notation.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!