繁体   English   中英

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

[英]Creating a quick sort using recursion and generics

我想问一下我创建的排序通用类。 我使用了今年学到的许多不同概念,并将其组合到一个不错的类中,该类可以用来对任何东西进行排序(当然,如果它是一个类,则该类具有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);
            }
        }


    }

我只有一个问题,就是我在互联网上使用的quickSort,然后自己将其转换为使用泛型。 我了解实际排序的工作方式。 我只想知道,为什么我不必退货。 我有点困惑。 我看到它实际上是在切换列表的值,但是我不知道它如何访问我发送的列表。 因为在我称之为的地方我可以做到这一点

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

因此,我只使用原始列表,并且comboBox中将包含A,B和C。

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

编辑:

 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);
            }
        }


    }

这是因为List<T>引用类型

C#中有两种类型:引用类型和值类型。 引用类型的变量存储对其数据(对象)的引用,而值类型的变量直接包含其数据。 对于引用类型,两个变量可以引用相同的对象。 因此,对一个变量的操作会影响另一变量引用的对象。 对于值类型,每个变量都有其自己的数据副本,并且对一个变量的操作不可能影响另一个变量(除非是in,ref和out参数变量;请参阅in,ref和out参数修饰符)。

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

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

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

如果您想了解.net框架如何帮助您进行集合排序,请阅读此处

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

基本上这段代码:

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

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

之所以起作用,是因为您正在就地排序 不创建列表的副本,并且所有更改都在通过Reference Type传递的原始列表上进行。 数组和引用类型的任何其他传递都可以使用相同的方法。

如果我建议让您的代码更快一点,更干净一点,那就是使用通用静态方法,如下所示:

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
    }
}

然后,您可以使用以下两种方法之一进行调用:

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

暂无
暂无

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

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