我一直是算法问题,需要我对链表和数组进行快速排序算法的实现 我已经完成了两个部分,算法正在运行,但似乎我的快速排序链表实现中存在一些错误。
这是我的快速排序链接列表实现。
public static void SortLinkedList(DataList items, DataList.Node low, DataList.Node high)
{
if( low != null && low !=high)
{
DataList.Node p = _PartitionLinkedList(items, low, high);
SortLinkedList(items, low, p);
SortLinkedList(items, p.Next(), null);
}
}
private static DataList.Node _PartitionLinkedList(DataList items, DataList.Node low, DataList.Node high)
{
DataList.Node pivot = low;
DataList.Node i = low;
for (DataList.Node j = i.Next(); j != high; j=j.Next())
{
if (j.Value().CompareTo(pivot.Value()) <= 0)
{
items.Swap(i.Next(),j);
i = i.Next();
}
}
items.Swap(pivot, i);
return i;
}
这是快速排序数组实现
public static void SortData(DataArray items, int low, int high)
{
if (low < high)
{
int pi = _PartitionData(items, low, high);
SortData(items, low, pi - 1);
SortData(items, pi + 1, high);
}
}
static int _PartitionData(DataArray arr, int low, int high)
{
double pivot = arr[high];
int i = (low - 1);
for (int j = low; j <= high - 1; j++)
{
if (arr[j].CompareTo(pivot)<=0)
{
i++;
arr.Swap(i,j);
}
}
arr.Swap(i + 1, high);
return i + 1;
}
这是快速排序数组和链表性能。 (左,右时间)
Picture
如你所见,qs链表需要10分钟来排序6400个元素。我不认为这是正常的..
另外我不认为它是因为数据结构,因为我使用相同的结构进行选择排序,并且链表和数组的性能都相似。
GitHub repo,以防我忘记提供一些代码。 Repo
答案 0 :(得分:0)
我会查看你的链表,特别是swap方法。除非我们看到链表的实现,否则我认为问题领域就在那里。
你有没有理由使用链接列表?他们有o(n)搜索,这使得快速排序n ^ 2lg(n)排序。
另一种方法是将链接列表中的所有项目添加到列表中,对列表进行排序,然后重新创建链接列表。 List.Sort()使用快速排序。
public static void SortLinkedList(DataList items)
{
list<object> actualList = new list<object>();
for (DataList.Node j = i.Next(); j != null; j=j.Next())
{
list.add(j.Value());
}
actualList.Sort();
items.Clear();
for (int i = 0; i < actualList.Count;i++)
{
items.Add(actualList[i]);
}
}
答案 1 :(得分:0)
对于6400个元素来说,10分钟是很长的一段时间。它通常需要2到3个可怕的错误,而不只是一个。
不幸的是,我只看到一个可怕的错误:你对open(FILE,'data.txt');
my $line = <FILE>;
my @lines = <FILE>;
print @lines;
while (<FILE>) {
print "$_";
}
的第二次递归调用一直到列表的末尾。你想让它停在SortLinkedList(items, p.Next(), null);
。
这可能占了10分钟,但似乎有点不太可能。
即使您修复了上述错误,它也会让我觉得您的排序不正确 - 请务必测试输出!
答案 2 :(得分:0)
链表的快速排序通常与数组的快速排序略有不同。使用第一个节点的数据值作为透视值。然后代码创建3个列表,一个用于值&lt; pivot,一个用于值== pivot,一个用于值&gt;枢。然后它对&lt;进行递归调用。枢轴和&gt;枢轴列表。当递归调用返回时,这3个列表现在被排序,因此代码只需要连接3个列表。
要加速列表的连接,请跟踪指向最后一个节点的指针。要简化此操作,请使用循环列表,并使用指向最后一个节点的指针作为访问列表的主要方式。这使得追加(加入)列表更简单(无扫描)。进入函数后,使用last-&gt; next以获取指向列表第一个节点的指针。
两种最坏情况数据模式已经是已排序数据或已经反向排序的数据。如果使用带有指向最后一个节点方法的指针的循环列表,那么最后一个节点和第一个节点的平均值可以用作2的中位数,这可能有所帮助(注意节点的列表==枢轴可能最终为空)。
最坏情况时间复杂度为O(n ^ 2)。最坏情况下的堆栈使用是O(n)。可以通过在列表中较小的列表上使用递归来减少堆栈使用量。枢轴和列表&gt;枢。返回后,现在排序的较小列表将与list == pivot连接并保存在第4个列表中。然后排序过程将迭代剩余的未排序列表,然后合并(或可能加入)保存的列表。
使用任何方法(包括bottom up merge sort)对链接列表进行排序比将链接列表移动到数组,排序数组,然后从排序数组创建链接列表要慢。然而,我描述的快速排序方法比使用带链表的数组定向算法要快得多。