背景
本來想一口喫個大胖子。直接一篇文章搞定所有常見排序,發現水平不夠,篇幅超過控制。故而決定一篇一篇先單獨寫,之後再發排序算法的總和篇(社畜像現實低頭orz.)
選擇排序 (Selection Sort)
本文要講的排序算法是排序算法中最基本算法之一的選擇排序(Selection Sort) 。
什麼是選擇排序?
選擇排序的命名“選擇”已經很好的解釋了其算法的基本思想。試想學生時代體育課叫一堆小朋友從矮到高排序是怎麼做的?大家總是找到最高的那個或者最矮的那個讓TA到一邊去,接着在剩餘的小朋友裏面再挑出最高或最矮的,讓TA到一邊排好序的小朋友堆裏,如此往復,就能完成小朋友的排序了,那麼這個其實就是咱們的選擇排序了。
選擇排序,每一次在未排序的元素裏 “選擇” 出最大(或最小)的元素,讓其加到有序元素裏。每一次能夠令未排序元素 - 1 ,有序元素 + 1。N次之後就能完成所有元素的排序。
選擇排序的空間時間複雜度
時間複雜度: O(n²),一共n輪,每一輪需要遍歷剩餘所有的元素,所以複雜度爲n²。
空間複雜度: O(n),通常的實現是破壞性的in-memory實現,即在給定的原數組上做破壞性排序。
選擇排序的實現
原理講了,筆者在此貼出實現代碼供參考。樣例代碼和測試代碼在筆者github上demo倉庫裏能找到。
/**
* 選擇排序的實現類。
* @author toranekojp
*/
public final class SelectionAscendingSort extends AbstractAscendingSort {
@Override
protected void doSort(int[] nums) {
assert nums != null;
final int boundle = nums.length;
for (int i = 0; i < boundle; i++) {
int minNum = nums[i]; // 記錄本輪最小數字
int minIndex = i; // 記錄本輪最小數字的下標。
// 枚舉剩餘數組,找出最小數字。
for (int j = i + 1; j < boundle; j++) {
if (nums[j] < minNum) {
// 找到更小的替換就當前記錄的信息。
minNum = nums[j];
minIndex = j;
}
}
// 通過交換把最小的數字挪到本輪擱置位i。
swap(nums, i, minIndex);
// 繼續下一輪直到所有元素都被處理。
}
}
}
結語
選擇排序雖然簡單,但是確實我們通過程序實現排序的第一步,因爲這和現實的排序很接近。理解並實現此算法會增加你的編程基本功。但是需要注意的是在工作中基本不會用到此類排序算法。