選擇排序詳解


選擇排序詳解


摘要:選擇排序算法是一種比較容易理解的排序算法,記得我在第一次學習C語言的時候,老師讓我們自己嘗試寫一個排序,我們很多人下意識寫出來的就是一種具有選擇排序思想的排序算法,只不過那種算法會花費一個額外的數組進行存儲,在學習了選擇排序算法之后,我知道了那個數組是沒有必要聲明的

1.選擇排序算法詳解

1.葯引子——我自己的排序方法

​ 選擇排序是一種非常基礎的排序算法,其排序關鍵在於:使用查找最大值/最小值的方法,查詢出數組中的最大/最小值,然后將這個最大/最小值放到數組的最后/最前邊,現在,我們用我剛學C語言時的那種選擇手段進行理解:

​ 首先我們得到一個數組之后:

​ 我們要創建一片和這個數組一樣大的數組區域,用於存儲已經排好序的新數組:

​ 現在,我們開始對數組進行最大值選取,數組中找最大值的方法想必大家都會,因此在這里不再贅述,總之我們在第一次會找到15,找到之后我們將15放在新數組的最后邊:

​ 如上圖所示,我們使用某種方式,反正就是在下次尋找最大值的時候,不再考慮15了,然后重復找最大值然后放在新數組中的這個過程,這樣將整個數組都標記完之后,我們就能對這個數組排序。然而,這個方法效率太低了,首先就是標記這個事情,就很難辦,當初我是使用了另外一個新數組來存儲已經被當成過最大值的數,每次在遍歷到一個原數組中的值后,都會現在這個標記數組中查一下,如果它不存在標記數組中,那么我再考慮它是否是最大值這件事,總之這種方法既浪費空間,又浪費時間,不知道人類早期有沒有用過我這種方法,我想如果早期的程序員們如果都是精英的話,那肯定連想到都不會想到我這種雙浪費的方法。然而我的這個基礎方法雖然簡單,但是已經體現出了選擇排序的思想了,那就是找最大/最小值,然后將它們放在屬於自己的合適位置。

2.命根子——選擇排序的精髓

​ 現在我們來正式開始講解選擇排序,選擇排序是一種簡單基礎好理解的排序方法,但我仍然要記錄一下。首先我們在上文中已經透露了選擇排序的思想,那么選擇排序是如何高效的完成這個排序行為的呢?首先我們需要理解的是:排序行為,本身可以理解為讓數字們移動到各自合適的位置的過程。這個思想將在歸並排序中有更加明顯的體現,既然排序行為是讓數字們各歸其位的過程,那我們如何知道哪個數字應該去哪個位置呢?也許人類能一眼看出,但是計算機卻沒有人類那么聰明,因此我們不得不使用更簡單的方式告訴計算機:一個數組中的數字,最大的一定在最后邊,最小的一定在最前邊,計算機秉持着這個指令,就可以在找到最大的數字之后將其放到最后邊或者將最小的數字放到最前邊,然后...然后呢?計算機可以找到一個數組中最大的或者最小的數字,但是它能找到次大或者次小的嗎?答案仍然是不可以,計算機沒有這么智能,因此我們還要告訴計算機一個指令,那就是在將當前數組的最大值放到最后邊或者將數組的最小值放到最前邊之后,你要縮小這個數組的規模,不再考慮最后一位或者最前一位,你要在這個縮小規模的新數組中重新重復剛才的行為。好了,這就是選擇排序

3.選擇排序圖解

​ 如圖所示,我們已經得到了一個數組,它是無序的,現在,我們開始尋找這個無序數組中的最小值(也可以尋找最大值,但是這里我們以尋找最小值為例。),首先,我們摘到了0,我們發現0是最小值,因此我們讓0和數組首位互換位置:

​ 之后,我們縮小數組的范圍,我們從數組的第二個位置開始算起,將原數組中以下標為1的元素為首元素的子數組作為新數組(藍色填充區域為新數組),然后我們在這個新數組中重復剛才的取最小值並交換的行為:

​ 現在,我們可以找到新數組中的最小值是1,因此我們將1和新數組的首元素位置進行互換,但是這里1所在的位置就是首元素位置,所以這里交換行為實際上沒什么意義,之后我們再次縮小數組規模並重復檢索行為:

​ 現在,我們經過檢索發現,2是當前新數組中的最小元素,因此我們將其和該數組的首元素進行位置互換:

​ 之后,我們繼續縮小數組規模,並重復檢索行為:

​ 我們經過檢索發現,當前數組中的最小元素為3,因此我們繼續將其和當前數組中的首元素進行位置互換:

​ 現在我們繼續縮小數組的規模,並繼續檢索:

​ 經過檢索我們發現,當前數組中的最小元素是4,它也恰好是首元素,因此這里交換行為沒什么意義,並繼續下一輪循環,縮小一次數組規模並繼續檢索:

​ 經過檢索我們發現,當前數組中的最小元素是7,它恰好也是首節點,因此這里的交換行為同樣沒什么意義,在經過沒有意義但是必須執行的交換之后,我們開始下一輪循環,縮小數組規模並重新開始檢索:

​ 在當前新數組中,我們發現最小的元素是9,我們將其哈數組的首元素進行互換:

​ 之后我們繼續縮小數組規模並重新進行檢索:

​ 然而此時我們發現,新數組中只剩下一個元素,我們已經將整個數組遍歷完一遍了,因此此時整個程序就宣告結束,而這個數組,實際上也排好序了。

​ 這就是選擇排序。

4.總結

​ 因此我們可以看到選擇排序的原理實際上就是不斷的尋找當前數組中的最小元素/最大元素,然后將他們放到最前邊/最后邊的位置上去,這個位置的放置是通過交換來實現的,因為它們被放置在最前/后邊的位置上以后,數組就要從最前邊/后邊縮小一個單位,也就是不再考慮已經被排好序,放在正確位置上的那個元素了,而是要考慮剩下的元素們,通過交換,我們可以將之前數組中的最小/最大元素放到相應位置去,並把之前那個位置上的元素轉移到即將要被重復這個行為的新數組中來,通過這種方法我們可以巧妙方便的在原數組上構建新數組,而不需要額外的數組空間進行結果數組的保存,也無需使用其他數組來標志哪個元素已經被排過序了這一事件,這就是選擇排序的巧妙之處。

2.選擇排序的代碼詳解

​ 接下來我們來看看選擇排序算法的代碼,並對代碼進行詳細的分析:

public static void searchSort(int[] arr){
        for (int i = 0; i<arr.length - 1; i++){//①
            int minIndex = i;
            int min = arr[i];//②
            for (int j = i + 1; j<arr.length; j++){//③
                if(min>arr[j]){
                    min = arr[j];
                    minIndex = j;
                }
            }
            arr[minIndex] = arr[i];
            arr[i] = min;//④
        }
        System.out.println(Arrays.toString(arr));
    }

​ ①.我們定義一個循環,這個循環就是用來進行上述的每輪排序行為的,在這個循環中,每輪循環都會找到當前數組中的最小值,並讓這個最小值和當前數組的首元素進行位置互換。與此同時,循環頭中的變量i在這里也有有着豐富的含義,它不僅代表循環的次數,它也代表着每次輪循環中數組的首元素位置,當數組中的首元素位置就是原最大的那個數組中最后一個元素的位置時,就說明排序已經到頭,算法可以結束了。

​ ②.我們定義最小值的下標變量,同時定義最小值。這里主要是找最值的方法,找最值的方法一般都是默認數組首節點是最值點,然后對數組進行遍歷,在遍歷過程中會依次查看整個數組中的所有元素並和最值進行對比,如果發現了比最值小的元素,那么就讓當前的數組元素替換掉之前的最值元素成為新的最值元素,如這里使用minIndex保存最值下標,使用min保存最值,當找到數組中新的最值時,新的最值下標就會替換掉minIndex中原來的值,而新的最值也會替換掉min中原來的值。

​ ③.這個循環就是找最值的循環體,具體解釋看上文中②的解釋。

​ ④.這里的兩句代碼就是將找到的最值與數組首元素的值進行對換的行為。之后將開啟新的一輪循環,新數組將從i開始,而i這時加了1,這就代表着新數組往后“縮”了一格,規模變小了一些。重復進行外循環,直到外循環終止,這個數組最終會被排好序。

​ 以上就是選擇排序法,要多加練習,才能快速的寫出它。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM