选择排序就这么简单
選擇排序就這么簡單
從上一篇已經講解了冒泡排序了,本章主要講解的是選擇排序,希望大家看完能夠理解并手寫出選擇排序的代碼,然后就通過面試了!如果我寫得有錯誤的地方也請大家在評論下指出。
選擇排序介紹和穩定性說明
來源百度百科:
選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始(末尾)位置,直到全部待排序的數據元素排完。選擇排序是不穩定的排序方法(比如序列[5, 5, 3]第一次就將第一個[5]與[3]交換,導致第一個5挪動到第二個5后面)。
上面提到了選擇排序是不穩定的排序方法,那我們的冒泡排序是不是穩定的排序方法呢?穩定的意思指的是什么呢?
判斷某排序算法是否穩定,我們可以簡單理解成:排序前2個相等的數其在序列的前后位置順序和排序后它們兩個的前后位置順序相同
- 如果相同,則是穩定的排序方法。
- 如果不相同,則是不穩定的排序方法
如果排序前的數組是[3,3,1],假定我們使用選擇排序的話,那第一趟排序后結果就是[1,3,3]。這個數組有兩個相同的值,它倆在array[0]和array[1],結果經過排序,array[0]的跑到了array[2]上了。
那么這就導致:2個相等的數其在序列的前后位置順序和排序后它們兩個的前后位置順序不相同,因此,我們就說它是不穩定的
再回到上面的問題,上一篇說講的冒泡排序是穩定的,主要原因是:倆倆比較的時候,沒有對相等的數據進行交換(因為沒必要)。因此它不存在2個相等的數其在序列的前后位置順序和排序后它們兩個的前后位置順序不相同。
那么穩定排序的好處是什么?
- 參考知乎回答@獨行俠的回答:
如果我們只對一串數字排序,那么穩定與否確實不重要,因為一串數字的屬性是單一的,就是數字值的大小。但是排序的元素往往不只有一個屬性,例如我們對一群人按年齡排序,但是人除了年齡屬性還有身高體重屬性,在年齡相同時如果不想破壞原先身高體重的次序,就必須用穩定排序算法.
很清晰的指出,只有當在“二次”排序時不想破壞原先次序,穩定性才有意義
參考資料:
- www.zhihu.com/question/46…
- tieba.baidu.com/p/872860935
- www.cnblogs.com/codingmylif…
一、第一趟排序
它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始(末尾)位置,直到全部待排序的數據元素排完
首先,我們創建數組,找到它最大的值(這就很簡單了):
int[] arrays = {2, 3, 1, 4, 3, 5, 1, 6, 1, 2, 3, 7, 2, 3};//假定max是最大的int max = 0;for (int i = 0; i < arrays.length; i++) {if (arrays[i] > max) {max = arrays[i];}}復制代碼隨后這個最大的數和數組末尾的數進行交換:
//使用臨時變量,讓兩個數互換int temp;temp = arrays[11];arrays[11] = arrays[13];arrays[13] = temp;復制代碼那么經過第一趟排序,我們的最大值已經到了數組的末尾了。
二、第二趟排序
再次從數組獲取最大的數(除了已經排好的那個):
int max2 = 0;for (int i = 0; i < (arrays.length - 1); i++) {if (arrays[i] > max2) {max2 = arrays[i];}}System.out.println(max2);復制代碼再將獲取到的最大值與數組倒數第二位交換:
temp = arrays[7];arrays[7] = arrays[12];arrays[12] = temp;復制代碼經過第二次排序,已經能夠將數組最大兩個數進行排序了
三、代碼簡化
從前兩趟排序其實我們就可以摸出規律了:
- 一個數組是需要n-1趟排序的(因為直到剩下一個元素時,才不需要找最大值)
- 每交換1次,再次找最大值時就將范圍縮小1
- 查詢當前趟數最大值實際上不用知道最大值是多少(上面我查出最大值,還要我手動數它的角標),知道它的數組角標即可,交換也是根據角標來進行交換
第一趟:遍歷數組14個數,獲取最大值,將最大值放到數組的末尾[13] 第二趟:遍歷數組13個數,獲取最大值,將最大值放到數組倒數第二位[12]
....
數組有14個數,需要13趟排序。
//記錄當前趟數的最大值的角標int pos ;//交換的變量int temp;//外層循環控制需要排序的趟數for (int i = 0; i < arrays.length - 1; i++) {//新的趟數、將角標重新賦值為0pos = 0;//內層循環控制遍歷數組的個數并得到最大數的角標for (int j = 0; j < arrays.length - i; j++) {if (arrays[j] > arrays[pos]) {pos = j;}}//交換temp = arrays[pos];arrays[pos] = arrays[arrays.length - 1 - i];arrays[arrays.length - 1 - i] = temp;}System.out.println("公眾號Java3y" + arrays); 復制代碼四、選擇排序優化
博主暫未想到比較好的優化方法,如果看到這篇文章的同學知道有更好的優化方法或者代碼能夠寫得更好的地方,歡迎在評論下留言哦!
查到的這篇選擇排序優化方法,感覺就把選擇排序變了個味,大家也可以去看看:
- 他是同時獲取最大值和最小值,然后分別插入數組的首部和尾部(這跟選擇排序的原理好像差了點,我也不知道算不算)
- www.cnblogs.com/TangMoon/p/…
五、擴展閱讀
C語言實現
int findMaxPos ( int arr[], int n){int max = arr[0];int pos = 0; for (int i = 1; i < n; i++) {if (arr[i] > max) {max = arr[i];pos = i;}}return pos;}void selectionSort ( int arr[], int n){while (n > 1) {int pos = findMaxPos(arr, n);int temp = arr[pos];arr[pos] = arr[n - 1];arr[n - 1] = temp;n--;//}}int main (){int arr[] = {5, 32, 7, 89, 2, 3, 4, 8, 9};selectionSort(arr, 9);for (int i = 0; i < 9; i++)cout << arr[i] << endl;}復制代碼如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
- 上一篇: 【数据结构】B-Tree, B+Tree
- 下一篇: linux日常笔记3