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

C# 使用递归和泛型创建快速排序,c#,sorting,generics,quicksort,icomparable,C#,Sorting,Generics,Quicksort,Icomparable,我想问一下我创建的排序泛型类。我使用了今年学到的许多不同的概念,并将其组合成一个很好的类,我可以用它对任何东西进行排序,如果它是一个类,那么这个类就有一个CompareTo方法 public class Sort<T> where T : IComparable<T> { private List<T> toSort; public Sort(List<T> sortList) {

我想问一下我创建的排序泛型类。我使用了今年学到的许多不同的概念,并将其组合成一个很好的类,我可以用它对任何东西进行排序,如果它是一个类,那么这个类就有一个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);
            }
        }


    }
我只有一个问题,我使用的快速排序是我在互联网上找到的,然后我自己把它转换成使用泛型。我了解实际的分类工作。我只是想知道,为什么我不归还一些东西呢。我有点困惑。我看到它实际上是在切换列表的值,但我想知道它是如何访问我发送的列表的。因为在我叫它的地方,我可以这么做

List<string> toSort = new List<string> { "C", "B", "A" };
                Sort<string> sort = new Sort<string>(toSort);
                cbxAlphabet.DataSource = toSort;
所以我只使用原始列表,它在组合框中有A、B和C

如果有人能解释这一点,我将不胜感激

编辑:


您有一个类构造函数,它期望列表作为参数,并对该列表进行排序

基本上,该代码:

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

现在,List是一种引用类型,这意味着如果您将它作为参数传递给修改它的其他代码,调用代码将看到修改后的列表。

您有一个类构造函数,它希望列表作为参数,并对该列表进行排序

基本上,该代码:

private List<T> toSort;
public Sort(List<T> sortList)
{
    toSort = sortList;
    quickSort();
}
现在,列表是一种引用类型,这意味着如果您将它作为参数传递给修改它的其他代码,调用代码将看到修改后的列表。

这是因为列表是一个引用类型

C中有两种类型:引用类型和值类型。引用类型的变量存储对其数据对象的引用,而值类型的变量直接包含其数据。对于引用类型,两个变量可以引用同一个对象;因此,对一个变量的操作可能会影响另一个变量引用的对象。对于值类型,每个变量都有其自己的数据副本,对一个变量的操作不可能影响到另一个变量,in、ref和out参数变量除外;请参见in、ref和out参数修改器

在您的示例中,变量toSort和专用字段Sort.toSort都引用完全相同的列表。

这是因为列表是一个列表

C中有两种类型:引用类型和值类型。引用类型的变量存储对其数据对象的引用,而值类型的变量直接包含其数据。对于引用类型,两个变量可以引用同一个对象;因此,对一个变量的操作可能会影响另一个变量引用的对象。对于值类型,每个变量都有其自己的数据副本,对一个变量的操作不可能影响到另一个变量,in、ref和out参数变量除外;请参见in、ref和out参数修改器


在您的示例中,变量toSort和private字段Sort.toSort都引用了完全相同的列表。

如果您操作作为参数传递的集合,将对能够访问该集合的相同实例的每个类进行操作,这就是为什么您不需要返回新的lost

要了解有关引用和值类型的更多信息,请阅读:


如果您想了解.net framework如何帮助您对集合进行排序,请阅读

如果您操作一个作为参数传递的集合,该集合将对能够访问该集合的同一实例的每个类进行操作,这就是您不需要返回新的lost的原因

要了解有关引用和值类型的更多信息,请阅读:


如果您想了解.net framework如何帮助您对集合进行排序,请阅读

此操作之所以有效,是因为您正在进行就地排序。不会复制该列表,并且所有更改都是在按引用类型传递的原始列表上进行的。同样的事情也适用于数组和任何其他按引用传递类型

如果我可以建议您使用通用静态方法,使您的代码更快、更清晰,如下所示:

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
    }
}
然后您可以将其称为两种方式之一:

列表.快速排序; SortMethods.QuickSortlist;
这样做之所以有效,是因为您正在进行就地排序。不会复制该列表,并且所有更改都是在按引用类型传递的原始列表上进行的。同样的事情也适用于数组和任何其他按引用传递类型

如果我可以建议您使用通用静态方法,使您的代码更快、更清晰,如下所示:

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
    }
}
然后您可以将其称为两种方式之一:

列表.快速排序; SortMethods.QuickSortlist; 列表是一种引用类型。由于排序类只是维护对列表的引用,而不是复制它,因此原始列表中的内容由该类修改。列表是一种引用类型。由于Sort类只是维护对列表的引用,而不是复制它,因此原始列表中的内容由class.Gu修改
这很有意义,我没想到用引用和值类型来看待它,这是我多年来一直听到的。这很有道理。非常感谢。伙计们,这很有意义,我没想到要用引用和值类型来看待它,这是我多年来一直听到的。这很有道理。非常感谢。在整个程序中没有参数是通过引用传递的。@Servy-不是通过引用显式传递的,但它们是通过引用传递的。请参考约书亚·罗宾逊的回答。非常感谢你的建议,我本来就是这样的,所以我对此感到很自豪。我喜欢能够快速排序的想法,不管是哪种类型。最初的想法是只对字符串进行排序,但后来我想到了更大的排序。我更改它的原因是为了勾选我的项目的一些要求,1。数据排序,使用IComparable,2。泛型类和3的使用。递归。因此,这三种方法都能顺利完成。我现在确实将其更改为静态,但请查看我的编辑。此外,我的讲师建议使用带有最大和最小堆示例的优先级队列,但每个人都会这样做,我想做点什么unique@JamesWasson当定义或调用参数时,如果存在ref、out或in关键字,则仅通过引用传递参数。由于这些关键字都不存在,所以参数按值传递。Joshua的回答指出类型是引用类型,而不是通过引用传递参数。这些都是完全不同的东西,只有一个是正确的。在整个程序中没有参数是通过引用传递的。@Servy-不是通过引用显式传递的,但它们是通过引用传递的。请参考约书亚·罗宾逊的回答。非常感谢你的建议,我本来就是这样的,所以我对此感到很自豪。我喜欢能够快速排序的想法,不管是哪种类型。最初的想法是只对字符串进行排序,但后来我想到了更大的排序。我更改它的原因是为了勾选我的项目的一些要求,1。数据排序,使用IComparable,2。泛型类和3的使用。递归。因此,这三种方法都能顺利完成。我现在确实将其更改为静态,但请查看我的编辑。此外,我的讲师建议使用带有最大和最小堆示例的优先级队列,但每个人都会这样做,我想做点什么unique@JamesWasson当定义或调用参数时,如果存在ref、out或in关键字,则仅通过引用传递参数。由于这些关键字都不存在,所以参数按值传递。Joshua的回答指出类型是引用类型,而不是通过引用传递参数。这些是完全不同的事情,其中只有一件是真的。