python實現快速排序


快速排序可以把時間復雜度優化到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~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM