鏈表的快排和歸併排序

鏈表快排

對一個單鏈表用快排的方式排序

快排的關鍵在於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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章