選擇排序 每一趟從待排序的元素中,選出最小的元素,放到已經排好序的序列的后面直到全部元素排序完畢。在這個過程中,有序區逐步擴大,而無序區逐漸縮小。
直接選擇排序
直接選擇排序是將無序區內的最小元素追加到有序區的后面,從而擴大有序區的范圍。而我們又是在原地排序,所有也就相當與交換無序區的第一個元素和無序區最小元素的位置。
我們需要一個游標來追蹤無序區的最小元素。 假設為 K ,
我們又同時假設每一趟排序前,無序區的第一個元素就是當前無序區的最小元素。 也就是說 k 在每一次排序開始時,都是指向無序區的第一個元素。
假設有這樣一個序列,最初整個序列都是無序的。k = 0; k指向6,我們假設6 是無序區里面最小的。(但這顯然是不可能的)
我們遍歷無序區所有元素,得到真正的最小元素的索引,賦值給k 然后將真正的最小元素和 無序區的第一個元素進行交換
如圖我們已經找到了無序區最小元素並完成了交換,同時有序區長度變為了1
然后我們繼續我們的排序工作。此時k=1,k指向2,我們假設 2 就是整個無序區的最小元素
我們遍歷所有的無序區元素,發現,2還真是最小的元素。直接擴大有序區的范圍即可,不需要交換
繼續排序,k=2,k指向4,依舊遍歷所有無序區的元素,發現3才是真正最小的,於是將3 和4交換,有序區范圍再一次擴大
繼續,k=3,指向6,遍歷所有的無序區元素,發現4才是最小的,交換6 和4
繼續 k = 4,指向5 ,遍歷所有無序區的元素,發現5確實是最小的,擴大有序區的范圍
k=5,指向6,發現6就是最大的了
有序區擴大到整個序列,排序完成。
代碼如下:
def select_sort(A,n): for i in range(n): # 無序區的范圍是 [0,n-1] k = i #確定每次循環 k 的初始值。仔細研究一下上圖會發現 每次循環 的 i 和 k 的值相等,都是當前無序區的第一個元素的索引 for j in range(i+1,n): # 已經假設 k 指向的就是最小元素,但實際可能並不是,因此從無序區的第二個元素開始遍歷所有剩余的元素,(也可以從i 開始,也就是說,從無序區的第一個元素開始,但是 k 本身就是無序區的第一個元素,它永遠不可能比他自己小,所以無序區的第二個元素開始查找比較好) if A[k]>A[j]: #如果正在遍歷的元素小於 k 指向的元素 k = j #那么就移動 k ,知道所有的剩余元素都遍歷完,這時候才能確定真正的 k 的位置。 if k != i: # 這里判斷 k 是否等與 i 的作用是為了減少操作量,就像 上圖里面k=1的時候,發現它確實就是最小的,因此就沒必要進行下面的操作。 A[k],A[i]=A[i],A[k] # 經過上面的查找已經找到了無序區真正的最小元素的索引,交換無序區最小元素和第一個元素。 return A A=[6,2,4,1,5,3] n =len(A) print(select_sort(A,n))