C# 另一个快速排序堆栈溢出

C# 另一个快速排序堆栈溢出,c#,quicksort,stack-overflow,C#,Quicksort,Stack Overflow,所以我一直在尝试自己实现一个快速排序,只是想从中学习一些东西,但它也会生成stackoverflowexception,但我似乎找不到原因 有人能给我一个线索吗 public void Partition(List<int> valuelist, out List<int> greater, out List<int> lesser) { lesser = new List<int>(); // <

所以我一直在尝试自己实现一个快速排序,只是想从中学习一些东西,但它也会生成stackoverflowexception,但我似乎找不到原因

有人能给我一个线索吗

  public void Partition(List<int> valuelist, out List<int> greater, out List<int> lesser)
        {
            lesser = new List<int>();  // <-- Stackoverflow exception here!
            greater = new List<int>();

            if (valuelist.Count <= 1)
                return;

            pivot = valuelist.First();

            foreach (int Element in valuelist)
            {
                if (Element <= pivot)
                    lesser.Add(Element);
                else
                    greater.Add(Element);
            }
        }

        public List<int> DoQuickSort(List<int> list)
        {
            List<int> great;
            List<int> less;

            Partition(list, out great, out less);

            DoQuickSort(great);
            DoQuickSort(less);

            list.Clear();
            list = (List<int>)less.Concat(great);

            return list;

        }
public void分区(列出valuelist、out List较大、out List较小)
{

lesser=new List();//您正在做一个无限循环

  DoQuickSort(great);
你需要一种方法,用一个标志或一个条件来摆脱这个循环

编辑
我要补充的是,在调试模式下,使用默认设置,在抛出异常之前,递归调用只能达到10000到16000之间,在发布模式下,递归调用只能达到50000到80000之间,这一切都取决于实际执行的代码

如果要处理大量的值,可能需要使用对象管理自己的递归调用

查看崩溃前有多少调用的示例代码;
(调试;14210调用,释放80071调用)


您没有在对
DoQuicksort
的递归调用中设置任何条件,因此它永远不会停止递归,从而导致堆栈溢出。如果列表包含多个元素,您应该只对其调用
DoQuicksort


编辑:正如威尔在评论中所说,这是一种非常缓慢的“快速排序”方法。您应该查看Wikipedia上提到的就地分区算法。

我认为您的代码中的一个问题是在对列表进行分区时保留了pivot值。这意味着您将遇到一种情况,即所有值都分区为较大值或较小值,并且分区将停止工作。这将影响不允许您再拆分其中一个列表,因此分区方法中的退出条件永远不会满足

您应该选择一个pivot值,从列表中删除pivot元素(代码中缺少这一部分),将其分为较大列表和较小列表,对它们进行排序(递归),然后连接较小列表、pivot元素(代码中自然也缺少这一元素)和较大列表


我可以发布一个更新的、有效的代码示例,但由于您处于“学习模式”,我会保密,直到你要求:)

给它一些小数据进行排序,然后用调试器检查逻辑是否错误,这不是最好的方法吗?我不认为任何依赖于创建大量集合和复制大量值的排序算法都可以称为“快速”。你应该重命名它“内存密集型slogsort保证尽可能慢。"@雷尼尔:依靠调试器来发现逻辑错误是相当懒惰的。有时这是不可避免的,但最好能在没有调试器帮助的情况下找到错误。@谢谢你指出这一点,我在这里试图学习一些东西,而不是做算法优化。@Tony最好的办法是对你的colle的索引进行分区操作。在一个集合中切换两个元素的位置比创建两个新集合并将值复制到其中要快一点。祝算法学习好运;我买了Knuth关于算法的论文,在阅读了前几章之后,我从屋顶上跳了下来。对-因为轴心被作为
太好了
,因此每次都会使用相同的透视。是的,DoQuickSort方法中没有任何条件检查。分区方法足够聪明,可以知道何时退出,但调用方没有进行这种检查。我是否每次都删除一个新的透视值?然后将其重新添加到正确的位置@the分区结束了?困惑了?!?托尼:我想维基百科文章中的伪代码示例可能会帮你解决这个问题:
   static int s = 1;
    static void Main(string[] args)
    {
        o();
    }

    static void o()
    {
        s++;
        Console.WriteLine(s.ToString());
        o();
    }