Exceptionnel用于递归执行快速排序的长计算时间

时间:2017-10-13 08:50:39

标签: c# recursion quicksort

我试图实现一个快速排序算法,但似乎有一些不好的行为。它确实对元素数组进行了排序,但它需要花费太多时间,确切地说,它需要花费大量时间才能完成大约165个元素(它运行了几分钟)。我尝试调试并意识到可能需要多次迭代才能完成,仍然可以产生正确的输出。代码写在一个继承List的类中,应该进行逐步编程。我做错了吗?我觉得这个过程需要太多的迭代。我的意思是,它是calles 快速排序。这是代码:

  using System;
  using System.Collection.Generic;

  public class PersonList : List<Person>{ 
       public void quickSort(int start, int end){
            if(start < end){
                 int pivot = partition(start, end);
                 if(pivot > 1){
                      quickSort(start, end -1);
                 }
                 if(pivot + 1 < end){
                      quickSort(pivot + 1, end);
                 }
            }
       }




       public int partition(int start, int end){
            Person per = new Person();
            int tmp = this[start].ID;
            while(true){
                 while(this[start].ID < tmp){
                      start++;
                 }
                 while(this[end].ID > tmp){
                      end--;
                 }
                 if(start < end){
                      if(this[start].ID == this[end].ID){
                           return end;
                      } else{
                           per = this[start];
                           this[start] = this[end];
                           this[end] = per;
                      }
                 } else{
                      return end;
                 }
            }
       }          
 }

1 个答案:

答案 0 :(得分:1)

请查看以下内容

quickSort(start, end -1);

QuickSort是一种分而治之的算法,它将操作的数据集划分为较小的块,并在较小的块上递归操作(然后将其分开)。你在这里做的是,你没有在数据集的较低“一半”(它应该如何工作)调用QuickSort,而是在最顶层项目减少的数据集上。由于这一行,递归操作的方式比它应该做的更大的数据集,因此需要更长的时间。

对缩小数据集进行操作的正确行将是

quickSort(start, pivot)

由于数据点是相对于pivot元素预先排序的,因此您可以将数据集划分为低于和高于pivot元素的块。因此我甚至相信

quickSort(start, pivot - 1)

就足够了。

修改

根据German Wikipedia(伪代码应该是可读的,虽然它是德语)代码看起来应该更像

private int Partition(int start, int end)
{
    var pivot = end;

    var i = start;
    var j = end - 1;

    int tmp = this[pivot].ID;

    do
    {
        while (this[i].ID < tmp && i < end)
        {
            i++;
        }

        while (this[j].ID > tmp && j > start)
        {
            j--;
        }

        if (i < j)
        {
            Swap(i, j);
        }
    }
    while (i < j);


    if (this[i].ID > tmp)
    {
        Swap(i, pivot);
    }

    return i;
}

我们必须使用单独的循环变量,因为它们会针对startend进行检查,如果startend本身发生了变化,我们就会丢失此信息。< / p>