C# 快速排序递归实现的计算时间非常长
我试图实现一个快速排序算法,但它似乎有一些不好的行为。它确实对一个元素数组进行排序,但需要花费太多的时间,确切地说,大约165个元素需要花费太多的时间,但它一次都没有完成(运行了几分钟)。我尝试过调试,并意识到可能需要多次迭代才能完成,但仍然会产生正确的输出。代码写在继承列表的类中,应该重新编程。我做错了吗?我觉得这个过程需要太多的迭代。我的意思是,它被称为QUICKsort。下面是代码:C# 快速排序递归实现的计算时间非常长,c#,recursion,quicksort,C#,Recursion,Quicksort,我试图实现一个快速排序算法,但它似乎有一些不好的行为。它确实对一个元素数组进行排序,但需要花费太多的时间,确切地说,大约165个元素需要花费太多的时间,但它一次都没有完成(运行了几分钟)。我尝试过调试,并意识到可能需要多次迭代才能完成,但仍然会产生正确的输出。代码写在继承列表的类中,应该重新编程。我做错了吗?我觉得这个过程需要太多的迭代。我的意思是,它被称为QUICKsort。下面是代码: using System; using System.Collection.Generic;
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;
}
}
}
}
使用系统;
使用System.Collection.Generic;
公共类个人列表:列表{
公共void快速排序(int开始,int结束){
如果(开始<结束){
int pivot=分区(开始、结束);
如果(轴>1){
快速排序(开始、结束-1);
}
如果(枢轴+1<结束){
快速排序(轴+1,结束);
}
}
}
公共整数分区(整数开始、整数结束){
每个人=新的人();
int tmp=this[start].ID;
while(true){
while(此[start].IDtmp){
结束--;
}
如果(开始<结束){
if(this[start].ID==this[end].ID){
返回端;
}否则{
per=此[开始];
此[开始]=此[结束];
这[结束]=每;
}
}否则{
返回端;
}
}
}
}
请看下一行
quickSort(start, end -1);
快速排序是一种分而治之的算法,它将它处理的数据集划分为较小的数据块,并递归地处理较小的数据块(然后对这些数据块进行划分)。您在这里所做的是,您不是在数据集的下半部分(它应该如何工作)上调用快速排序,而是在由最上面的项缩减的数据集上调用快速排序。由于这一行,递归操作的数据集比预期的要大,因此需要更长的时间
在简化数据集上操作的正确行是
quickSort(start, pivot)
由于数据点是相对于pivot元素进行预排序的,因此可以将数据集划分为比pivot元素低和高的数据块。因此我甚至相信
quickSort(start, pivot - 1)
就够了
编辑
根据(伪代码应该是可读的,尽管它是德语的)代码应该看起来更像
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;
}
私有int分区(int开始,int结束)
{
var pivot=结束;
var i=启动;
var j=结束-1;
int tmp=this[pivot].ID;
做
{
while(此[i].IDtmp&&j>start)
{
j--;
}
if(itmp)
{
交换(i,枢轴);
}
返回i;
}
我们必须使用单独的循环变量,因为它们是根据
开始
和结束
进行检查的,如果开始
和结束
本身发生了变化,我们将丢失这些信息。您构建自己的循环变量而不是使用现有的排序算法有什么特别的原因吗?(开始,透视)
?但我仍在检查代码。。。这就是我的第一印象。另外,Person per=new Person()代码>您正在此处创建一个新的Person对象。不需要。您只需要本地变量。无论如何,您都可以将其设置为[start]。如果这是一种个人学习方法,请借此机会学习如何使用探查器。这是一种低估开发人员技能的方式。如果我们看的是实际的代码,那就太好了。提示-C#是一种区分大小写的语言,因此您在这里展示的内容无法编译。那么,我们怎么知道这与您实际测试的结果有多接近呢?更改为quickSort(start,pivot)
会在int tmp=this[start].ID代码>列表包含165个元素我刚刚运行了10k个列表元素,它没有给我一个溢出异常。Person
是如何定义的?当异常发生时,start
的值是多少?只有属性为“ID”的类,如public int ID{get;set;}