如何干净利落地使用QuickSort对链表进行排序--Python
问题描述
使用快速排序对链接列表进行排序的最简洁方法是什么?我目前有以下内容,但不是很好。我想要一个类似Sort(Self)的函数,这样我就可以简单地使用list.sort(),并且我可以使用快速排序方法对我的链表进行排序。 潜在的方法,但不确定如何实现:从当前列表(Self)开始,让Pivot作为列表头部的数据,并创建两个新的链表:一个称为Small(包含数据小于Pivot的所有元素),另一个(包含除Pivot以外的所有剩余元素)。然后,调用Smaller.sort()和ther.sorte(),将当前列表设置为较小,然后追加Pivot并与其他列表合并。如果有人有任何想法...
# 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("
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("
Before Sort ", end = "")
obj.display()
obj.quick_sort(obj.head, obj.last_node())
print("
After Sort ", end = "")
obj.display()
if __name__ == "__main__": main()
解决方案
虽然您的代码似乎可以工作,但有时不需要将值从一个节点移动到另一个节点,而是需要移动节点本身(保持节点值与节点实例相关联)。
下面是我建议如何在单链表中实现类似快速排序的算法。我删除了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()
相关文章