链表排序-归并排序和快速排序
LeetCode148 SortList
题意:给定一个链表,要求用O(n log n) 的复杂度进行排序。
直观的链表归并排序:
1 class Solution: 2 # @param head, a ListNode 3 # @return a ListNode 4 def sortList(self, head): 5 if not head or not head.next :return head 6 p , one,two=ListNode(0),head,head 7 p.next=head 8 while two and two.next: 9 p = one 10 one , two = one.next,two.next.next 11 p.next=None # 截断 12 lhead=self.sortList(head) 13 rhead=self.sortList(one) 14 return self.merge(lhead,rhead) 15 16 def merge(self,lhead,rhead): 17 head = ListNode(-1) #表头 18 p,prep=None,head 19 while lhead and rhead: 20 if lhead.val < rhead.val: 21 p ,lhead= lhead,lhead.next 22 else: 23 p,rhead=rhead,rhead.next 24 prep.next=p 25 prep=prep.next 26 27 while lhead: 28 p , lhead= lhead,lhead.next 29 prep.next=p 30 prep=prep.next 31 while rhead: 32 p,rhead=rhead,rhead.next 33 prep.next=p 34 prep=prep.next 35 36 return head.next
快速排序,因为是链表不能用下标快速访问,挖坑法不适用,这里采用《算法导论》中的单向双指针法,end记录边界不采用None截断
1 class ListNode(object): 2 def __init__(self, x): 3 self.val = x 4 self.next = None 5 6 class Solution(object): 7 def sortList(self, head): 8 """ 9 sort list using quick sort 10 :type head: ListNode 11 :rtype: ListNode 12 """ 13 if head is None: 14 return None 15 tail = self.get_tail(head) 16 head, tail = self.quick_sort(head, tail) 17 tail.next = None 18 return head 19 20 def quick_sort(self, head, tail): 21 """ 22 Sort in place 23 :param head: 24 :param tail: 25 :return: 26 """ 27 if head is not tail: 28 head_left, tail_left, head_ref, tail_ref, head_right, tail_right = self.quicksort_partition(head, tail) 29 if head_left is None: # if there is no node in left part after partition 30 head = head_ref 31 else: 32 head_left, tail_left = self.quick_sort(head_left, tail_left) 33 head = head_left 34 tail_left.next = head_ref 35 if head_right is None: # if there is no node in right part after partition 36 tail = tail_ref 37 else: 38 head_right, tail_right = self.quick_sort(head_right, tail_right) 39 tail_ref.next = head_right 40 tail = tail_right 41 return head, tail 42 43 44 def quicksort_partition(self, head, tail): 45 reference = tail 46 head_ref, tail_ref = reference, reference 47 head_left, tail_left, head_right, tail_right = None, None, None, None 48 49 sentinel = ListNode(None) # use sentinel to simplify the code 50 sentinel.next = head 51 node = sentinel 52 while node.next is not tail: 53 node = node.next 54 if node.val > reference.val: # put node into right part 55 if head_right is not None: 56 tail_right.next = node 57 tail_right = node 58 else: # right part is empty 59 head_right = node 60 tail_right = node 61 elif node.val < reference.val: # put node into left part 62 if head_left is not None: 63 tail_left.next = node 64 tail_left= node 65 else: # left part is empty 66 head_left = node 67 tail_left = node 68 else: # put node into reference part 69 tail_ref.next = node 70 tail_ref = node 71 return head_left, tail_left, head_ref, tail_ref, head_right, tail_right 72 73 def get_tail(self, node): 74 while node.next: 75 node = node.next 76 return node