如何解决使用python中的快速排序对链表进行排序
我是 Python 新手。我在链接列表中存储了以下书籍列表,我想使用快速排序对它们进行排序,但不幸的是,我遇到了一个问题。
class Node:
def __init__(self,data=None):
self.data = data
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.head = None
self.tail = None
def append_value(self,x):
if not isinstance(x,Node):
x = Node(x)
if self.is_empty():
self.head = x
else:
current = self.head
while current.next:
current = current.next
current.next = x
x.prev = current
self.tail = x
def length(self):
count = 0
current = self.head
while current:
count += 1
current = current.next
return count
def is_empty(self):
return self.head is None
def __str__(self):
to_print = ''
current = self.head
while current:
to_print += f'{current.data} <-> '
current = current.next
if to_print:
return f'[{to_print[:-5]}]'
return '[]'
def quick_sort(self,arr):
if self.length() < 2:
return self
else:
pivot = self.tail.data
smaller,equal,larger = [],[],[]
current = self.head
while current:
if current.data < pivot:
smaller.append(current.data)
elif current.data == pivot:
equal.append(current.data)
else:
larger.append(current.data)
current = current.next
return self.quick_sort(smaller) + equal + self.quick_sort(larger)
这是快速排序方法,但它在“返回 self.quick_sort(smaller) + equal + self.quick_sort(larger)”上给了我 RecursionError。如何使用快速排序对链表进行排序?
my_list = DoublyLinkedList()
my_list.append_value('In Search of Lost Time')
my_list.append_value('Ulysses by James Joyce')
my_list.append_value('Within a Budding grove')
my_list.append_value('The Guermantes Way')
my_list.append_value('In Search of Lost Time')
my_list.append_value('Sodom & Gomorrah')
my_list.append_value('One Hundred Years of Solitude')
my_list.append_value('War and Peace')
print(f'List of Books: {my_list}')
print(f'Quick Sort: {my_list.quick_sort(my_list)}')
解决方法
确实,发生错误是因为您将标准列表传递给 quick_sort
,而它期望参数是双向链表实例。
此外,如果在这个算法中允许使用列表,那就很奇怪了,因为人们可能想知道为什么首先会有一个双向链表。如果您打算使用列表,那么您不妨将数据存储在列表中并对列表进行排序。这不可能是目的。
关于代码的一些其他评论:
-
quick_sort
是类的方法,因此不必将链表也作为参数传递。相反,传递两个参数来标识该链表中子节的开始节点和结束节点。 -
最后的
return
语句有问题。如果quick_sort
确实要返回一个链表,那么+
不是您可以在这些列表上使用的运算符。此外,快速排序应该是一种就地排序算法,而+
建议创建一个新列表。由于它是就地的,您应该可以只返回self
。
所以,...你真的需要通过遍历链表并操作它来解决这个问题。
这是一种方法。首先定义两个允许在列表中任意位置插入和删除节点的方法:
def remove_node(self,node):
if node.prev:
node.prev.next = node.next
else:
self.head = node.next
if node.next:
node.next.prev = node.prev
else:
self.tail = node.prev
node.next = node.prev = None
return node
def insert_after(self,prev,node):
if not isinstance(node,Node):
node = Node(node)
node.prev = prev
if prev:
node.next = prev.next
prev.next = node
else:
node.next = self.head
self.head = node
if node.next:
node.next.prev = node
else:
self.tail = node
return self
后者实际上是比您已有的 append_value
更灵活的方法。你实际上可以利用这个新的来定义你的:
def append_value(self,x):
return self.insert_after(self.tail,x)
然后执行如下快速排序:
以开始和结束节点作为参数。从列表中提取(删除)结束节点并将其视为枢轴。让两个引用沿着这个子列表走向彼此,从末尾开始。当它们的值处于枢轴值的好的一侧时,让该参考移近一些。一旦您有两个引用,其值与枢轴相反,交换这两个节点中的数据。一旦这两个引用相互交叉,您就确定了两个分区。将枢轴节点注入到列表中,就在这两个分区之间。最后,使用递归对两个分区做同样的事情:
def quick_sort(self,start=None,end=None):
if not start and not end: # set default arguments:
start = self.head
end = self.tail
if not start or not end or start == end or end.next == start:
# The sublist is empty or has just one value
return self
# Extract the pivot node from the list
end,pivot = end.prev,self.remove_node(end)
pivotdata = pivot.data
# Define two references that will walk towards eachother:
right = end
left = start
while left and left.prev != right: # While they didn't cross over
if left.data <= pivotdata:
left = left.next
elif right.data >= pivotdata:
right = right.prev
else: # Swap values,not the nodes:
left.data,right.data = right.data,left.data
left = left.next
right = right.prev
# Insert the pivot node between the two partitions
self.insert_after(right,pivot)
# Sort the non-empty partitions recursively
if start.prev != pivot:
self.quick_sort(start,right)
if end.next != pivot:
self.quick_sort(left,end)
return self
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。