1. 程式人生 > >排序演算法 JS實現

排序演算法 JS實現

原文引用自這裡,這裡只是我自己的學習的補充以及筆記

插入排序

時間複雜度,O(N2

  • 插入排序: 在已經排好序的序列中從後向前掃描
  • 思路:插入排序在比較的時候有兩種情況,下一個數更大,下一數更小或相等當下一個數更大的時候,就把下一個數在陣列內的索引向後移動一位,相當於是給Temp騰出位置, 繼續比較,因為在Tmep之前的數其實都是排好順序的,所以,當遇到下一位數更小的時候,就可以break出當前迴圈,並且把Temp賦值給arr[j]
  • 其實再說的簡單一點,每一次比較都相當於是互換位置或者不換,只是我們這裡用Tmep把比較的數儲存起來了 所以只是進行了 互換位置的第一步,向後移動,沒有把Temp真正的互換,當遇到了不需要互換的時候,就在進行互換的第二步
  • for迴圈外層控制未排序元素,內層遍歷控制已排序元素
var arr = [5, 6, 3, 1, 8, 7, 2, 4];

function insertSort(arr) {
  for (var i = 1; i < arr.length; i++) {
    var Temp = arr[i];
    for (var j = i; j >= 0; j--) {
      if (arr[j - 1] > Temp) {
        // 如果前面的數比Temp大,那麼他們需要後退一位用來給Temp讓出一個位置
        arr[j] = arr[j - 1
]; } else { // 因為前面已經排好序了所以就直接賦值 arr[j] = Temp; break; } } } return arr; } console.log(insertSort(arr));

選擇排序

時間複雜度,O(N2

  • 選擇排序:在沒有排好序的序列中選擇最小的放入到排好序的序列的後方
  • 思路:整個陣列分為兩個部分已經排好序的前部分a,未排好序的後部分b, 每次迴圈從b的第一個數字開始,選擇出最小的數字,交換b的第一個數字和最小的數字,依次推進,直到b部分的長度為0
  • 外迴圈為b的第一個數字,內迴圈進行比較
  • minValue為最小數字,minIndex為最小數字的索引用於後面交換,temp交換數字時暫時儲存
var arr = [5, 1, 6, 3, 1, 8, 7, 2, 4];

function selectSort(arr) {
var minValue, minIndex, temp;
  for (var i = 0; i < arr.length - 1; i++) {
    minIndex = i; // 每次要進行重置,否則如果當b的第一個數字就是最小的值的時候,minIndex不會進行操作,會保留上次迴圈的值,造成錯誤
    minValue = arr[i];
    for (var j = i + 1; j < arr.length; j++) {
      if (arr[j] < minValue) {
        minIndex = j;
        minValue = arr[minIndex];
      }
    }
    // 當b的第一個數字不是最小的值的時候,才進行交換
    if (minIndex !== i) {
      temp = arr[i];
      arr[i] = minValue;
      arr[minIndex] = temp;
    }
  }
  return arr;
}
console.log('選擇排序' + selectSort(arr2));

歸併排序

時間複雜度,O(nlogn)

  • 選擇排序,把陣列細分到最小化,排序後再組合在排序,從n個數字→n/2個組合→n個數字
  • 思路:由於要不停的拆分陣列在比較拆分在比較,可以感覺到,應該是有大量重複的工作的,所以,根據答案可知運用了遞迴方法,通過兩個函式劃分功能
  • mergeSort把陣列拆分開,並且遞迴呼叫自己,直到陣列被劃分為最完全狀態。每一次的拆分呼叫merge方法,進行排序,merge對拆分出的兩個陣列排序比較,通過依次比較兩個陣列中的數字排序,最後concat兩個陣列並返回
  • merge依次比較,從兩個陣列的0號元素開始比較,每得到一個結果push進一個新的陣列中,並把這個元素從原陣列中shift掉,繼續比較“0”號元素
function merge(arrLeft, arrRight) {
  var newArr = [];

  while (arrLeft.length && arrRight.length) {
    if (arrLeft[0] > arrRight[0]) {
      newArr.push(arrRight.shift());
    } else {
      newArr.push(arrLeft.shift());
    }
  }
  // 當left和right中其中有一個率先排序完成,剩餘的還未push進newArr的陣列就直接連線到temp中
  return newArr.concat(arrLeft, arrRight);
}
// 拆分  
function mergeSort(arr) {
  // 遞迴結束條件
  if (arr.length === 1) {
    return arr;
  }

  var mid = Math.floor(arr.length / 2), // 平均分配兩個陣列,使用floor是因為保證前一個數組都是偶數,假如有奇數個數字,只會留在最後
    left = arr.slice(0, mid),
    right = arr.slice(mid);

  return merge(mergeSort(left), mergeSort(right));
}
console.log('歸併排序' + mergeSort(arr3));

氣泡排序

時間複雜度,O(N2

  • 氣泡排序:遍歷陣列,每次迴圈,把最小的數放到開頭
  • 思路:每進行一次迴圈就把最大的數放到末尾,所以每次比較相鄰的兩個數字,交換或者不交換
  • 迴圈的次數每次減少一次,比如第一次排序完成後,最後一個數就不參與排序了
 var arr4 = [5, 1, 6, 3, 1, 8, 7, 2, 4];
// 氣泡排序
function bubbleSort(arr) {
  var temp;

  for (var i = 0; i < arr.length-1; i++) {
    for (var j = arr.length-1; j > i; j--) {
      if (arr[j] < arr[j - 1]) {
        temp = arr[j];
        arr[j] = arr[j - 1];
        arr[j - 1] = temp;
      }
    }
  }
  return arr;
}
console.log('氣泡排序' + bubbleSort(arr4));

快速排序

時間複雜度,O(nlogn)

  • 快速排序,選擇比較標準值,比標準值大的放在右邊,小的放在左邊
  • 思路:每次排序,選擇一個標準值,以及一段比較值,比如從arr[0]到arr[9],每次迴圈把這一段值分為比標準值大比標準值小,多次遞迴排序,最後得到結果。關鍵在於選擇遞迴拆分點,也就是每次要得到標準值在陣列中的位置index。初始的時候,標準值為最右側的值,index為最左側,當每次比較的時候,有arr[i]比標準值小,就交換arr[i]和arr[index],並且此時可以知道,index需要+1, 通俗來說就是,現在至少有一個值比標準值小了,所以標準值最後存放的位置至少+1,迴圈完了以後,在把標準值放入到arr[index]中,就完成了一次操作
var arr5 = [5, 1, 6, 3, 1, 8, 7, 6, 2, 4];
// 快速排序
function quickSort(arr) {
  function swap(arr, index, i) {
    var temp = arr[index];
    arr[index] = arr[i];
    arr[i] = temp;
  }

  function partition(arr, left, right) {
    var index = left;
    var pointValue = arr[right];

    for (var i = left; i < right; i++) {
      if (arr[i] < pointValue) {
        swap(arr, index, i);
        index++;
      }
    }
    // 找到標準值最後的位置之後,把標準值放置過來
    swap(arr, index, right);
    return index;
  }

  function sort(arr, left, right) {
    if (left > right) {
      return;
    }
    var index = partition(arr, left, right);
    sort(arr, left, index - 1);
    sort(arr, index + 1, right);
  }

  sort(arr, 0, arr.length - 1);
  return arr;
}
console.log('快速排序' + quickSort(arr5));