寫在Selection Sort之前:
我們先來學習O(n2)時間復雜度的排序算法,對于排序算法,最優的是O(nlogn)時間復雜度的排序算法,那么我們為什么學習O(n2)的排序算法呢?
重視學習O(n^2)的排序算法原因:
- 相對基礎
(很多時候,在遇到一個問題時,我們都要先嘗試用簡單的方法嘗試解決,這個過程可以加深我們對問題本身的理解 進而提出更加復雜的方法或者來優化我們原來設想的簡單解法,啟發:要是對于一些面試問題一時沒有思路,不妨先嘗試簡單的方法,雖然這個簡單的方法有問題,但是我們先擺出來,擺的過程中可能就會想到優化的方法,同時也可讓面試官看到我們思考問題的過程) - 編碼簡單,易于實現,是一些簡單情景的首選
(有些情況下我們使用的不是高級程序設計語言,在底層我們可能使用匯編,這種情況下O(n^2)的排序算法便于實現就成為了首選) - 在一些特殊情況下,簡單的排序算法更有效
- 簡單的排序算法思想可以衍生出復雜的排序算法
(比如希爾排序是在插入排序下進行了一次優化實現) - 可作為子過程,改進更復雜的排序算法
注意:以上有不理解,不要太在意,相信通過后續學習的深入可對其有更深的理解
我們首先來學習選擇排序(Selection Sort)
Selection Sort 思路:
對于給定的數組:
1.png
首先我們在整個數組中找到第一名的位置(假設我們從小到大排),然后在數組中找到最小的數:
2.png
然后將1和現在的第一名的位置上的數(8)進行交換:
3.png
經過這樣的一次交換,1所處的位置就是其最終的位置了:(以后就不用管1了,省心的孩子....)
4.png
之后,我們在剩下的位置(即除去1的6到4)找到此時最小的數:2,把2和相應的第2個位置上的元素(6)進行交換:
5.png
此時1和2的順序已好:
6.png
此過程依此類推,繼續在剩下的部分(6到4)找最小的數:
7.png
8.png
9.png
再看第4個:
10.png
11.png
下面5:
12.png
13.png
6:
14.png
15.png
7:
16.png
7不用動:(可以理解自己和自己進行了一次交換,結果是沒有動)
17.png
對于8:(和7情況一樣)
18.png
C++代碼:
#include <iostream>
#include <algorithm>
using namespace std;
void selectionSort(int arr[], int n){
for(int i = 0 ; i < n ; i ++){
// 尋找[i, n)區間里的最小值
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
int main() {
int a[10] = {10,9,8,7,6,5,4,3,2,1};
selectionSort(a,10);
for( int i = 0 ; i < 10 ; i ++ )
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
Java代碼:
public class SelectionSort {
// 我們的算法類不允許產生任何實例
private SelectionSort(){}
public static void sort(int[] arr){
int n = arr.length;
for( int i = 0 ; i < n ; i ++ ){
// 尋找[i, n)區間里的最小值的索引
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr , i , minIndex);
}
}
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
public static void main(String[] args) {
int[] arr = {10,9,8,7,6,5,4,3,2,1};
SelectionSort.sort(arr);
for( int i = 0 ; i < arr.length ; i ++ ){
System.out.print(arr[i]);
System.out.print(' ');
}
System.out.println();
}
}