简体   繁体   English

使用递归和泛型创建快速排序

[英]Creating a quick sort using recursion and generics

I want to ask about the sort generic class I created. 我想问一下我创建的排序通用类。 I used a lot of different concepts I learned this year and combined it into a nice class which I can use to sort anything (granted that if its a class the class has a CompareTo method) 我使用了今年学到的许多不同概念,并将其组合到一个不错的类中,该类可以用来对任何东西进行排序(当然,如果它是一个类,则该类具有CompareTo方法)

public class Sort<T> where T : IComparable<T>
    {
        private List<T> toSort;
        public Sort(List<T> sortList)
        {
            toSort = sortList;
            quickSort();
        }
        public void quickSort()
        {
            qSort(toSort, 0, toSort.Count - 1);
        }
        private void qSort(List<T> toSort, int left, int right)
        {
            //set the indexes
            int leftIndex = left;
            int rightIndex = right;

            //get the pivot
            var pivot = toSort[left + (right - left) / 2];
            while (leftIndex <= rightIndex)
            {
                //check left values
                while (toSort[leftIndex].CompareTo(pivot)<0)
                {
                    leftIndex++;
                }
                //check right values
                while (toSort[rightIndex].CompareTo(pivot) >0)
                {
                    rightIndex--;
                }
                //swap
                if (leftIndex <= rightIndex)
                {
                    var tmp = toSort[leftIndex];
                    toSort[leftIndex] = toSort[rightIndex];
                    toSort[rightIndex] = tmp;

                    //move towards pivot
                    leftIndex++;
                    rightIndex--;
                }
            }
            //continues to sort left and right of pivot
            if (left < rightIndex)
            {
                qSort(toSort, left, rightIndex);
            }
            if (leftIndex < right)
            {
                qSort(toSort, leftIndex, right);
            }
        }


    }

I just have one question, the quickSort I used I got on the internet and then converted it to use generics by myself. 我只有一个问题,就是我在互联网上使用的quickSort,然后自己将其转换为使用泛型。 I understand how the actual sorting works. 我了解实际排序的工作方式。 I just want to know, why don't I have to return something. 我只想知道,为什么我不必退货。 I am a bit confused. 我有点困惑。 I see it is actually switching the values of the lists, but I wonder how it accesses the list I sent. 我看到它实际上是在切换列表的值,但是我不知道它如何访问我发送的列表。 Because where I call it I can just do this 因为在我称之为的地方我可以做到这一点

List<string> toSort = new List<string> { "C", "B", "A" };
                Sort<string> sort = new Sort<string>(toSort);
                cbxAlphabet.DataSource = toSort;

So I just use the original list and it will have A, B and C in the comboBox. 因此,我只使用原始列表,并且comboBox中将包含A,B和C。

If anybody can explain this I would really appreciate it! 如果有人可以解释这一点,我将不胜感激!

EDIT: 编辑:

 public static class Sort<T> where T : IComparable<T>
    {
        public static void quickSort(List<T> sortList)
        {
            qSort(sortList, 0, sortList.Count - 1);
        }
        private static void qSort(List<T> toSort, int left, int right)
        {
            //set the indexes
            int leftIndex = left;
            int rightIndex = right;

            //get the pivot
            var pivot = toSort[left + (right - left) / 2];
            while (leftIndex <= rightIndex)
            {
                //check left values
                while (toSort[leftIndex].CompareTo(pivot)<0)
                {
                    leftIndex++;
                }
                //check right values
                while (toSort[rightIndex].CompareTo(pivot) >0)
                {
                    rightIndex--;
                }
                //swap
                if (leftIndex <= rightIndex)
                {
                    var tmp = toSort[leftIndex];
                    toSort[leftIndex] = toSort[rightIndex];
                    toSort[rightIndex] = tmp;

                    //move towards pivot
                    leftIndex++;
                    rightIndex--;
                }
            }
            //continues to sort left and right of pivot
            if (left < rightIndex)
            {
                qSort(toSort, left, rightIndex);
            }
            if (leftIndex < right)
            {
                qSort(toSort, leftIndex, right);
            }
        }


    }

It is because List<T> is a Reference Type . 这是因为List<T>引用类型

There are two kinds of types in C#: reference types and value types. C#中有两种类型:引用类型和值类型。 Variables of reference types store references to their data (objects), while variables of value types directly contain their data. 引用类型的变量存储对其数据(对象)的引用,而值类型的变量直接包含其数据。 With reference types, two variables can reference the same object; 对于引用类型,两个变量可以引用相同的对象。 therefore, operations on one variable can affect the object referenced by the other variable. 因此,对一个变量的操作会影响另一变量引用的对象。 With value types, each variable has its own copy of the data, and it is not possible for operations on one variable to affect the other (except in the case of in, ref and out parameter variables; see in, ref and out parameter modifier). 对于值类型,每个变量都有其自己的数据副本,并且对一个变量的操作不可能影响另一个变量(除非是in,ref和out参数变量;请参阅in,ref和out参数修饰符)。

In your example, the variable toSort and the private field Sort.toSort both reference the exact same list. 在您的示例中,变量toSort和私有字段Sort.toSort都引用完全相同的列表。

If you manipulate a collection passed as parameter, that will be manipulated for every class able to access the same instance of the collection, this is why you don't really need to return a new lost. 如果您对作为参数传递的集合进行操作,那么它将为每个能够访问该集合的同一实例的类进行操作,这就是为什么您实际上不需要返回新的lost的原因。

To learn more about reference and value types please read: Value Types Reference Types 要了解有关引用和值类型的更多信息,请阅读: 值类型 引用类型

If you want to take a look at how the .net framework helps you out with the sorting of collections, please read here 如果您想了解.net框架如何帮助您进行集合排序,请阅读此处

You have a class constructor that expects the list as the parameter, and it's sorting that list. 您有一个类构造函数,期望将列表作为参数,并对列表进行排序。

Basically this code: 基本上这段代码:

private List<T> toSort;
public Sort(List<T> sortList)
{
    toSort = sortList;
    quickSort();
}

Now, List<T> is a reference type, which means that if you pass it on as a parameter to some other code that modifies it, the calling code will see the modified list. 现在, List<T>是引用类型,这意味着如果将其作为参数传递给其他修改它的代码,则调用代码将看到修改后的列表。

The reason this works is because you are doing in-place sorting . 之所以起作用,是因为您正在就地排序 No copy of the list is made and all changes are made on the original list you passed by Reference Type . 不创建列表的副本,并且所有更改都在通过Reference Type传递的原始列表上进行。 The same thing works on arrays and any other pass by Reference Type. 数组和引用类型的任何其他传递都可以使用相同的方法。

If I might make a suggestion to make your code a little faster and cleaner is to use generic static methods, like so: 如果我建议让您的代码更快一点,更干净一点,那就是使用通用静态方法,如下所示:

public static class SortMethods
{
    public static <T> List<T> QuickSort(this List<T> toSort) where T : IComparable<T>
    {
        QuickSort(toSort, 0, toSort.Count - 1);
        return toSort;
    }
    private static <T> void QuickSort(this List<T> toSort, int left, int right) where T : IComparable<T>
    {
        // perform quick sort
    }
}

Then you can call this one of two ways: 然后,您可以使用以下两种方法之一进行调用:

  • list.QuickSort();
  • SortMethods.QuickSort(list);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM