排序算法,整體來講就是選一個基準值,把小於基準值的分一撥,把大於基準值的分到另外一撥,而後遞歸。算法
有區別的是,分區算法有差別,最直接的是,選個基準值,定義兩個列表(小值分區less和大值分區great),而後挨個比較,小的追加到less,大的追加到greatapp
再有就是,選個基準值,先從右邊開始比,比基準值大的無論,比基準值小就和基準值換位置,換一次後,就去和左邊比,比基準值小的無論,比基準值大的又去換位置,略有些繞。less
最後,還能夠不遞歸,經過把分區節點保存在棧裏來實現。dom
1 # -*- coding: utf-8 -*- 2 3 import numpy as np 4 #1)依次對比arr[0]和其餘元素,比arr[0]小的話,就原地刪除,而後插入到arr[0]前面,基準值後移。大於等於,則不處理。而後遞歸 5 #原地排序 6 def quick_sort1(arr,left,right): 7 8 if left>=right: 9 return 10 flag=left 11 for i in range(left+1,right+1): 12 if arr[flag]>arr[i]: 13 temp=arr[i] 14 del arr[i] 15 arr.insert(flag,temp) 16 flag+=1 17 quick_sort1(arr,left,flag-1) 18 quick_sort1(arr,flag+1,right) 19 #2)基準值arr[0],對比全部元素,比它小就追加到less後面,比它大就追加到great後面,相等就追加到pivot後面,而後遞歸 20 #返回排序後的列表 21 def quick_sort2(arr): 22 less=[] 23 great=[] 24 pivot=[] 25 if len(arr)<=1: 26 return arr 27 else: 28 p=arr[0] 29 for i in arr: 30 if i<p: 31 less.append(i) 32 elif i>p: 33 great.append(i) 34 else: 35 pivot.append(i) 36 less=quick_sort2(less) 37 great=quick_sort2(great) 38 return less+pivot+great 39 #2-2)基本思想同上,代碼更簡化 40 def quick_sort22(arr): 41 if len(arr)<=1: 42 return arr 43 else: 44 return quick_sort22([i for i in arr[1:] if i<arr[0]])+[arr[0]]+quick_sort22([i for i in arr[1:] if i>=arr[0]]) 46 #2-3)思路同上,更簡化的版本 47 quick_sort23=lambda xs:((len(xs)<=1 and [xs]) or [quick_sort23([x for x in xs[1:] if x<xs[0]])+[xs[0]]+quick_sort23([x for x in xs[1:] if x>=xs[0]])])[0] 49 quick_sort24=lambda arr:arr if len(arr)<=1 else quick_sort24([x for x in arr[1:] if x<arr[0]])+[arr[0]]+quick_sort24([x for x in arr[1:] if x>=arr[0]])
#lambda 參數:取值1,若是知足條件1,不然,取值2 51 52 53 #3)定義兩個函數:分區和排序。分區是要把列表元素移動位置,直到基準值arr[0]移到中間(左邊都比它小,右邊都比它大)。排序則調用分區並遞歸 54 #原地排序 55 def partition(arr,i,j): 56 p=arr[i] 57 while i!=j: 58 while i<j and p<=arr[j]:#此處添加=,解決了以前遇到的序列中有重複值時死循環的問題 59 j-=1 60 arr[i]=arr[j] 61 while i<j and p>arr[i]: 62 i+=1 63 arr[j]=arr[i] 64 arr[i]=p 65 return i 66 def quick_sort3(arr,i,j): 67 if i<j: 68 mid=partition(arr,i,j) 69 quick_sort3(arr,i,mid-1) 70 quick_sort3(arr,mid+1,j) 71 #3-2)上述思路的變體,分區函數變更,每次都比右邊是否比基準值大,大的話,j前移,不然,把arr[j]給到arr[i],而後i後移,arr[i]再給到arr[j],繼續上述循環 72 def partition2(arr,i,j): 73 p=arr[i] 74 while i!=j: 75 while i<j and p<=arr[j]: 76 j-=1 77 78 while i<j and p>arr[j]: 79 arr[i]=arr[j] 80 i+=1 81 arr[j]=arr[i] 82 arr[i]=p 83 return i 84 def quick_sort32(arr,i,j): 85 if i<j: 86 mid=partition2(arr,i,j) 87 quick_sort32(arr,i,mid-1) 88 quick_sort32(arr,mid+1,j) 89 #3-3)分區函數變更,基準值爲最後一個值,依次比較,若是比基準值小,就換到前面去,最後再把基準值換到中間。 90 def partition3(arr,i,j): 91 p=arr[j] 92 x=i-1 93 for y in range(i,j): 94 if arr[y]<=p: 95 x+=1 96 arr[x],arr[y]=arr[y],arr[x] 97 arr[x+1],arr[j]=arr[j],arr[x+1] 98 return x+1 99 def quick_sort33(arr,i,j): 100 if i<j: 101 mid=partition3(arr,i,j) 102 quick_sort33(arr,i,mid-1) 103 quick_sort33(arr,mid+1,j) 104 #4)非遞歸方式,使用棧,思路相似previous,只是把切分邊界保存在棧(用list實現)裏,\ 105 #當只剩一個元素時,跳出本次循環,進入下次循環,看下一個區間裏元素值是否多於1個,直到棧空 106 def quick_sort4(arr,i,j): 107 if j<=i: 108 return 109 stack=[] 110 stack.extend([i,j]) 111 while stack: 112 left=stack.pop(0) 113 right=stack.pop(0) 114 if right<=left: 115 continue 116 x=left-1 117 p=arr[right] 118 for y in range(left,right):#此處循環不包括最後一個元素,循環結束後,最後一個元素換到中間 119 if arr[y]<=p: 120 x+=1 121 arr[x],arr[y]=arr[y],arr[x] 122 arr[x+1],arr[right]=arr[right],arr[x+1] 123 stack.extend([left,x,x+2,right]) 124 125 126 if __name__=="__main__": 127 s=np.random.randint(1,30,20).tolist() 128 print(s) 129 #print(quick_sort24(s)) 130 quick_sort4(s,0,len(s)-1) 131 print(s)