關於排序,其實不論是哪一種語言,都有它內置的排序函數,咱們要用的時候調用就好了,既然如此,咱們爲何還要講這個東西呢?我想,其實,咱們講排序更可能是在於排序中包含的思想算法,由於,算法對於計算機來講至關重要,一個好的算法可以讓計算機的效率達到事半功倍的效果,因此,算法是計算機語言中一門至關熱門的課程,它所表明的計算機思惟也是很值得咱們去深刻研究的。javascript
我也知道,關於我標題中的排序,博客園中的不少做者都寫過詳細解釋的文章,可能,筆者本人認爲本身的理解更能體現出這個排序的工做原理吧,因此,筆者也就大慚不愧的在這裏再次寫下關於冒泡排序的文章,有須要的讀者能夠看一下。css
再進入正題以前,我給你們介紹一下谷歌瀏覽器一個頗有用的調試程序代碼的功能,若是你已經知道,請略過。html
首先,打開谷歌瀏覽器,輸入咱們的代碼腳本:java
右鍵,點擊檢查,算法
按順序點擊,獲取腳本的運行代碼:數組
個人腳本是bubble.html,存儲在www.test.com域名下面的js/f目錄下面,每一個人的腳本不同,存儲的目錄也不同,請根據本身的狀況來。瀏覽器
調出腳本的內容後,下面就是調試代碼了。函數
選擇好了斷點以後,接下來在谷歌瀏覽器中再次運行腳本,就是對下面的www.test.com/js/f/bubble.html再回車運行測試
再次運行以後,你會看到這樣的東西:優化
看到上面的那個藍色矩形框了嗎?這個藍色矩形框就是腳本正在運行的代碼位置,那咱們怎麼讓腳本的代碼一步步的運行呢?
這裏之因此對這個腳本的for循環代碼進行斷點監控,其實,我是爲了查看冒泡排序究竟是怎麼循環操做的,對於新手來講,這樣子直觀的查看冒泡排序代碼的運行狀況會更好的瞭解算法的執行過程。
對於這個調試小功能就介紹到這裏了,下面進入正題,沒辦法直接想象出冒泡排序的執行狀況的話,你能夠按我上面的步驟調出谷歌的調試功能,直觀的查看冒泡排序的整個過程。
介紹一下兩個變量互相調換的思惟,咱們藉助中間變量來調換:
//交互元素,這裏的代碼是從腳本中截取出來的,這麼簡單,應該不影響理解 if(arr[j] > arr[j+1]){ mark = false; var temp = arr[j];//temp是中間變量,把要交換的第一個元素arr[j]賦值給中間變量,也是把第一個元素存儲起來 arr[j] = arr[j+1];//第二個元素賦值給第一個元素,由於第一個元素咱們已經存儲在中間變量中了,因此咱們不用擔憂它的值會被覆蓋掉 arr[j+1] = temp;//temp存儲了第一個元素的值,把它賦值給第二個元素,就是把第一個元素賦值給第二個元素了,到這一步,兩個元素已經交換位置了 }
再介紹一下,冒泡排序的算法過程:
冒泡排序:經過對相鄰元素的對比,並交換位置,一步一步的把一個元素給挑選出來。
舉個例子,對下面的數組進行排序:
這是一個無序的數組:2,9,4,8,5,1,0,7,3,6
比較規則:大於>
第一輪:
第一次比較:咱們把2和9做比較:2>9嗎 ?2和9比較是假,那麼咱們無論它,繼續向前。
第二次比較:9和4作比較,9>4嗎 ? 是真,那麼咱們讓它們交換值,交換了值,它們的位置不就變了嗎,是吧?怎麼交換值上面已經講過,這裏再也不重複了。
通過此次交換值,原來的數組已經變成:2,4,9,8,5,1,0,7,3,6
第三次比較:9和8作比較,9>8嗎 ? 是真,那麼它們兩個繼續交換值,此時,數組已經變成:2,4,8,9,5,1,0,7,3,6
......................
看到這裏9的位置了嗎?它是否是一步一步日後移?第一次比較由於9原本就是大的,因此,它不該該和2交換位置,所以,9沒有被放到前面去,第二次比較,由於9比4大,因此,根據比較規則,它們應該互換位置,也就是9向後移了一位,第三次比較,依然符合比較規則,因此9和8互換位置了,9又向後移了一步,接下來的比較和上面的比較是同樣的過程,你本身比較想象一下吧,這裏就再也不重複了。
比較到最後一次:原數組的狀況應該是:2,4,8,5,1,0,7,3,6,9
通過第一輪的比較,咱們已經把最大的元素給放到最後面去了,對吧?
接下來,第二輪:
首先說一下,第二輪的時候,原來的數組2,9,4,8,5,1,0,7,3,6,已經變成了2,4,8,5,1,0,7,3,6,9,咱們是在已經冒泡過一次的數組的基礎上進行比較的,先確認這一點,要是你還認爲是最初的數組,那麼,接下來的比較你會被搞糊塗的。呵呵。
此刻的數組:2,4,8,5,1,0,7,3,6,9
根據比較規則:2>4 嗎?是假,無論它,繼續向前比較。
4>8嗎?是假,無論它,繼續向前比較。
8>5嗎?是真,二者交換值,也就是互換位置,此刻數組:2,4,5,8,1,0,7,3,6,9
繼續向前,8>1嗎?是真,二者交換位置,此刻數組:2,4,5,1,8,0,7,3,6,9
.......
比較到最後,原數組又發生了改變,已經變成:2,4,5,1,0,7,3,6,8,9
通過兩輪的比較,原數組是否已經變得有序一點了?呵呵,沒有錯,兩輪以後,最後面的兩位數已是有序的了。
既然兩輪以後,最後面的兩位已是有序的了,那麼,十輪以後呢?你本身想象一下。
十輪以後,這個數組確定已經排序好了。這就是冒泡排序的工做過程,相鄰元素比較,每一輪冒泡出一個有序的值。
那麼,咱們怎麼用代碼的方式實現冒泡排序呢?
寫到這裏,我想你們應該知道怎麼作了吧?
咱們用兩層嵌套的for循環來實現這個過程,也就是實現冒泡排序:
//外層控制輪數 for(var i=0;i<len;i++){ //內層對數組元素進行冒泡選擇 for(var j=0;j<len-1-i;j++){ //交互元素 if(arr[j] > arr[j+1]){ var temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } }
上面那兩個嵌套的for循環看到了嗎?外層的for循環,咱們就是用來控制比較········輪數········的,
內層的for循環,咱們用來控制···················每一輪的比較次數··················的,同時,在這個for循環裏面,咱們還要作什麼呢?上面的文字敘述,你看懂了嗎?上面的文字敘述中,咱們是否是在···每一次比較···的時候,都要根據比較規則來交換數組元素的位置,是吧?那麼,程序的工做過程也是同樣的,咱們也要在這裏根據比較規則對數組的元素進行交換位置,爲的是冒泡出咱們須要的元素。
下面是冒泡排序的完整代碼,我對他進行了優化,固然,若是還能夠優化,你也能夠繼續優化的。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-cn"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>冒泡排序</title> <meta name="keywords" content="關鍵字列表" /> <meta name="description" content="網頁描述" /> <link rel="stylesheet" type="text/css" href="" /> <style type="text/css"></style> <script type="text/javascript"> //參數數字數組 function bubble(arr){ //檢查參數 if(toString.call(arr) !== '[object Array]'){ return false; } //獲取數組長度 var len = arr.length; if(len <= 1){//小於1不用排序 return arr; } //外層控制輪數 for(var i=0;i<len;i++){ //標記是否有排序的元素 var mark = true; //內層對數組元素進行冒泡選擇 for(var j=0;j<len-1-i;j++){ //交互元素 if(arr[j] > arr[j+1]){ mark = false; var temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } if(mark){ //當沒有進行冒泡選擇時,證實已經排序好了 return arr; } } } //測試 var ar = [9,3,7,4,8,2,5,1,6,0]; alert(bubble(ar)); </script> </head> <body> </body> </html>
這裏只是簡單的介紹冒泡排序的工做原理,假若有時間,我再詳細講解一下另外三個排序,快速排序、選擇排序、插入排序。
其實這三個排序的工做原理都和冒泡排序很類似,網上也有不少文章介紹,你們能夠本身研究一下。