關於算法的東西,本來不應該交給javascript來做,因為對算法和數據結構的理解,並不會因為用自己熟悉的語言實現常用數據結構和算法而得到多大的提升,不過這一過程終歸是有一些好處的,對於一些非科班出身的人來講。
首先解釋一下冒泡排序的機制:遍歷要排序的數列,比較相鄰兩個元素,如果他們的順序和我們想要的不一致,就把他們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。冒泡排序的做法有小數上浮 或者 大數下沉兩種 ,這里只提及大數下沉的實現。
外層循環的作用是,提取出目前未排序數組中最大的數,放置於已排數據的左邊。也就是說我們第一次外層循環,是把最大數的位置交換到數組的最右邊,第二次外層循環是把次大數交換到數組的次右邊,依次類推。而且一個數組的長度為length,我們只需要提出 length-1 個大數,則數組的 第一個 必定為 未被提取的 最小數,那么在外層for循環的條件判斷 i 的取值范圍也就可以理解了。
而內層循環的作用就是實現我們想要的大數下沉的過程。每次比較的是相鄰兩個數據,所以一個數組的長度為length,我們只需要做 length-1 次相鄰的比較,就可以實現大數下沉,而 之前循環 已經沉淀的大數 並不需要再進行 排序了 , 所以內層循環的 條件判斷 j 的取值范圍 也容易理解了。
接下來我們要做數據交換了,我們想做的是 大數沉淀, 也就是 當相鄰兩個數據,左邊比右邊大時,交換位置,這里提供了三種方法。
下面發一段關於冒泡排序的代碼吧。
1 function bubbleSort (arr) { 2 for (var i = 0; i < arr.length-1; i++) { 3 for (var j = 0; j < arr.length-1-i; j++) { 4 if (arr[j] > arr[j+1]) { 5 /* 設置第三方變量來用於數據交換,且這個變量放在循環的外面性能要好 6 var temp = arr[j]; 7 arr[j] = arr[j+1]; 8 arr[j+1] = temp; 9 */ 10 11 // 利用加法來實現兩個數據的交換 12 // arr[j] = arr[j] + arr[j+1]; 13 // arr[j+1] = arr[j] - arr[j+1]; 14 // arr[j] = arr[j] - arr[j+1]; 15 16 // 利用位運算實現兩個數據的交換 17 arr[j] = arr[j]^arr[j+1]; 18 arr[j+1] = arr[j]^arr[j+1]; 19 arr[j] = arr[j]^arr[j+1]; 20 } 21 }; 22 }; 23 return arr; 24 }
我們可以看到,第一種方法需要開辟新的內存空間,所以這個第三方變量為全局變量時性能較好,這一種方法是使用最多的方法,也最易於理解。
第二種方法,則是利用了加法實現了兩個數據的交換,也不難理解,而且加法可以做,減法肯定也可以做,畢竟減法在某種意義上來講,也是加法。
第三種方法使用了位運算,按位異或 XOR 由符號(^)表示,它是直接對數據在內存中的二進制形式進行運算。這里用到了按位異或的一個特性實現了數據的交換:一個數據按位異或另一個數兩次等於它本身。它的效率要比上述兩種方式的效率要高,但是用javascript想要高效率的處理數據本身就是一個笑話。
至此我們的冒泡就告一段落了,如有錯漏的地方還請多多指正。