上篇咱們好好聊了聊冒泡排序,這篇咱們來聊聊另外一種初級排序算法——選擇排序java
選擇排序的算法思路一樣很簡單。仍是數組爲例,咱們如今有個整數數組,要求將其中整數元素按值的大小從小到大排個序。選擇排序的具體思路是這樣:先從頭遍歷數組,找出其中值最小的那個元素,而後將其值同遍歷區間最開始那個元素交換,若是值最小的元素恰是最開始那個元素,就本身跟本身交換值。第一遍遍歷完成,數組中最小的值已是數組第一個元素,此時數組第一個元素已部分有序,將從新遍歷的初始下標加一,開始下次遍歷,如此循環,直至遍歷區間內只剩一個元素,此時數組已總體有序。算法
來具象化捋一遍選擇排序的邏輯:數組
``函數
設現有無序數組 a = [40, 50, 20, 30, 10]
其有序狀態應爲 a = [10, 20, 30, 40, 50]
咱們對其作下選擇排序,具象展現以下:
數組下標:a[0] a[1] a[2] a[3] a[4]
初始值: 40 50 20 30 10
第一次選擇遍歷過程: 40 50 20 30 10 (遍歷區間值最小元素爲a[4],
↑ ↑ 與遍歷區間初始下標a[0]交換值)
第二次選擇遍歷過程: 10 50 20 30 40 (最小元素爲a[2],與a[1]交換值,
--- ↑ ↑ 下劃線標示的元素已部分有序)
第三次選擇遍歷過程: 10 20 50 30 40 (最小元素爲a[3],與a[2]交換值,
-------- ↑ ↑ 下劃線標示的元素已部分有序)
第四次選擇遍歷過程: 10 20 30 50 40 (最小元素爲a[4],與a[3]交換值,
------------ ↑ ↑ 下劃線標示的元素已部分有序)
第五次選擇遍歷過程: 10 20 30 40 50 (遍歷區間內只剩一個元素了,
------------------ ↑↑ 代表此時數組已總體有序)
數組此時已總體有序: 10 20 30 40 50 (數組此時已總體有序)
-----------------------
複製代碼
OK 邏輯捋的差很少了咱們開始擼代碼,以 Java 爲例,咱們先來擼個爲整數數組選擇排序的遞歸實現版本:post
/** * @see: 選擇排序的遞歸實現 * @param array: 待排序數組,咱們採用原地排序 * @param start: 當次查找最小值(遍歷區間)的初始下標,初次調用值應爲0 */
public static void sortSelect(int[] array, int start){
//遞歸結束條件,此時數組已總體有序
if (start >= array.length - 1){
return;
}
//先假定遍歷區間第一個下標的值爲最小值;
int minValueIndex = start;
//開始遍歷特定數組區間,將區間內最小值交換到區間初始位置
for (int i = start + 1; i <= array.length - 1; i ++){
if (array[i] < array[minValueIndex]){
minValueIndex = i;
}
}
//把最小的值交換到遍歷區間初始下標位置
int mid = array[start];
array[start] = array[minValueIndex];
array[minValueIndex] = mid;
//遞歸開始遍歷下個遍歷區間
sortSelect(array, start + 1);
}
複製代碼
咱們在實際生產環境中寫排序算法確定不能用遞歸,在 Java 中遞歸的函數調用棧太深會致開銷甚大,上面主要是爲便於理解來的初級版本,咱們來優化成非遞歸版本,即雙層嵌套版本:優化
/** * @see: 選擇排序的非遞歸實現,即雙層嵌套實現 * @param array: 待排序數組,咱們採用原地排序 */
public static void sortSelect(int[] array){
//遞歸結束條件,此時數組已總體有序
for (int start = 0; start < array.length - 1; start ++){
//先假定遍歷區間第一個下標的值爲最小值;
int minValueIndex = start;
for (int startInner = start + 1; startInner <= array.length - 1; startInner ++ ){
if (array[startInner] < array[minValueIndex]){
minValueIndex = startInner;
}
}
//把最小的值交換到遍歷區間初始下標位置
int mid = array[start];
array[start] = array[minValueIndex];
array[minValueIndex] = mid;
//循環開始遍歷下個遍歷區間
}
}
複製代碼
兩種實現代碼擼下來,相信你已完全掌握了選擇排序算法。spa
選擇排序有兩個特色:code
選擇排序須要的額外空間複雜度同冒泡排序,爲О(1)排序
讀者請自行發散思惟把以上代碼改爲爲 Comparable 數組排序的版本。遞歸
下篇咱們聊插入排序。
完。