在c#中实现快速排序时遇到问题

时间:2011-07-31 21:03:18

标签: c# quicksort

我在尝试让这个快速排序算法100%工作时遇到了一些麻烦。截至目前,当它试图交换2个相同的数字时,它会挂起一点(试图解决你在代码中看到的那个)。

这件事几乎就在那里。我只是不确定我错过了什么。我花了几个小时试图找出它无济于事。

我正在上课,不幸的是我的老师说他无法帮助我,因为我正在做泛型(额外的功劳)而他只能在C#中使用字符串或整数(他主要是java / c ++)老师....他很久没有和c#一起工作了。)

Quicksort静态类

class QuickSort<T> where T : IComparable<T>
{
    //No variables or properties, more of a helper class

    //This is the method that will be called by the user.
    //It ties the internal methods into one to sort the
    //array. It needs an array passed into it, As well as
    //the size of the array.
    public static void  QSort(T[] array,int size)
    {
        //If array is empty, or has 1 element, it is sorted.
        //Return immediatly.
        if (size == 1 || size == 0)
        { return; }
        else
        {   
            //Time to sort, pass in the array, the left bounds of 0,
            //and the right bounds of high - 1 (the last element).
            Partition(array, 0, size);
        }
    }

    //This method splits the work area in half, putting lower
    //values left of the pivot, and greater values right of
    //the pivot.
    private static void Partition(T[] array, int lower, int upper)
    {
        //If upper is less 1, then there is no
        //sorting that can be done.
        if ((upper - lower) < 2)
        { return; }

        //Get the right bound -1, to make sure it stays
        //within actual array bounds
        int left = lower;
        int right = upper-1;

        //Set pivot to equal the middle most array. I used this
        //expression because wikipedia mentions it will stop
        //overflow and invalid pivot position that can come
        //with exceptionally large arrays using the basic
        //(a+b)/2 equation.
        int pivot_index = left + (right - left) / 2;
        T pivot = array[pivot_index];

        while (left < right)
        {
            //array[left] < pivot
            while ((array[left].CompareTo(pivot) <= 0) && (left < right))
            {
                left++;
            }
            //array[right] > pivot
            while ((array[right].CompareTo(pivot) >= 0)&& (left < right))
            {
                right--;
            }


            if (left != right)
            {
                Swap(array, left, right);
                left++;
                right--;
            }
        }

            //Send in the lower bound, and the pivot point.
            Partition(array, lower, right);

            //Send in the pivot point as lower bound, and upper
            Partition(array, right+1, upper);

    }


    //This method simply swaps the first position with the second.
    private static void Swap(T[] array, int position1, int position2)
    {
        T tempHolder = array[position1];
        array[position1] = array[position2];
        array[position2] = tempHolder;
    }

}

主要课程

class Tester
{
    static void Main(string[] args)
    {

        ContiguousList<int> tester = new ContiguousList<int>(100);
        Random rand = new Random(5433);
        for (int ii = 0; ii < tester.Size; ii++)
        {
            tester.SetElement(ii, rand.Next(0, 100));
        }

        for (int ii = 0; ii < tester.Size; ii++)
        {
            Console.WriteLine(tester.GetElement(ii).ToString());
        }
        Console.WriteLine();



        tester.Sort();
        for (int ii = 0; ii < tester.Size; ii++)
        {
            Console.WriteLine(tester.GetElement(ii).ToString());
        }



    }
}

这对我来说相当困难,因为我可以遵循的唯一在线实现是c ++(找到一个好的伪代码解释,如果我可以使用指针&gt;。&lt;)或者它们仅用于排序整数。 / p>

我想也许缺少交换,或者我的逻辑处理if array [left] == array [right]是否有问题。

(哦,不要介意主要的连续列表...我们的老师让我们编写自己的智能阵列并告诉我们使用它,这样我们就可以看到智能数组是如何工作的。)

感谢任何帮助人员。我的大脑真的很难过这个。

- 编辑 我更改了循环,因此一个检查&gt; = 0,另一个&lt; 0去除不需要的支票。

- 编辑 我再次调整了一下,现在它似乎几乎排序了,但不完全,我的前10个元素是1,1,2,3,2,3,6,5,4,5所以某种程度上有些东西没有得到当值相同时,交换正确。

Edit-- 只需重新阅读我正在使用的快速排序解释/伪代码,并注意到一点“这个版本只适用于具有独特元素的数组”警告..​​....所以我是对的,因为当2个元素保持时,它必须做同样的价值,有些东西不起作用......虽然&gt;仍然难以解决它的问题。&lt;

2 个答案:

答案 0 :(得分:2)

由于第一个循环,左侧元素不能小于枢轴。由于第二个循环,正确的元素不能超过枢轴。因此,如果它们相等,那么它们必须都与枢轴相等,因此它们最终的阵列中的哪一半并不重要。

无论如何,我认为修改代码所需要做的就是稍微调整这些行:

        if (array[left].CompareTo(array[right]) == 0)
        {
            left++;
            right--;
        }
        else if (left != right)
        {
            Swap(array, left, right);
            left++;
            right--;
        }

但有一些简化:

  1. 由于left == right隐含array[left].CompareTo(array[right]) == 0),因此您的left != right测试是多余的。
  2. 作为必然结果,你总是向左递增并向右递减。所以你可以把它移到条件之外。
  3. 因此生成的代码如下所示:

            if (array[left].CompareTo(array[right]) != 0)
            {
                Swap(array, left, right);
            }
            left++;
            right--;
    

答案 1 :(得分:-1)

您应该更改交换方法以交换实际数据,而不是访问数组。在C#中你需要'ref'所以任何数据都作为参考发送:

    private static void Swap(ref T a, ref T b)
    {
        T temp = a;
        a = b;
        b = temp;
    }