1)選定一個基準元素;
2)通過一趟排序,將全部元素分紅兩部分;
3)分別對兩部分重複上述操做,直到全部元素都已排序成功。 python
由於單鏈表只能從鏈表頭節點向後遍歷,沒有prev指針,所以必須選擇頭節點做爲基準元素。這樣第二步操做的時間複雜度就爲O(n)。因爲以後都是分別對兩部分完成上述操做,所以會將鏈表劃分爲logn個段,所以時間複雜度爲O(nlogn) 。
算法
能夠看出,快排實現也是先對數據進行一遍遍歷找到關鍵值得位置,和數組不一樣的是數組能夠從兩端向中間靠攏,可是單向鏈表只能從一段開始,但用兩個指針一樣能夠實現。
數組
以[4,2,5,3,7,9,0,1]爲例模擬一趟快排的過程:ui
一、初始化時,i指向鏈表首元素4;j = i +1,指向2。基準數字爲當前i 指向的數字:4。指針
j | |||||||
---|---|---|---|---|---|---|---|
4 | 2 | 5 | 3 | 7 | 9 | 0 | 1 |
i |
二、隨後開始循環,j 當前指向2,由於2小於4,因此要把2移動到前面去。code
按照算法步驟操做:blog
執行一次交換後的結果以下:排序
j | |||||||
---|---|---|---|---|---|---|---|
4 | 2 | 5 | 3 | 7 | 9 | 0 | 1 |
i |
三、接下來,因爲 j 指向的值5 大於4,直接跳過,執行j++,此時 j 指向3;遞歸
j | |||||||
---|---|---|---|---|---|---|---|
4 | 2 | 5 | 3 | 7 | 9 | 0 | 1 |
i |
四、 j 指向的值爲3,小於4,仿照步驟2,咱們再次執行一次交換移動過程。it
交換後的結果以下:
j | |||||||
---|---|---|---|---|---|---|---|
4 | 2 | 3 | 5 | 7 | 9 | 0 | 1 |
i |
五、j指向的值爲7,大於4,因此直接跳過,執行 j++,j 指向9:
j | |||||||
---|---|---|---|---|---|---|---|
4 | 2 | 3 | 5 | 7 | 9 | 0 | 1 |
i |
六、同理,j 指向的值爲9,也大於4,跳過,執行 j++,j 指向0:
j | |||||||
---|---|---|---|---|---|---|---|
4 | 2 | 3 | 5 | 7 | 9 | 0 | 1 |
i |
七、j 指向的值爲0,小於4,執行一次交換過程:
交換後的結果以下:
j | |||||||
---|---|---|---|---|---|---|---|
4 | 2 | 3 | 0 | 7 | 9 | 5 | 1 |
i |
八、j 指向的值爲1,小於4,咱們再執行一次交換過程
交換後的結果以下:
j | ||||||||
---|---|---|---|---|---|---|---|---|
4 | 2 | 3 | 0 | 1 | 9 | 5 | 7 | |
i |
九、最後,交換當前 i指向的值1,和4。獲得[一、二、三、0、四、九、五、7],一趟排序結束。
j | ||||||||
---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 0 | 4 | 9 | 5 | 7 | |
i |
此時可見:4的左邊都是小於4的數字,右邊都是大於4的數字,一趟排序肯定了一個數字最終位置。
接下來,對左邊和右邊分別排序,遞歸,直到元素所有有序。
# Definition for singly-linked list. class ListNode(object): def __init__(self, val): self.val = val self.next = None class LinkList(object): # 單鏈錶快速排序 def quickSort(self, head): """ :type head: ListNode :rtype: ListNode """ if not head or not head.next: return head ans = ListNode(0) ans.next = head return self.sort(ans, None) def sort(self, head, end): if head == end or head.next == end or head.next.next == end: return head tpmHead = ListNode(0) # 劃分節點 poi = head.next # 遍歷指針 cur = poi pre = tpmHead # 一趟劃分 while cur.next != end: # 當前節點值域小於劃分節點的值域,則將當前節點放到左側 if cur.next.val < poi.val: pre.next = cur.next pre = pre.next cur.next = cur.next.next else: cur = cur.next # 合併臨時鏈表和原鏈表,將原鏈表接到臨時鏈表後面便可 pre.next = head.next head.next = tpmHead.next self.sort(head, poi) self.sort(poi, end) return head.next