資料結構與演算法筆記-------選擇排序
選擇排序
基本介紹
選擇式排序也屬於內部排序法,是從欲排序的資料中,按指定的規則選出某一元素,再依規定交換位置後達到排序的目的。
排序思想
選擇排序(select sorting) 也是一種簡單的排序方法。它的基本思想是:
第一次:從一個array陣列中找到最小值與array[0]交換,也就是說不是像冒泡那樣找到小的就交換,而是遍歷了陣列,找到最小的和array[0]交換,一次只發生一次交換
第二次:從array陣列的array[1]~~~array[n-1]中找到最小值,與array[1]交換,這個過程中也是隻發生一次交換
第三次
總共通過n-1次,得到一個按排序碼從小到大排序的有序序列
思路
第一輪:將第一個位置當成最小數,開始迴圈遍歷餘下陣列,比他小的更新成最小值,再往後找比現在這個還小的,一輪下來,找到最小的,開始交換
第二輪:將第二個位置當成最小數,開始迴圈遍歷餘下陣列,往後面比較,發現比他小的,在更新最小值,再往後,找到剩餘數中最小的數,遍歷完之後,和第一個位置交換
第三輪:同理,從第三個位置開始
….
直到n-1輪
請聽題:
現有科大學生十位,顏值分別是[100,10,35,24,16,79,4,2,57,80],請使用選擇排序從低到高進行排序
程式碼
推導過程:
/**
* @author 王慶華
* @version 1.0
* @date 2020/12/21 21:32
* @Description TODO
* @pojectname 簡單選擇排序
*/
public class SelectSort {
public static void main(String[] args) {
int[] array = {100,10,35,24,16,79,4,2,57,80};
selectSort(array);
}
//選擇排序演算法
public static void selectSort (int[] array){
//逐步推到方式
//第一輪排序
//原始陣列[100,10,35,24,16,79,4,2,57,80]
//結果:[2,10,35,24,16,79,4,100,57,80]
int minIndex = 0;//用來存放,最小值的下標
int min = array[0];//假定現在最小值是陣列第一個 也充當了中間值,來交換
for (int i = 0+1; i < array.length ; i++) {
if (min > array[i]){//說明我們的假定最小值不是最小值
min = array[i]; //重置最小值
minIndex = i; //重置最小值索引
}
}
//迴圈結束,開始交換
if (minIndex != 0) {
array[minIndex] = array[0];
array[0] = min;
}
System.out.println("第一輪後:"+ Arrays.toString(array));
//第一輪後:[2, 10, 35, 24, 16, 79, 4, 100, 57, 80]
//第二輪排序
minIndex = 1;//用來存放,最小值的下標
min = array[1];//假定現在最小值是陣列第一個 也充當了中間值,來交換
for (int i = 1+1; i < array.length ; i++) {
if (min > array[i]){//說明我們的假定最小值不是最小值
min = array[i]; //重置最小值
minIndex = i; //重置最小值索引
}
}
//迴圈結束,開始交換
if (minIndex != 1) {
array[minIndex] = array[1];
array[1] = min;
}
System.out.println("第二輪後:"+ Arrays.toString(array));
//第二輪後:第二輪後:[2, 4, 35, 24, 16, 79, 10, 100, 57, 80]
//依次類推
}
}
在推導過程中,我們發現我們每次for迴圈之前,開始的標記,比上一輪for迴圈開始的位置+1了
那麼我們可以用for迴圈來解決
/**
* @author 王慶華
* @version 1.0
* @date 2020/12/21 21:32
* @Description TODO
* @pojectname 簡單選擇排序
*/
public class SelectSort {
public static void main(String[] args) {
int[] array = {100,10,35,24,16,79,4,2,57,80};
System.out.println("排序前"+Arrays.toString(array));
selectSort(array);
System.out.println("排序後"+Arrays.toString(array));
}
//選擇排序演算法
public static void selectSort(int[] array){
for (int i = 0; i < array.length -1 ; i++) {
int minIndex = i;
int min = array[i];
for (int j = i+1; j <array.length ; j++) {
if (min > array[j]){//說明假定的最小值不是最小
min = array[j];//重置min
minIndex = j;//重置最小值下標
}
}
//交換
if (minIndex != i){
array[minIndex] = array[i];
array[i] = min;
}
System.out.println("第"+i+"輪排序的結果是");
System.out.println(Arrays.toString(array));
}
}
}
我們來語言加深一下記憶:
外層迴圈控制第幾輪排序,內層迴圈是用來控制我們的排序開始的位置
其中,優點在哪?我們發現我們的資料交換的方式跟我們的氣泡排序不一樣了,因為這裡是一次交換,不像是我們的氣泡排序那樣,每次達到要求就交換,所以我們的選擇排序,用了最小值下標這個中間輔助變數,用來只發生一次變化
那有人會覺得,若是我第N輪恰好不用交換呢?我們發現我們交換的時候多了一層if判斷,這個if判斷就是用來判斷,當前最小值下標是不是我們一開始假定的最小值的下標,如果不是在交換,是的話就直接輸出了,不發生交換,算是一個小優化
然後我們測一測選擇排序去排序一個array[80000]陣列的時間,我們發現就單單2秒鐘或者3秒鐘,確實比氣泡排序快多了