js排序演算法原理圖示詳解

antzone發表於2017-06-19

在javascript中排序演算法有多種,當然這不是js所獨有的,各個語言都是這樣。對這幾個排序演算法的充分掌握還是非常有必要的,因為這不僅僅是一個知識點的問題,而是一種思維的問題,可以將其潛移默化的應用到各種場景,下面就通過程式碼例項結合圖示分別一一介紹一下它們的實現原理。

一.氣泡排序:

冒泡的原理是讓最大元素或者最小元素”浮起來“

插入排序,選擇排序,快速排序,氣泡排序都是比較排序。

思路如下:

依次比較相鄰的兩個數,將小數放在前面,大數放在後面。

step1:比較第1個和第2個數,將小數放前,大數放後。比較第2個數和第3個數,將小數放前,大數放後,如此繼續,直至比較最後兩個數,將小數放前,大數放後。

step2:在第二趟:仍從第一對數開始比較(因為可能由於第2個數和第3個數的交換,使得第1個數不再小於第2個數),將小數放前,大數放後,一直比較到倒數第二個數(倒數第一的位置上已經是最大的),第二趟結束,在倒數第二的位置上得到一個新的最大數(其實在整個數列中是第二大的數)。

如此下去,重複以上過程,直至最終完成排序。

由於在排序過程中總是小數往前放,大數往後放,相當於氣泡往上升,所以稱作氣泡排序。

氣泡排序的動畫效果

要注意三點:

1.交換類的方法在javascript中可以用 a=[b,b=a][0] 這個非常巧妙的方法來解決。

[JavaScript] 純文字檢視 複製程式碼
var,a,b,temp
temp = a;
a=b;
b = temp

2.要注意迴圈變數的快取,這裡快取了array.length。

3.要注意內嵌的那個迴圈,是從第一個數比較到倒數第n個數,n則為比較的step數。

程式碼例項:

[JavaScript] 純文字檢視 複製程式碼
function bubbleSort(array){
  var l=array.length;
  //比較的step數為陣列的長度
  for (var index = 0; index < l; index++) {
        //內嵌交換的次數是從第一個數比較到倒數第總長-n個數,n則為比較的step數
    for (var j = 0; j < l-index; j++) {
      if (array[j] < array[j - 1]) {
        array[j] = [array[j - 1], array[j - 1] = array[j]][0]//在這裡交換元素
       }
    }
    for (var k = 0; k < l; k++) {
      console.log(array[k] + ",");
    }
    console.log('這是第'+(index+1)+'次排序')
  }
}
var a = [6,54,6,22,5,7,8,2,34];
bubbleSort(a);

動畫效果如下:

a:3:{s:3:\"pic\";s:43:\"portal/201703/29/112646eb8ltd5jbgrtzlg8.gif\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

二.插入排序:

這個比較簡單,通俗的說就是摸牌插牌的步驟。

思路如下:

1首先假摸了一張牌,手裡目前所有牌設為empty = [],摸了一張push(arr[0])。

2取出下一個牌,設為a,在所有的牌empty(已經排序)從後向前掃描。

3如果手裡這張牌empty[empty.length-n](已排序)大於新元素,將該牌移到下一位置(騰空間)empty[empty.length-n]= empty[empty.length-n+1]。

4重複步驟3,直到找到已排序的牌empty[empty.length-n]小於或者等於a。

5將a插入到該位置中 empty[empty.length-n]=a。

6重複步驟2。

程式碼如下:

[JavaScript] 純文字檢視 複製程式碼
function insert(arr){
  var l = arr.length;
  var empty = [];//空陣列,表示我們的手
  empty.push(arr[0]);//我們先摸起來一張
  //注意這裡起點是1,因為我們已經摸了一張了!
  for (var index = 1; index < l; index++) {
    if(arr[index] > empty[empty.length - 1]){
      empty[empty.length] = arr[index]
    } //如果比有序陣列empty還大,直接放到末尾
        //從最大值跟arr進行比較,為了給arr騰空。當arr<有序陣列的某一位時,就不用移動了
    for (var j = empty.length; j > 0 && arr[index] < empty[j - 1]; j--) { 
      empty[j] = empty[j - 1]; //向右移動
      empty[j - 1] = arr[index]; //把值放到空出來的位置上
    }
  }
  return empty
}

動畫效果如下:

a:3:{s:3:\"pic\";s:43:\"portal/201703/29/112756rjen75wg7rijr11n.gif\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

三.選擇排序:

把最小元素找出來-扔到陣列裡-再找次小的-扔到陣列裡,以此類推。

首先在未排序陣列中找到最小元素,找的方法可以利用不斷判斷並賦值的手段,即:設陣列第一個元素array[0]為最小元素,那麼“最小元素”在陣列中的序號就為0

之後遍歷陣列,若陣列第二個元素比他還要小,那麼說明第二個為最小元素,把“0” 更新為“1”。

遍歷完畢後,我們就知道這一系列的最小元素下標為“n”;直接拿出來存放到排序序列的起始位置(array[n])

然後,再從剩餘未排序元素中繼續尋找最小元素,然後放到排序序列末尾。注意,此時遍歷的下標就從1開始了。因為已經挑出了一個最小元素了。以此類推,直到所有元素均排序完畢。

[JavaScript] 純文字檢視 複製程式碼
function selectSort(array){
  var min;
  var l = array.length;//快取長度
  //開始進行迴圈,一共迴圈l次,就可以找出l個元素了
  for (var index = 0; index < l; index++) {
    min = index;//假設第一個為最小元素
    for (var j = index + 1; j < l; j++) {//從第一個開始迴圈,遍歷
      if (array[min] > array[j])//判斷之後的是否比前面的小
        min = j;//更新"最小"的下標
    }
    if(min != index) {
      array[index]= [array[min],array[min]=array[index]][0];//交換元素
    }
  }
  return array;
}

這裡仍然注意的是交換的寫法 array[index]= [array[min],array[min]=array[index]][0]

可以方便的把array[index]與array[min]交換。

a:3:{s:3:\"pic\";s:43:\"portal/201703/29/112858izq8j5nc888n6v8j.gif\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

快速排序是目前最強大的排序演算法,演算法利用了遞迴的思想。

從陣列中挑出一個元素,稱為"基準",這個可以直接利用length/2挑出來。

遍歷陣列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。通俗來講:男的站左邊,女的站右邊。之後得到了一個這樣的陣列 array= 比基準小的部分組成的陣列lArray+基準+比基準大的部分組成的陣列rArray。那麼之後只需要再把lArray,rArray進行“同樣的”處理即可。這就需要用到遞迴的寫法了。處理之後,lArray又分成了 lArray的基準,比lArray基準還小的,比lArray基準還大的。那麼不斷的進行操作,男的站左邊,女的站右邊,直到發現,lArray的長度變成1了,不足以再分下去了,認為排序結束。

[JavaScript] 純文字檢視 複製程式碼
function quickSort(arr) {
  var l = arr.length;//快取陣列長度
  //如果我們拿到的lArray,rArray長度比1都小,那就不用排了~
  if(arr.length <= 1){return arr}; 
  //取陣列中間的那個數。注意length/2不一定是整數,用Math.floor取整
  var num = Math.floor(arr.length / 2);
  //利用splice方法,取一個元素出來,注意語法
  var numValue = arr.splice(num, 1)[0];
  var left = [];//建立左邊基準容器
  var right = [];//建立右邊基準容器
  for (var index = 0; index < l; index += 1) {//開始遍歷陣列
    arr[index] < numValue ? left.push(arr[index]) : right.push(arr[index]);//男的站左邊,女的站右邊。。
  }
  return quickSort(left).concat([numValue], quickSort(right))//遞迴,繼續對左右陣列進行操作。
}

動畫效果如下:

a:3:{s:3:\"pic\";s:43:\"portal/201703/29/112952zlm6otu4ug47ozy4.gif\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

相關文章