如何干净地使用 QuickSort 对链表进行排序 - Python
Posted
技术标签:
【中文标题】如何干净地使用 QuickSort 对链表进行排序 - Python【英文标题】:How to cleanly use QuickSort to sort Linked List - Python 【发布时间】:2021-12-15 19:30:46 【问题描述】:使用快速排序对链表进行排序的最简洁方法是什么?我目前有以下,但不是很好。我正在使用诸如 sort(self) 之类的函数,因此我可以简单地使用 list.sort() 并且我会通过快速排序方法对我的链表进行排序。
可能的方法但不知道如何实现:从当前列表(self)开始,让pivot为列表头部的数据,并创建两个新的链表:一个称为smaller(包含其数据的所有元素小于枢轴)和另一个(包含所有剩余元素,除了枢轴)。然后,调用smaller.sort()和other.sort(),将当前列表设置为更小,然后追加pivot并与other合并。
如果有人有任何想法......
# Node of LinkedList
class Node :
def __init__(self, data) :
# set node value
self.data = data
self.next = None
class MyLinkedList :
# Class constructors
def __init__(self) :
self.head = None
self.tail = None
# insert node at last of linke list
def insert(self, value) :
# Create a node
node = Node(value)
if (self.head == None) :
# When linked list empty add first node
self.head = node
self.tail = node
else :
# Add new node at end of linked list
self.tail.next = node
self.tail = node
# Display linked list nodes
def display(self) :
if (self.head != None) :
print("\n Linked List :", end = "")
temp = self.head
while (temp != None) :
print(" ", temp.data, end = "")
temp = temp.next
if (temp == self.head) :
# avoid loop
return
else :
print("Empty Linked List", end = "")
# Find last node of linked list
def last_node(self) :
temp = self.head
while (temp != None and temp.next != None) :
temp = temp.next
return temp
# Set of given last node position to its proper position
def parition(self, first, last) :
# Get first node of given linked list
pivot = first
front = first
temp = 0
while (front != None and front != last) :
if (front.data < last.data) :
pivot = first
# Swap node value
temp = first.data
first.data = front.data
front.data = temp
# Visit to next node
first = first.next
# Visit to next node
front = front.next
# Change last node value to current node
temp = first.data
first.data = last.data
last.data = temp
return pivot
# Perform quick sort in given linked list
def quick_sort(self, first, last) :
if (first == last) :
return
# Find pivot node
pivot = self.parition(first, last)
if (pivot != None and pivot.next != None) :
self.quick_sort(pivot.next, last)
if (pivot != None and first != pivot) :
self.quick_sort(first, pivot)
def main() :
obj = MyLinkedList()
# Create linked list
obj.insert(41)
obj.insert(5)
obj.insert(7)
obj.insert(22)
obj.insert(28)
obj.insert(63)
obj.insert(4)
obj.insert(8)
obj.insert(2)
obj.insert(11)
print("\n Before Sort ", end = "")
obj.display()
obj.quick_sort(obj.head, obj.last_node())
print("\n After Sort ", end = "")
obj.display()
if __name__ == "__main__": main()
【问题讨论】:
“我没有节点类、链表类等”:你的第一个代码块有它们。那么你想要什么:是否有类的解决方案?如果您只包括一次尝试,并准确指出它的问题所在,那就太好了。目前你的问题“任何想法”太宽泛了。 简单看一下我目前的快速排序,不难看出效率不高,感觉还可以改进。没有类的提及是指不同的代码(我已删除以避免混淆)并且原始帖子已被更正。 ~~~~ 我是否应该将其作为一种解决方法:将数据值放入数组中,使用快速排序对数组进行排序,然后将所有内容追加回链表? 如果您的代码有效,并且您要求在效率(或最佳实践等)方面进行审查,那么这个问题更适合CodeReview 【参考方案1】:虽然您的代码似乎可以工作,但有时需要不要将值从一个节点移动到另一个节点,而是移动节点本身(保持节点值与节点实例相关联)。
以下是我建议在单链表中实现类似快速排序的算法的方法。我删除了tail
属性并将大部分逻辑移到Node
类中:
class Node:
def __init__(self, data, nxt=None):
self.data = data
self.next = nxt
def __iter__(self):
curr = self
while curr:
node = curr
curr = curr.next
yield node
def values(self):
return (node.data for node in self)
def partition(self):
nodes = iter(self)
next(nodes) # skip self
left = self # left partition always has pivot node as its tail
pivotvalue = self.data
right = None
for curr in nodes:
# Prefix the current node to the relevant partition
if curr.data < pivotvalue:
curr.next = left
left = curr
else:
curr.next = right
right = curr
self.next = None # Terminate the left partition
return left, right
def quick_sort(self):
if not self.next: # Base case: one node only
return self
left, right = self.partition()
# Left partition has at least one node (the pivot node, which remains its tail)
left = left.quick_sort()
# Right partition could be empty
if right:
right = right.quick_sort()
self.next = right # Chain the two sorted partitions
return left
def is_sorted(self):
values = self.values()
prev = next(values)
for data in values:
if data < prev:
return False
prev = data
return True
class MyLinkedList:
def __init__(self, *values):
self.head = None
self.prefix(*values)
def prefix(self, *values):
for data in reversed(values):
self.head = Node(data, self.head)
def values(self):
if self.head:
return self.head.values()
def __str__(self): # Preferred over a display() method
return "[" + "->".join(map(str, self.values())) + "]"
def quick_sort(self):
self.head = self.head and self.head.quick_sort()
def is_sorted(self):
return self.head is not None and self.head.is_sorted()
from random import shuffle
def main():
# Perform 100 tests with shuffled lists of 20 values
for _ in range(100):
values = list(range(20))
shuffle(values)
obj = MyLinkedList(*values)
print("Before Sort")
print(obj)
obj.quick_sort()
print("After Sort")
print(obj)
if not obj.is_sorted():
raise ValueError("not sorted!")
if __name__ == "__main__":
main()
【讨论】:
我完全重写了我的答案。让我知道这是否有用。以上是关于如何干净地使用 QuickSort 对链表进行排序 - Python的主要内容,如果未能解决你的问题,请参考以下文章