基本思想:兩兩比較相鄰記錄的關鍵字,如果反序則交換,直至沒有反序為止。
- 最初的冒泡排序(初級版):
1 //從小到大 2 function BubbleSort(arr){ 3 var i,j,temp; 4 for(i=0;i<arr.length-1;i++){ 5 for(j=i+1;j<arr.length;j++){ 6 if(arr[i]>arr[j]){ 7 temp=arr[j]; 8 arr[j]=arr[i]; 9 arr[i]=temp; 10 } 11 } 12 } 13 return arr; 14 } 15 var arr=[10,7,9,11,22,33,4,2,0,1000]; 16 BubbleSort(arr);
17 console.log(arr); //[0, 2, 4, 7, 9, 10, 11, 22, 33, 1000]
由於這樣的排序僅僅是交換順序,不算是真正的冒泡排序,效率也比較低。
當i=0,
arr[0]和它后邊的每一項進行比較大小,前者大於后者,則進行交換。始終保證arr[0]為最小值。
當i=1,(arr[0]已經為最小值,不需要進行比較,)
arr[1]和它后邊的每一項進行比較大小,前者大於后者,則進行交換。始終保證arr[1]為最小值(除去arr[0]以外)。
.......直至i=arr.length-2時,保證前arr.length-1項均“比較”小(小於后邊的所有項),此時不再需要進行比較。(當n個數,前n-1個為“比較”小的值后,最后一個還有什么比較的意義呢??)
- 正宗的冒泡排序(將小的數字如同氣泡一樣慢慢的浮上表面)
1 //從小到大 2 function BubbleSort(arr){ 3 var i,j,temp; 4 for(i=0;i<arr.length-1;i++){ 5 for(j=arr.length-1;j>i;j--){ 6 if(arr[j]<arr[j-1]){ //j為從后往前循環 7 temp=arr[j-1]; 8 arr[j-1]=arr[j]; 9 arr[j]=temp; 10 } 11 } 12 } 13 return arr; 14 } 15 var arr=[10,7,9,11,22,33,4,2,0,1000]; 16 BubbleSort(arr);
17 console.log(arr);// [0, 2, 4, 7, 9, 10, 11, 22, 33, 1000]
當i=0時,
j的第1次循環:j=arr.length-1,j從數組的最后一項開始和前一項比較大小,當前者小於后者,交換位置。
j的第2次循環:j=arr.length-2,繼續和前一項比較大小。
......直至j=1時結束。此時數組的第一項為最小值。
當i=2時,
j的第1次循環:j=arr.length-1,j從數組的最后一項開始和前一項比較大小,當前者小於后者,交換位置。
j的第2次循環:j=arr.length-2,繼續和前一項比較大小。
......直至j=2時結束(即比較完第三項和第二項,第一項已經確定,不需要進行比較)。此時數組的第二項為最小值(除去第一項以外)。
繼續循環i,i=arr.length-2時。比較j的第arr.length項和第i=arr.length-1項,即可得到最終結果。
- 優化后的冒泡排序
當待排序的序列為{2,1,3,4,5,6,7,8,9},那么僅僅需要交換第一個和第二個關鍵字即可。但是前面的算法還是會將循環都執行一遍,造成了多余的計算。
此時我們可以添加一個標記變量flag。
1 //從小到大 2 function BubbleSort(arr){ 3 var i,j,temp; 4 var flag=true; //flag進行標記 5 for(i=0;i<arr.length-1&&flag;i++){ //若flag為false則退出循環 6 flag=false; //初始化為false 7 for(j=arr.length-1;j>i;j--){ 8 if(arr[j]<arr[j-1]){ //j為從前往后循環 9 temp=arr[j-1]; 10 arr[j-1]=arr[j]; 11 arr[j]=temp; 12 flag=true; //如果有數據交換則為true 13 } 14 } 15 } 16 return arr; 17 } 18 var arr=[10,7,9,11,22,33,4,2,0,1000];
19 BubbleSort(arr); 20 console.log(arr); // [0, 2, 4, 7, 9, 10, 11, 22, 33, 1000]
標記變量聲明時狀態為true,進行循環后,標記變量初始化為false狀態。當后邊的項兩兩進行比較時,發生交換則將標記變量狀態更正為true,如果自始至終標記變量的狀態都沒有更正為true,說明為有序,則在外層循環的終止判斷語句中退出。
優化的關鍵在於:
在變量i的for循環中,增加了對flag是否為true的判斷。通過這種改進,可以避免在有序的情況下進行無意義的循環判斷。
- 時間復雜度
1.最好的情況,即數組有序,可以推斷出就是n-1次的比較,時間復雜度為O(n)
2.當最壞的情況,即數組逆序,第一個數需要排n-1次,第二個數需要排n-2次,第3個數需要排n-3次……這樣依次類推,最后一個數只需要排一次,加起來共需要排n(n-1)/2次,所以時間復雜度為O(O^2)
看完大話數據結構,根據自己的理解整理了下,還請大家留下寶貴意見。