1. 程式人生 > >經典排序演算法之桶排序、氣泡排序和選擇排序

經典排序演算法之桶排序、氣泡排序和選擇排序

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

排序完畢。

之所以稱之為氣泡排序,是因為每次迴圈後都找出了最大(或最小)的元素向後移,就像水中的氣泡一樣,如圖:

                                                    

看影象不像是冒泡呢?

時間複雜度(執行起來效率最低的):若待排序資料的初始狀態是正序的,一趟掃描即可完成排序。此時時間複雜度為O(n);若初始時是反序的,需要進行  趟排序。每趟排序要進行  次關鍵字的比較,此時時間複雜度為;因此,平均時間複雜度為:。此外,氣泡排序是穩定的。

示例程式碼:

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] + " ");
		}
	}
	
}