經典排序演算法之桶排序、氣泡排序和選擇排序
1.桶排序
桶排序是將待排序的資料扔到按順序排列的桶裡,如下圖:
其中每個桶都有按順序的編號(桶就是陣列,編號是陣列的下標),將每個數放到編號與之對應的桶裡,然後再將桶裡的數依次拿出來便排號了序。缺點:如果需要對100、2、0進行排序,則需要建立一個大小為101(下標從0開始,見上圖)的陣列,造成了嚴重的空間浪費。
時間複雜度:
對於N個待排資料,M個桶:
平均時間複雜度:O(N+N*logN-N*logM)
最好情況下的時間複雜度:O(N),當N=M時,即極限情況下每個桶只有一個數據時。
如果相對於同樣的N,桶數量M越大,其效率越高,最好是O(N)。當然桶排序的空間複雜度為O(N+M),如果輸入資料非常龐大,而桶的數量也非常多,則空間代價無疑是昂貴的。此外,桶排序是穩定的。
示例程式碼:
public class BucketSort { public static void main(String[] args) { int arr[] = {3, 1, 5, 3, 4}; bucketSort(arr); } static void bucketSort(int arr[]) { //首先找出待排序資料的最大值 int max = 0; for (int i = 0; i < arr.length; i++) { if(max < arr[i]) { max = arr[i]; } } //建立桶 int bucket[] = new int[max + 1]; //將資料放入桶 for (int i = 0; i < arr.length; i++) { bucket[arr[i]]++; } //輸出桶裡的資料 for (int i = 0; i < bucket.length; i++) { for (int j = 0; j < bucket[i]; j++) { System.out.print(i + " "); } } } }
2.氣泡排序
氣泡排序是比較相鄰兩個元素的大小,將大的(或小的),向後移動。
例如,我們需要對3,6,4,2,4進行排序(由小到大),則氣泡排序過程如下:
第一次迴圈:
3,6,4,2,4 第一次比較:3和6比較,3小於6,不移動,結果:3,6,4,2,4
第二次比較:6和4比較,6大於4,將6後移,結果:3,4,6,2,4
第三次比較:6和2比較,6大於2,將6後移,結果:3,4,2,6,4
第四次比較:6和4比較,6大於4,將6後移,結果:3,4,2,4,6
第二次迴圈:
3,4,2,4,6 第一次比較:2和4比較,3小於4,不移動,結果:3,4,2,4,6
第二次比較:4和2比較,4大於2,將4後移,結果:3,2,4,4,6
第三次比較:4和4比較,4等於4,不移動,結果:3,2,4,4,6
第三次迴圈:
3,2,4,4,6 第一次比較:3和2比較,3大於2,將3後移,結果:2,3,4,4,6
第二次比較:3和4比較,3小於4,不移動,結果:2,3,4,4,6
第四次迴圈:
2,3,4,4,6 第一次比較:2和3比較,2小於3,不移動,結果:2,3,4,4,6
排序完畢。
之所以稱之為氣泡排序,是因為每次迴圈後都找出了最大(或最小)的元素向後移,就像水中的氣泡一樣,如圖:
看影象不像是冒泡呢?
時間複雜度(執行起來效率最低的):若待排序資料的初始狀態是正序的,一趟掃描即可完成排序。此時時間複雜度為;若初始時是反序的,需要進行 趟排序。每趟排序要進行 次關鍵字的比較,此時時間複雜度為;因此,平均時間複雜度為:。此外,氣泡排序是穩定的。
示例程式碼:
public class BubbleSort {
public static void main(String[] args) {
int arr[] = {3, 6, 4, 2, 4};
bubbleSort(arr);
}
static void bubbleSort(int arr[]) {
//需要迴圈的次數
for (int i = 0; i < arr.length - 1; i++) {
//比較次數
for (int j = 0; j < arr.length - i - 1; j++) {
//資料交換
if(arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for(int a : arr) {
System.out.print(a + " ");
}
}
}
3.選擇排序
選擇排序是每一次從待排序的資料中選出最大(或最小)的一個元素,存放在未排序資料的後端(或前端)位置,直到全部待排序的資料元素排完。 其和氣泡排序類似,氣泡排序是兩兩比較交換,而此方法是先找出最大(或最小)值後再與序列的後端(或前端)進行交換,如圖(別說這個圖和氣泡排序的一樣哈,看第一次迴圈後的是不一樣的):
時間複雜度(優於氣泡排序):最好和最壞情況都是,但交換次數少,優於氣泡排序。此外,選擇排序是不穩定的。
示例程式碼:
public class SelectionSort {
public static void main(String[] args) {
int arr[] = {3, 6, 4, 2, 4};
selesctionSort(arr);
}
static void selesctionSort(int arr[]) {
//最大元素下標
int maxIndex = 0;
int temp = 0;
//迴圈次數
for (int i = 0; i < arr.length; i++) {
maxIndex = 0;
//比較
for (int j = 0; j < arr.length - i; j++) {
if(arr[maxIndex] < arr[j]) {
maxIndex = j;
}
}
//將最大元素放到每趟未排序元素的最後
temp = arr[arr.length - i - 1];
arr[arr.length - i - 1] = arr[maxIndex];
arr[maxIndex] = temp;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}