本系列排序包括十大經典排序算法。
- 使用的語言爲:Java
- 結構爲: 定義抽象類
Sort
裏面實現了,交換,大小比較等方法。例如交換兩個值,直接傳入下標就可以了。其他的具體排序的類都繼承抽象類Sort
。這樣我們就能專注於算法本身。
/*
* 返回值等於0,代表 array[i1] == array[i2]
* 返回值小於0,代表 array[i1] < array[i2]
* 返回值大於0,代表 array[i1] > array[i2]
*/
protected int cmp(int i1, int i2) {
return array[i1].compareTo(array[i2]);
}
protected int cmp(T v1, T v2) {
return v1.compareTo(v2);
}
protected void swap(int i1, int i2) {
T tmp = array[i1];
array[i1] = array[i2];
array[i2] = tmp;
}
複製代碼
什麼是選擇排序
- 選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理是:第一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,然後再從剩餘的未排序元素中尋找到最小(大)元素,然後放到已排序的序列的末尾。以此類推,直到全部待排序的數據元素的個數爲零。選擇排序是不穩定的排序方法
算法思想
- n個記錄的文件的直接選擇排序可經過n-1趟直接選擇排序得到有序結果:
- ①初始狀態:無序區爲R[1..n],有序區爲空。
- ②第1趟排序 在無序區R[1..n]中選出關鍵字最小的記錄R[k],將它與無序區的第1個記錄R[1]交換,使R[1..1]和R[2..n]分別變爲記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
- ……
- ③第i趟排序 第i趟排序開始時,當前有序區和無序區分別爲R[1..i-1]和R(i..n)。該趟排序從當前無序區中選出關鍵字最小的記錄 R[k],將它與無序區的第1個記錄R交換,使R[1..i]和R分別變爲記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
解釋
- 對比數組中前一個元素跟後一個元素的大小,如果後面的元素比前面的元素小則用一個變量k來記住他的位置,接着第二次比較,前面“後一個元素”現變成了“前一個元素”,繼續跟他的“後一個元素”進行比較如果後面的元素比他要小則用變量k記住它在數組中的位置(下標),等到循環結束的時候,我們應該找到了最小的那個數的下標了,然後進行判斷,如果這個元素的下標不是第一個元素的下標,就讓第一個元素跟他交換一下值,這樣就找到整個數組中最小的數了。然後找到數組中第二小的數,讓他跟數組中第二個元素交換一下值,以此類推。
算法分析
時間複雜度
選擇排序的最壞、最好、平均時間複雜度爲 O(n^2)。 綜上,因此選擇排序總的平均時間複雜度爲O(n^2)。但是總體上要比冒泡排序要好。因爲交換的次數少於冒泡排序
算法穩定性
- 選擇排序是一種穩定排序算法。
是否是原地算法
- 何爲原地算法?
- 不依賴額外的資源或者依賴少數的額外資源,僅依靠輸出來覆蓋輸入
- 空間複雜度爲 ?(1) 的都可以認爲是原地算法
- 非原地算法,稱爲 Not-in-place 或者 Out-of-place
- 選擇排序屬於 In-place
代碼
public class SelectionSort <T extends Comparable<T>> extends Sort<T>{
@Override
protected void sort() {
// TODO Auto-generated method stub
for (int end = array.length-1; end >0; end--) {
int maxIndex = 0;
for (int begin = 1; begin <=end; begin++) {
if (cmp(maxIndex, begin)<=0) {
maxIndex = begin;
}
}
swap(maxIndex, end);
}
}
}
複製代碼
驗證
使用數據源如下
Integer[] array = {7, 3, 5, 8, 6, 7, 4, 5,19,30,40,50};
結果爲:
- 【SelectionSort】 穩定性:true 耗時:0.0s(0ms) 比較次數:66 交換次數:11
轉載: