python选择排序从大到小_经典排序算法和Python详解之(一)选择排序和二元选择排序...
本文源自微信公眾號【Python編程和深度學(xué)習(xí)】原文鏈接:經(jīng)典排序算法和Python詳解之(一)選擇排序和二元選擇排序,歡迎掃碼關(guān)注鴨!
掃它!掃它!掃它排序算法是《數(shù)據(jù)結(jié)構(gòu)與算法》中最基本的算法之一。排序就是對于一個列表,按照某關(guān)鍵字遞增或遞減的順序進行操作。
目錄
一、穩(wěn)定排序和不穩(wěn)定排序
二、內(nèi)部排序和外部排序
三、時間復(fù)雜度和空間復(fù)雜度
四、算法一:選擇排序
五、算法二:二元選擇排序法(選擇排序改進)
一、穩(wěn)定排序和不穩(wěn)定排序
穩(wěn)定排序:經(jīng)過某種排序后,如果兩個記錄序號同等,且兩者在原無序記錄中的先后秩序依然保持不變。如:冒泡排序,歸并排序、插入排序、計數(shù)排序。
不穩(wěn)定排序:經(jīng)過排序后,序號相等,前后秩序有變化。如:快速排序、選擇排序、希爾排序、堆排序。
下面簡單介紹一下穩(wěn)定排序和不穩(wěn)定排序的實際區(qū)別:如果一個列表是[2,1,3,5,6,2],對應(yīng)的序號為a0: 2, a1: 1, a2: 3, a3: 5, a4: 6, a5: 2 。穩(wěn)定排序的結(jié)果:[1,2,2,3,5,6],對應(yīng)的序號為:a1, a0, a5, a2, a3, a4。不穩(wěn)定排序的結(jié)果:[1,2,2,3,5,6],對應(yīng)的序號為:a1, a5, a0, a2, a3, a4。可以看出,經(jīng)過穩(wěn)定排序后相等的數(shù)排序后其前后順序是不變的,而不穩(wěn)定排序后其前后順序是變化的。
那又會有人問了,既然排序結(jié)果一樣為什么非要區(qū)分穩(wěn)定排序和不穩(wěn)定排序呢,其實仔細(xì)分析就會恍然大悟,排序結(jié)果表面看起來一樣,但其實是不一樣的,我們舉個例子:班級每月一次考試,某一次考完之后需要對學(xué)生的成績進行排名(為了簡單我們假設(shè)只有4名同學(xué)),A:70分,B:80分,C:80分,D:90分。此時排序的時候分?jǐn)?shù)排名為70分,80分,80分,90分。但同樣都是80分,到底B和C誰在前面,老師也很糾結(jié),這時比較公平的方法就是穩(wěn)定排序,如果分?jǐn)?shù)一樣,誰上次考試排名靠前那么這次也靠前,激勵大家每次都能考高分。也就是穩(wěn)定排序可以讓第一次排序的結(jié)果服務(wù)于第二次排序中數(shù)值相等的那些數(shù)。
二、內(nèi)部排序和外部排序
內(nèi)部排序:數(shù)據(jù)記錄在內(nèi)存中進行排序。外部排序:因排序的數(shù)據(jù)很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。
通常討論的排序方法都是內(nèi)排序,如:插入排序、希爾排序、選擇排序、冒泡排序、歸并排序、快速排序、堆排序、計數(shù)排序等。
三、時間復(fù)雜度和空間復(fù)雜度
影響排序算法性能的三個因素:時間復(fù)雜度:即時間性能,高效率的排序算法應(yīng)該是具有盡可能少的關(guān)鍵字比較次數(shù)和記錄的移動次數(shù) 空間復(fù)雜度:主要是執(zhí)行算法所需要的輔助空間,越少越好。算法復(fù)雜性:主要是指代碼的復(fù)雜性。
用一張圖概括:
其中n是數(shù)據(jù)規(guī)模,k是桶的個數(shù),In-place是占用常數(shù)內(nèi)存,不占用額外內(nèi)存,Out-place是占用額外內(nèi)存。首先定義交換任意兩項位置的函數(shù)swap:
def?swap(x,i,j):????'''
????交換x的i,j位置元素
????'''
????temp?=?x[i]
????x[i]?=?x[j]
????x[j]?=?temp
四、算法一:選擇排序
選擇排序(Selection ?sort)是一種簡單直觀的排序算法。它的工作原理是每一次從待排序的數(shù)據(jù)元素中選出最小(或最大)的一個元素,存放在序列的起始位置,然后,再從剩余未排序元素中繼續(xù)尋找最小(大)元素,然后放到已排序序列的末尾。以此類推,直到全部待排序的數(shù)據(jù)元素排完。選擇排序是不穩(wěn)定的排序方法。無論數(shù)據(jù)什么樣,時間復(fù)雜度都是O(n^2), 因此數(shù)據(jù)規(guī)模越小越好,好處就是不占用額外內(nèi)存。
Python代碼如下:
def?selectionSort(list):????for?i?in?range(len(list)?-?1):
????????#?記錄最小數(shù)的索引
????????minIndex?=?i
????????for?j?in?range(i?+?1,?len(list)):
????????????if?list[j]?????????????????minIndex?=?j
????????#?i?不是最小數(shù)時,將?i?和最小數(shù)進行交換
??????????????if?i?!=?minIndex:
????????????list[i],?list[minIndex]?=?list[minIndex],?list[i]
????return?list
例如待排序列表是[2,3,4,1,5]一共5個數(shù),我們實際分析一下以上代碼,對i進行從0到5-1 (0-1-2-3)的遍歷,對j進行從i+1到5 (…..4)的遍歷,來尋找列表的最小值。
1、當(dāng)i = 0,minindex = 0,當(dāng)j = i+1 = 1, list[1] = 3 > list[0] = 2, minindex不變。當(dāng)j = i+2 = 2, list[2] = 4 > list[0] = 2, minindex 不變。當(dāng)j = j+3 = 3, list[3] = 1 < list[0] = 2, minindex = 3。當(dāng)j = j+4 = 4, list[4] = 5 > list[3] = 1, minindex不變,最終minindex = 3。
此時i = 0 != minindex = 3, 交換兩項,list[0]和list[3],最后列表變?yōu)?#xff1a;[1,3,4,2,5],查找出的最小值放在起始 ?位置,再從剩余列表繼續(xù)查找最小值。
2、當(dāng)i = 1,minindex = 1,繼續(xù)遍歷j,簡單說,當(dāng)j = i+2 = 3, list[3] = 1 < list[1] = 3, minindex = 3。
此時i = 1 != minindex = 3, 交換兩項,list[1]和list[3], 最后列表變?yōu)?#xff1a;[1,2,4,3,5]。
3、當(dāng)i = 2, minindex = 2, 繼續(xù)遍歷j,簡單說,當(dāng)j = i+1 = 3, list[3] = 3 < list[2] = 4, minindex = 3。
此時i = 2 != minindex = 3, 交換兩項,list[2] 和list[3], 最后列表變?yōu)?#xff1a;[1,2,3,4,5]。
4、當(dāng)i = 3, minindex = 3, 繼續(xù)遍歷j,j只有等于4,list[4] = 5 大于list[3] = 4,minindex = 3還是初始值。
此時i = 3 == minindex = 3, 不用做交換,遍歷結(jié)束,最后列表排序結(jié)果為:[1,2,3,4,5]。
代碼里用到了兩個for循環(huán),因此時間復(fù)雜度為O(n^2)。
五、算法二:二元選擇排序法(選擇排序改進)
選擇排序法每輪只找最小值,效率較低,可以考慮每次同時尋找最小值和最大值,并且在某一輪如果最小值與最大值相同,說明剩下的數(shù)都相同,可以直接結(jié)束。此外,與選擇排序不同的是,需要考慮到如果第i輪里,恰好第i個數(shù)就是最大值時,先交換minindex和i之后,最大值的下標(biāo)變成了minindex,這時候應(yīng)該交換minindex和n-i-1,而不是maxindex和n-i-1
Python代碼:
def?selectionSort_1(x):???i?=?0
???while?i?<=?len(x)?//?2:###兩側(cè)一起向中心移動,因此為一半
???????minindex?=?i
???????maxindex?=?i
???????j?=?i?+?1
???????while?j????????????if?x[minindex]?>?x[j]:
???????????????minindex?=?j
???????????if?x[maxindex]????????????????maxindex?=?j
???????????j+=?1
???????if?x[minindex]?==?x[maxindex]:
???????????return?x?
???????if?minindex?!=?i:
???????????swap(x,i,minindex)
???????if?maxindex?!=?len(x)?-?1?-?i?:
???????????if?maxindex?!=?i:
???????????????swap(x,len(x)?-?1?-?i,maxindex)
???????????else:
???????????????swap(x,len(x)?-?1?-?i,?minindex)
???????i?+=?1?
???return?x
舉例待排序列表是[2,3,4,1,5,6]一共6個數(shù),我們實際分析一下以上代碼,因為要從兩側(cè)同時向中心查找,因此i只需要遍歷列表的一半。
1、當(dāng)i = 0, 此時i <= len(list)//2 = 3,minindex = 0,maxindex = 0, j = i+1 = 1, 判斷j = 1 < len(list) – i = 6-0=6, 判斷l(xiāng)ist[minindex=0] = 2 < list[j=1] = 3, minindex=0不變。判斷l(xiāng)ist[maxindex=0] = 2 < ?list[j=1]=3,maxindex = 1。
j + 1 = 2, 判斷j = 2 < len(list) – i = 6-0=6, 判斷l(xiāng)ist[minindex=0] = 2 < list[j=2] = 4, minindex=0不變。判斷l(xiāng)ist[maxindex=1] = 3 < ?list[j=2]=4, maxindex = 2。
j + 1 = 3, 判斷j = 3 < len(list) – i = 6-0=6, 判斷l(xiāng)ist[minindex=0] = 2 > list[j=3] = 1, minindex=j=3。判斷l(xiāng)ist[maxindex=2] = 4 > ?list[j=3]=1, maxindex = 2保持不變。
j + 1 = 4, 判斷j = 4 < len(list) – i = 6-0=6, 判斷l(xiāng)ist[minindex=3] = ?1< list[j=4] = 5, minindex=3保持不變。判斷l(xiāng)ist[maxindex=2] = 4 < ?list[j=4]=5, maxindex = j = 4。
j + 1 = 5, 判斷j = 5 < len(list) – i = 6-0=6, 判斷l(xiāng)ist[minindex=3] = ?1< list[j=5] = 6, minindex=3保持不變。判斷l(xiāng)ist[maxindex=4] = 5 < ?list[j=5]=6, maxindex = j = 5。
這樣就當(dāng)i=0時,同時找到一個最大值和一個最小值。判斷l(xiāng)ist[minindex = 3] = 1, list[maxindex= 5]=6, 兩者不相等。判斷minindex = 3 != i = 0, 交換list[i]和list[minindex],此時list = [1,3,4,2,5,6]。判斷maxindex = 5 == len(list) -1 – i = 5, i = i + 1 = 1。
2、當(dāng)i = 1, 判斷i <= len(list)//2 = 3,minindex = 1,maxindex = 1, j = i+1 = 2, 判斷j = 2 < len(list) – i = 6-1=5, 判斷l(xiāng)ist[minindex=1] = 3 < list[j=2] = 4, minindex=1不變。此時 list[maxindex=1] = 3 < ?list[j=2]=4, maxindex = j = 2。
j = j+1 = 3, 判斷j = 3 < len(list) – i = 6-1=5, 判斷l(xiāng)ist[minindex=1] = 3 > list[j=3] = 2, minindex=j=3。判斷l(xiāng)ist[maxindex=2] = 4 > ?list[j=3]=2, maxindex = 2保持不變。
j = j+1 = 4, 判斷j = 4 < len(list) – i = 6-1=5, 判斷l(xiāng)ist[minindex=3] = 2 < list[j=4] = 5, minindex=3保持不變。判斷l(xiāng)ist[maxindex=2] = 4 < ?list[j=4]=5, maxindex = j = 4。
這樣就當(dāng)i=1時,同時找到一個最大值和一個最小值。判斷l(xiāng)ist[minindex = 3] = 2, list[maxindex= 4]=5, 兩者不相等。判斷minindex = 3 != i = 1, 交換list[i]和list[minindex],此時list = [1,2,4,3,5,6]。判斷maxindex = 4 == len(list) -1 – i = 4, i = i + 1 = 2。
3、當(dāng)i = 2, 判斷i <= len(list)//2 = 3,minindex = 2,maxindex = 2, j = ?i+1 = 3, 判斷j = 3 < len(list) – i = 6-2=4, 判斷l(xiāng)ist[minindex=2] = 4 > list[j=3] = 3, minindex=j = 3。此時 list[maxindex=2] = 4 > list[j=3]=3, maxindex = 2保持不變。
j = j+1 = 4, 判斷j = 4 == len(list) – i = 6-2=4, 這樣就當(dāng)i=1時,同時找到一個最大值和一個最小值。判斷l(xiāng)ist[minindex = 3] = 3, list[maxindex= 2]=4, 兩者不相等。
判斷minindex = 3 != i = 2, 交換list[i=2]和list[minindex=3],此時list = [1,2,3,4,5,6]。判斷maxindex = 2 != len(list) -1 – 2 = 3, 判斷maxindex = 2 == i = 2, 交換list[len(list)-1-i=3]和list[minindex = 3],也就是沒交換。最終的排序結(jié)果是[1,2,3,4,5,6]。
總結(jié)
以上是生活随笔為你收集整理的python选择排序从大到小_经典排序算法和Python详解之(一)选择排序和二元选择排序...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux ping策略打开_linux
- 下一篇: python 在excel指定列添加数据