快速排序可以把時間復雜度優化到nlog2n,省心多了。。。
來八卦一下快速排序
1. 快速排序就是選定一個標志位,我們把它叫做flag,期望把小於flag的放在它的左邊,把大於flag的放在它的右邊,這樣就以flag的分界,把原來的list分為了兩個子list : list1 和 list2。
2. 按照上述方法,在list1 和 list2中再分別選flag,將list2 和 list2 分別拆成兩個list,依次類推
3. 直到n = 1,即每個子list都只有一個元素 整個過程 : n/2x = 1 x = log2n
那么如何實現step1呢,既然有的元素比flag大,有的元素比flag小,那么我們定義兩個游標,一個指向大於flag的元素,一個指向小於flag的元素,選定list中的最后一個元素作為flag
list = [5,1,3,8,9,4,7,6]
(整個過程,可以在紙上先寫一寫,分析一下就很清楚了)
在上面的列表中,選擇list[-1] = 6作為flag位,定義游標 i 和游標 j ,i指向大於flag的元素,j指向小於flag的元素。
Step1 :將 i 初始化到-1 位置,將 j 初始化到 0 位置
Q:為什么將 i 初始化到-1位置,即指向列表前面一個空的位置?
A:等下解釋。。。
Step2:j :0——>len(list)-1
比較list[j]和flag,在例子中,現在j=0,list[0] < flag,這時候 i= i+1, exchange list[i] 和 list[j]的值
Q:現在 i 和 j 指向的都是0的位置,為什么自己要和自己交換呢?
A:可以在代碼中看到,這樣做其實是為了保持程序的一致性,當然你也可以自己判斷,如果i 和 j 指向的都是同一個位置,那沒必要交換
Step3:j++,到了j=(index)3的時候,這時候 i 還是指向(index)2的,發現,list[j=3] = 8 是大於flag的,那么,i 原地不動 ,即現在i 還是指向index=2的位置,i 不往前走了。
Step4:當 j 走到5的時候,list[5] = 4,它小於flag ,而它前面的8 和 9 都比flag大,那么,也肯定比list[5] = 4要大了,好,i+1,即 i 現在指向(index)3,即value=8,exchange list[i] 和 list[j],然后j 繼續向前走。
總之,j 先走,只要碰到小於flag的數,i 就+1,只要碰到大於flag的數,i 就原地不動,j 繼續向前走,目前就是把后面小的數給挪到前面來。
現在,來解釋一下為什么將i 初始化到 -1 的位置呢?
很簡單,當第一個位置的元素大於flag時,i 指向0,原地不動,而j 繼續向前走,當遇到下面一個比flag小的元素時,i+1,那么,你就永遠處理不到第一個元素了,嗯,就是這個原因,可以自己在紙上寫一下,一下子就看出來了。
上面的過程可以用下面的代碼實現;
1 if __name__ == '__main__': 2 l = [5,1,3,8,9,4,7,6] 3 4 def first_sort(l): 5 flag = l[-1] 6 i = -1 7 for j in range(len(l)-1): 8 if l[j] > flag: 9 pass 10 else: 11 i += 1 12 tmp = l[i] 13 l[i] = l[j] 14 l[j] = tmp 15 print(l) 16 print("\n" + "*"*20 + "\n") 17 18 tmp = l[-1] 19 l[-1] = l[i+1] 20 l[i+1] = tmp 21 22 print(l) 23 print("\n" + "*"*20 + "\n") 24 25 first_sort(l)
運行后的結果為:
[5, 1, 3, 4, 9, 8, 7, 6] ******************** [5, 1, 3, 4, 6, 8, 7, 9] ********************
從第一個打印出的list來看,小於flag的和大於flag的已經分開了
將list[-1] 和 list[i+1] 交換,那么第一次快排就完成了,(運行結果的第二條)
清楚了這個過程以后,接下來就是遞歸的事兒了,呃,不想寫了,好累。。。直接貼代碼。
1 def path_sort(list,start_index,end_index): 2 flag = list[end_index] 3 i = start_index - 1 4 for j in range(start_index,end_index): 5 if list[j] > flag: 6 pass 7 else: 8 i += 1 9 tmp = list[i] 10 list[i] = list[j] 11 list[j] = tmp 12 tmp = l[end_index] 13 l[end_index] = l[i+1] 14 l[i+1] = tmp 15 16 return i+1 17 18 def Quick_sort(list,start_index,end_index): 19 if start_index >= end_index: 20 return 21 middle = path_sort(list,start_index,end_index) 22 Quick_sort(list,start_index,middle-1) 23 Quick_sort(list,middle+1,end_index) 24 print(l) 25 26 Quick_sort(l,0,len(l)-1)
ps,其實不難的,只要你肯認真思考。O(∩_∩)O~