鏈表快排
對一個單鏈表用快排的方式排序
快排的關鍵在於partition函數,因爲單鏈表是不能倒序遍歷的,因此不能通過頭尾雙指針向內夾的partition函數,而是用都是從頭開始的雙指針方式,具體的兩種partition函數可以參考:快排的兩種partition函數
這裏鏈表快排和數組快排partition函數中關鍵的不同點在於:partition函數中遍歷結束的方式,和遞歸結束的方式
# 鏈表快排
class Node:
def __init__(self, val):
self.val = val
self.next = None
def bulid_list(data_list):
head = Node(0)
cur = head
for val in data_list:
cur.next = Node(val)
cur = cur.next
return head.next
def print_list(root):
while root:
print(root.val)
root = root.next
def partition(start, end):
left = start
right = start
while right != end: # 遍歷到end爲止
if right.val<start.val:
left = left.next
left.val, right.val = right.val, left.val
right = right.next
start.val, left.val = left.val, start.val
return left
def quick_sort(left, right):
if left!=right: # 遞歸的終止條件是左右指針不相等
index = partition(left, right)
quick_sort(left, index) # 這兩行也要注意,這裏以index結束,前半部分並不會有它
quick_sort(index.next, right) # 這裏要以index.next開始
array = [1,6,0,-1]
root = bulid_list(array)
head = root
print_list(root)
quick_sort(head, None)
print_list(head)
鏈表的歸併排序
有兩個關鍵的地方:
1、獲取一個單鏈表的中點位置,用快慢指針的方法
2、根據中點截斷一個鏈表,將中間節點位置的next設置爲None,就將鏈表斷開了,這一點還是很巧妙的
其他地方實際上和數組的歸併類似
class LinkSort:
def get_mid_of_list(self, head):
if not head:
return head
p = head.next
q = head
while p:
p = p.next
if p:
p = p.next
q = q.next
return q
def merge_sort(self, head):
if not head or not head.next:
return head
mid = self.get_mid_of_list(head)
left = head
right = mid.next
mid.next = None # 這一步比較關鍵
p = self.merge_sort(left)
q = self.merge_sort(right)
pre = Node(-1)
cur = pre
while p and q:
if p.val < q.val:
cur.next = p
cur = p
p = p.next
else:
cur.next = q
cur = q
q = q.next
cur.next = p or q # 返回p和q中的非空值
return pre.next