【问题标题】:How can I prevent my Quicksort Algorithm from throwing a StackOverflowException如何防止我的快速排序算法抛出 StackOverflowException
【发布时间】:2021-08-25 08:21:07
【问题描述】:

我正在尝试用 C# 编写一个 quicksort 算法,而我最近一直得到 System.StackOverflowExceptions 并且不知道为什么。

这是我的班级:

    class quicksort : sortalgorithm
{
    int pivotIndex = -1;
    int pivotSwapped = 0;
    Random rand = new Random();

    public quicksort(int[] arr)
    {
        if (arr.Length < 5)
        {
            throw new Exception("Array has too few Entries");
        }
        toSort = arr;
    }

    protected override int sort()
    {
        if (pivotIndex == -1) getPivot();
        int indexL = getIndexLeft();
        int indexR = getIndexRight();
        if (indexR != -1 && indexL != -1 && indexL != toSort.Length-1)
        {
            swap(indexL, indexR);
        }
        if (indexL > indexR)
        {
            Console.WriteLine("Index thingy");
            swap(toSort.Length - 1, indexL);
            pivotSwapped++;
            if (pivotSwapped == toSort.Length - 1)
            {
                return 1;
            }
            else
            {
                Console.WriteLine("new piv");
                pivotSwapped++;
                getPivot();
                sort();
                return -1;
            }
        }
        else
        {
            sort();
            return -1;
        }
    }

    private void swap(int i, int j)
    {
        int temp = toSort[i];
        toSort[i] = toSort[j];
        toSort[j] = temp;
    }

    private void getPivot()
    {
        pivotIndex = rand.Next(0, toSort.Length - 1);
        swap(toSort.Length - 1, pivotIndex);
    }

    private int getIndexLeft() // Larger then Pivot Starting: Left
    { //Error Here
        int itemFromLeft = -1;
        for (int i = 0; i < toSort.Length - 1; i++)
        {
            if (toSort[i] >= toSort[toSort.Length - 1])
            {
                itemFromLeft = i;
                i = toSort.Length + 1;
            }
        }
        //Console.WriteLine(itemFromLeft);
        return itemFromLeft;
    }

    private int getIndexRight()// Smaller then Pivot Starting: Right
    {
        int itemFromRight = -1;
        for (int i = toSort.Length - 1; i >= 0; i--)
        {
            if (toSort[i] < toSort[toSort.Length - 1])
            {
                itemFromRight = i;
                i = -1;
            }
        }
        //Console.WriteLine(itemFromRight);
        return itemFromRight;
    }
}

我希望有人可以帮助我。

附:在这种情况下,sortalgorithm 类只有数组 toSort

我的控制台输出总是有点像这样:

[4, 28, 62, 33, 11] // The unsorted array
Index thingy
new piv
Index thingy
new piv
Index thingy
new piv

Process is terminated due to `StackOverflowException`.

【问题讨论】:

  • 在调试器中运行你的程序,当 StackOverflow 发生时,检查调用堆栈。
  • 我看不到您提供的代码与算法 C. A. R.Hoare 之间的联系,该算法显示为 ACM ALGORITHM 64 QUICKSORT(超出类名)。有没有你在编码时尝试遵循的快速排序演示文稿?

标签: c# algorithm quicksort


【解决方案1】:

Hoare 分区方案的这个简单实现演示了如何通过在较小的分区上递归并循环返回较大的分区来避免堆栈溢出,这是原始快速排序中使用的一个想法。堆栈空间复杂度限制在 O(log2(n)),但最坏情况下的时间复杂度仍然是 O(n^2)。

        static public void Quicksort(int [] a, int lo, int hi)
        {
            while(lo < hi){                 // while partition size > 1
                int p = a[(lo + hi) / 2];
                int i = lo, j = hi;
                i--;                        // Hoare partition
                j++;
                while (true)
                {
                    while (a[++i] < p) ;
                    while (a[--j] > p) ;
                    if (i >= j)
                        break;
                    int t = a[i];
                    a[i] = a[j];
                    a[j] = t;
                }
                i = j++;                    // i = last left, j = first right
                if((i - lo) <= (hi - j)){   // if size(left) <= size(right)
                    Quicksort(a, lo, i);    //   recurse on smaller partition
                    lo = j;                 //   and loop on larger partition
                } else { 
                    Quicksort(a, j, hi);    //   recurse on smaller partition
                    hi = i;                 //   and loop on larger partition
                }
            }
        }

【讨论】:

    【解决方案2】:

    堆栈溢出错误通常发生在递归出错时,即函数不断调用自身,直到堆栈中没有剩余空间来容纳所有引用,

    唯一明显的候选者是

                **sort();**
                return -1;
            }
        }
        else
        {
            **sort();**
            return -1;
        }
    

    所以一个或另一个递归调用可能不正确,需要删除,我怀疑问题将得到解决

    编辑:

    因为您无法调试代码 这就是快速排序的样子

    public int sort()
    {
        qsort(0, toSort.Length - 1);
        return 0;
    }
    
    private void qsort( int left, int right)
    {
        if (left < right)
        {
            int pivot = Partition( left, right);
    
            if (pivot > 1)
            {
                qsort( left, pivot - 1);
            }
            if (pivot + 1 < right)
            {
                 qsort( pivot + 1, right);
            }
        }
    }
    private int Partition( int left, int right)
    {
        int pivot = toSort[left];
        while (true)
        {
    
            while (toSort[left] < pivot)
            {
                left++;
            }
    
            while (toSort[right] > pivot)
            {
                right--;
            }
    
            if (left < right)
            {
                if (toSort[left] == toSort[right]) return right;
    
                int temp = toSort[left];
                toSort[left] = toSort[right];
                toSort[right] = temp;
    
    
            }
            else
            {
                return right;
            }
        }
    }
    

    注意如果 left >= right 什么都不做

    【讨论】:

    • 问题是,我想编写一个快速排序算法,这取决于递归。我也不能过多地更改代码,因为我想比较所有算法
    • 您需要添加正确的检查和平衡,以防止递归发生超出其应有的次数
    • 我会从您的输出中建议 indexL &gt; indexR 不正确,否则“Index thingy”将向输出流发送垃圾邮件,因此该子句不正确或第二次调用排序不正确,您应该返回一个失败的状态,而不是重新开始排序
    • 根据Explaination(输入了正确的时间戳,暂停并阅读文字)我关注了,是正确的。
    • 感谢@AlirezaAhmadi,我一直在努力寻找确切的失败点,但你打败了我
    猜你喜欢
    • 2019-09-25
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 2020-03-18
    • 2020-03-23
    • 2016-11-24
    • 2018-05-17
    • 1970-01-01
    相关资源
    最近更新 更多