文章目錄
選擇排序(selection sort)是一種簡單直觀的排序演算法。它的工作原理是:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置(公升序或者降序),然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。選擇排序的主要優點與資料移動有關。如果某個元素位於正確的最終位置上,則它不會被移動。選擇排序每次交換一對元素,它們當中至少有乙個將被移到其最終位置上,因此對n
個元素的表進行排序總共進行至多n-1
次交換,所以它的時間複雜度是n(n-1)
,不包括這個函式的低階項和首項係數後用大o表示法為:o(n^2)
。在所有的完全依靠交換去移動元素的排序方法中,選擇排序屬於非常好的一種。
現有序列[1, 9, 8, 5, 6, 7, 4, 3, 2],請使用選擇排序對該列表進行排序。
nums =[1
,9,8
,5,6
,7,4
,3,2
]length =
len(nums)
for i in
range
(length-1)
: max_index=i
for j in
range
(i+1
,length)
:if nums[max_index]
< nums[j]
: max_index = j
if i != j:
nums[max_index]
, nums[i]
= nums[i]
, nums[max_index]
print
(nums)
上面的**,僅僅是針對題中的列表進行的定製化
選擇排序,真正的要適用各種型別的數字序列,還需要進行進一步優化。
每一次迴圈找到乙個最大值或最小值,存放在排序序列的起始位中去,我們知道,每次在未排序區查詢時,都會進行遍歷,那麼必然會發現最大值,同時也會發現最小值,那麼我們是否可以同時對最大值和最小值進行排序呢?
由於一次迴圈要同時判斷最大值和最小值,由於迴圈是從左邊開始的,所以最大值的初始位置和i的取值是相同的,但最小值的初始值是從末尾開始,逐漸向右的,所以這裡啟用乙個變數記錄最小值的位置便於交換。
nums =[1
,9,8
,5,6
,7,4
,3,2
]#正索引 0 1 2 3 4 5 6 7 8
#負索引-9 -8 -7 -6 -5 -4 -3 -2 -1
length =
len(nums)
for i in
range
(length -1)
: max_index = i
min_index =
-i -
1 source_min = min_index # 1
for j in
range
(i+1
, length)
:if nums[max_index]
< nums[j]
: max_index = j
if nums[min_index]
> nums[
-j -1]
: min_index =
-j -
1if max_index != i:
nums[max_index]
, nums[i]
= nums[i]
, nums[max_index]
if min_index != source_min:
nums[min_index]
, nums[source_min]
= nums[source_min]
, nums[min_index]
print
(nums)
上面雖然已經完成了二元選擇排序,但是結果卻不是正確的,為什麼呢?想一下:如果最小值所在的位置剛好是最大值要交換的位置時,如果直接交換最大值,那麼最小值的索引就會變為原最大值的索引。針對這種情況在交換最大值時判斷一下最大值要交換的位置是否等於最小值所在的位置,如果是,那麼需要在最大值修改完畢後,將最小值的索引進行重置(重置為最大值所在的索引)
nums =[1
,9,8
,5,6
,7,4
,3,2
]#正索引 0 1 2 3 4 5 6 7 8
#負索引-9 -8 -7 -6 -5 -4 -3 -2 -1
length =
len(nums)
for i in
range
(length -1)
: max_index = i
min_index =
-i -
1 source_min = min_index
for j in
range
(i+1
, length)
:if nums[max_index]
< nums[j]
: max_index = j
if nums[min_index]
> nums[
-j -1]
: min_index =
-j -
1if max_index != i:
nums[max_index]
, nums[i]
= nums[i]
, nums[max_index]
if(length + min_index)
== i:
min_index = max_index
if min_index != source_min:
nums[min_index]
, nums[source_min]
= nums[source_min]
, nums[min_index]
print
(nums)
思考點1:既然我們一趟可以確定兩個元素(1個最大值,1個最小值),那我們還需要length-1次迴圈嗎? 如果元素為7個,只需要判斷3次即可,如果元素是8個,只需要判斷4次即可,根據以上條件得知,只需要迴圈length//2次就可以完成排序了。
思考點2:在一次迴圈的結果中最大值或最小值和要排的位置的值是相同時,就不需要進行修改了。
思考點3:如果在一次迴圈中最大值索引和最小值索引對應的元素相同,比如[4,2,1,1,1,1,3] 這種情況下,[1,1,1,1] 就不需要排序了。
nums =[1
,9,8
,5,6
,7,4
,3,2
]# nums = [4, 3, 1, 1, 2, 1, 1, 5, 6, 2]
# 正索引 0 1 2 3 4 5 6 7 8
# 負索引-9 -8 -7 -6 -5 -4 -3 -2 -1
count =
0swap =
0length =
len(nums)
for i in
range
(length -1)
:# 優化迴圈次數
max_index = i
min_index =
-i -
1 source_min = min_index # 1
for j in
range
(i +
1, length)
: count +=
1if nums[max_index]
< nums[j]
: max_index = j
if nums[min_index]
> nums[
-j -1]
: min_index =
-j -
1if nums[max_index]
== nums[min_index]
:# 最大最小值相同,則排序完畢
break
if max_index != i:
nums[max_index]
, nums[i]
= nums[i]
, nums[max_index]
swap +=1if
(length + min_index)
== i:
min_index = max_index
if min_index != source_min and nums[min_index]
!= nums[source_min]
:# 如果值相同,就不需要交換了
swap +=
1 nums[min_index]
, nums[source_min]
= nums[source_min]
, nums[min_index]
print
(count,swap)
print
(nums)
排序 2 選擇排序
工具方法類 package mydatastructrueadndalgorith.three.arrsort 陣列為模板排序演算法中的一些公用的模板方法 建立人 曹雪坤 version 1.0.0 public class example 遍歷陣列 public static void show ...
排序 選擇排序(2)
選擇排序 selection sort 是一種簡單直觀的排序演算法。它的工作原理是每一次從待排序的資料元素中選出最小 或最大 的乙個元素,存放在序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小 大 元素,然後放到已排序序列的末尾。以此類推,直到全部待排序的資料元素排完。選擇排序是不穩定的排序方...
排序2 選擇排序 選擇排序 堆排序
選擇排序,依次找到資料集n n 1 n 2 中比它大 小的最大 最小者,最終達到全部資料有序。1 選擇排序 直接的依次找到資料集合n n 1 n 2.的最大 最小者形成排序,非常好理解。選擇排序可能是和氣泡排序一樣,最直觀能想到的排序方法。顯然選擇排序和氣泡排序一樣,無所謂最好 最壞 平均,選擇排序...