1. 程式人生 > >氣泡排序 java

氣泡排序 java

引言

氣泡排序是我們一般排序入門,也是演算法入門。但是重複的迴圈註定它是一個低效的演算法,低效不低效是由排序多少數字來決定的。可能我們排幾個數時,看不出來,但是要是給上一個100萬數字的陣列排序,那就需要很長的時間,而快排只需要很短時間。

原理

它的一次排序就像石頭扔在水中,石頭和水不停的做交換,直到石頭觸地。
將相鄰的兩個元素加以比較,若左邊的元素大於右邊的元素,則將兩元素交換,若左邊的元素小於右邊的元素,那麼兩元素位置不變,右邊的元素繼續和下一個元素進行比較,重複這個過程,直到比較到最後一個數為止。

虛擬碼
BUBBLEE-SORT(A)	//氣泡排序
	for i <
- 1 to length[A] //外層迴圈 從第一個數到最後一個數 do for j <- length[A] downto i+1 //只排 指標往後的 do if A[i]<A[j-1] //比較 then exchange A[j]<->A[j-1} //交換
程式碼
private static int[] bubbleSort(int[] a) {
	if(a.length == 1)
		return a;
	for (int i = 0; i < a.length-1; i++) {
		int temp;
		for (int
j = 0; j < a.length-i-1; j++) { if(a[j]>a[j+1]) { temp=a[j]; a[j] = a[j+1]; a[j+1] = temp; } } } return a; }
時間複雜度分析
程式碼段 開銷 次數
for i <- 1 to length[A] c1 n+1
do for j <- length[A] downto i+1 c1 i = 1 n ( n i + 1 ) \sum_{i=1}^n(n-i+1)
do if A[j]<A[j-1] c2 i = 1 n ( n i ) \sum_{i=1}^n(n-i)
then exchange A[j]<->A[j-1] c3 t(i)

T ( n ) = c 1 ( n + 1 ) + c 1 [ i = 1 n ( n i + 1 ) ] + c 2 [ i = 1 n ( n i ) ] + c 3 t i T(n) = c_1(n+1) + c_1[\sum_{i=1}^n(n-i+1)]+c_2[\sum_{i=1}^n(n-i)] +c_3t_i
= c 1 ( n + 1 ) + c 1 n ( n + 1 ) / 2 + c 2 n ( n 1 ) / 2 + c 3 t i = c_1(n+1) +c_1n(n+1)/2+c_2n(n-1)/2+c_3t_i
= n 2 ( c 1 + c 2 ) / 2 + n ( 3 c 1 c 2 ) / 2 + c 1 + c 3 t i = n^2(c_1+c_2)/2 + n(3c_1 - c_2)/2+c_1+c_3t_i
最後的結果:
T ( n ) = a n 2 + b n + c T(n) = an^2+bn+c
在排序量特別大時,高數告訴我們要忽略低項看高項(在 n 2 n^2 看來 n n 就是個弟弟)
我們可得到一個大概描述這個時間複雜度的值 O ( n 2 ) O(n^2)

如何優化演算法

氣泡排序很穩定,但是它時間複雜度高,重複交換的太多了,如:

我這裡只能改進演算法,讓它少算一些不必要的過程,但也不能根治(要高效就只能用其他演算法了)
改進1:
以上面的排序,如果我們一開始就給出的是一排好的陣列,但是陣列還是要再排一遍,所以為了解決這個問題,就要在程式碼中放置一監視的變數。

private static int[] bubbleSort(int[] a) {
	if(a.length == 1)
		return a;
	for (int i = 0; i < a.length-1; i++) {
		int temp;
		boolean maxT = true;
		for (int j = 0; j < a.length-i-1; j++) {
			if(a[j]>a[j+1])
				{
				temp=a[j];
				a[j] = a[j+1];
				a[j+1] = temp;
				maxT = false;
		}
		}
		if(maxT)
			return a;
	}
	return a;