单链表上递归快速排序的基本情况
我正在尝试在单链表上进行递归快速排序。基本情况是什么?当我到达它时我需要做什么才能让函数“倒回”并打印排序列表?这是一些代码,但我认为这是非常错误的......
public static void qSort(SLLNode first, SLLNode last)
{
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
if (first!=last)
{
while (head!=null)
{
if (head.data.compareToIgnoreCase(pivot.data)<0)
{
pivot.succ = head.succ ;
head.succ = first ;
first = head ;
qSort(first, pivot) ;
qSort(head, last) ;
}
qSort(first, pivot) ;
qSort(head, last) ;
}
}
}
重新表述我的问题:当我到达基本情况first==last
时,我需要做什么? > 如何使递归倒回并生成排序列表?
这是我更新的代码:
public static void qSort(SLLNode first, SLLNode last)
{
if (first==last)
{
return ;
}
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
while (head!=null)
{
if (head.data.compareToIgnoreCase(pivot.data)<0)
{
pivot.succ = head.succ ;
head.succ = first ;
first = head ;
qSort(first, pivot) ;
qSort(head, last) ;
}
qSort(first, pivot) ;
qSort(head, last) ;
}
}
I'm trying to get my head around a recursive quicksort on a singly linked list. What is the base case, and what do I need to do when I reach it in order for the function to 'rewind' and print a sorted list? Here is some code, but I think it's desperately wrong...
public static void qSort(SLLNode first, SLLNode last)
{
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
if (first!=last)
{
while (head!=null)
{
if (head.data.compareToIgnoreCase(pivot.data)<0)
{
pivot.succ = head.succ ;
head.succ = first ;
first = head ;
qSort(first, pivot) ;
qSort(head, last) ;
}
qSort(first, pivot) ;
qSort(head, last) ;
}
}
}
To rephrase my question: When I reach the base case first==last
, what do I need to do? How can I make the recursion rewind and produce the sorted list?
Here's my updated code:
public static void qSort(SLLNode first, SLLNode last)
{
if (first==last)
{
return ;
}
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
while (head!=null)
{
if (head.data.compareToIgnoreCase(pivot.data)<0)
{
pivot.succ = head.succ ;
head.succ = first ;
first = head ;
qSort(first, pivot) ;
qSort(head, last) ;
}
qSort(first, pivot) ;
qSort(head, last) ;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
一般来说,
对于快速排序的一般回顾,您可能应该回顾一下 快速排序-维基百科上的排序算法。简而言之,如果您使用
partition
辅助函数使列表进入这样一种状态,即小于枢轴点的所有内容都位于其左侧,大于枢轴点的所有内容都位于其左侧,则会更容易对吧。然后,您可以对枢轴的两侧递归地调用快速排序。EJP也有一个很好的点。我还没有见过链表上的快速排序。
不管怎样,让我们这样做吧
我看到用链表进行快速排序的方式,算法会是这样的,
它变得有点棘手,因为你必须跟踪
pivot - 1
,它不是'使用单链表是很自然的。此外,上述算法并没有真正考虑相等的元素。但一般的想法是,您最终会得到小于pivot
的所有内容在它之前,所有大于它的内容都在它之后,然后您再次为两侧调用qsort
。您的代码
让我们通过一个简单的案例来运行您的程序。
是我们的开始。
假设
给定列表的当前状态,对于每个元素,
if (head.data.compareToIgnoreCase(pivot.data)<0)
为 true。所以我们输入
if
语句,然后 do这给了我们
如果我有这个权利,那么对 Should 的调用
可能会是
所以你不会在整个过程中调用
qSort
再次列出。似乎您可能想继续浏览列表,直到小于枢轴的所有内容都位于列表的左侧,然后再递归调用 qSort。In General
For a general review on quick-sort, you should probably review the quick-sort algorithm on Wikipedia. In short, it's easier if you use a
partition
helper function to get your list into a state where everything less than your pivot point is to the left of it, and everything greater than the pivot point is to the right of it. You then call quick-sort recursively with both sides of the pivot.EJP also has a very good point. I haven't seen quick-sort on a linked list.
Let's Do It Anyway
The way I see a quick-sort with a linked-list, the algorithm would be something like
It gets a little tricky because you have to keep track of
pivot - 1
, which isn't very natural to do with a singly linked list. Also, the above algorithm doesn't really account for elements that are equal. But the general idea is that you end up with everything less thanpivot
being before it, and everything greater than it being after, and then you callqsort
again for both sides.Your Code
Let's run through your program with a simple case.
Is our start.
Gives us
Let's say
if (head.data.compareToIgnoreCase(pivot.data)<0)
is true for each element given the current state of the list.So we enter the
if
statement, and doThis gives us
If I have that right, then the call to
Should probably instead be
So you're not calling
qSort
over the whole list again. It also seems like you might want to instead keep going through your list until everything that is less than the pivot is to the left of it, before recursively callingqSort
.研究链表的快速排序是一件有用的事情。在研究任何算法时,重要的是要了解绝对需要什么。
在这种情况下,人们发现不需要随机访问迭代器。事实上,前向迭代器就足够了。
Stepanov 在 STL 中的大量工作就是提取此类信息。
这是一个简单的 C++ 实现。抱歉更改语言。
我只是交换数据而不是节点指针。后者与快速排序无关。
是的,我知道我对枢轴元素的选择可能会引起问题。
人们可以找到第一个和最后一个之间的距离 d,然后在 [0, d) 范围内选择一个随机数 x。现在将初始化为first的指针前进x次,并将其数据与first指向的数据交换。
最初的调用会是这样的
Investigating Quicksort for a linked list is a useful thing. In studying any algorithm it is important to understand what is absolutely required.
In the case here one discovers that random access iterators are not required. Indeed forward iterators are sufficient.
A lot of Stepanov's work with the STL was to distill such information.
Here is a simple implementation in C++. Sorry for the change of language.
I'm just swapping data instead of node pointers. Doing the latter has nothing to do with Quicksort.
And yes, I know my choice of pivot element can cause problems.
One could find the distance, d, between first and last and then pick a random number x in the range [0, d). Now advance a pointer initialized to first x times, and swap its data with the data pointed to by first.
The initial call would be something like
基本情况是一个包含 0 或 1 个元素的列表。
The base case is a list with 0 or 1 elements.
你不需要“倒带”。当您进行递归调用时,它会在调用完成时返回递归堆栈。
如果(第一个==最后一个)返回;
You don't need to "rewind." When you make a recursive call, it goes back up the recursion stack when the call finishes.
if(first==last) return;
从概念上讲,请注意,在
first==last
的基本情况下,您有一个元素的链接列表,因此它已经排序。我认为你的算法可能略有偏差?您需要一个循环,将小于枢轴的所有内容移动到上半部分,将大于枢轴的所有内容移动到下半部分。然后(循环完成后!)您可以递归地对两半进行排序。我发现你的做法有点不同,但我不相信这是正确的......
最后,正如其他人所说,对链接列表进行排序并不是一项非常有用的任务。你不会用自行车来拖拖车......
Conceptually, note that in a base case where
first==last
, you have a linked list of one element and thus it is already sorted.I think your algorithm may be slightly off?. You want a loop that moves everything less than the pivot to the first half, and everything greater to the second half. Then (after the loop is done!) you can recursively sort the halves. I see that yours is doing it a little differently, but I'm not convinced it's right....
Finally, as stated by others, sorting a linked list is not a very useful task. You wouldn't use a bike to tow a trailer....