JavaScript數組-排序算法

數組排序算法

數組排序

冒泡排序
 插入排序
 快速排序
 選擇排序
 希爾排序
 歸併排序
 ...javascript

算法在線動態演示

// 冒泡排序
    // 當前項和後一項進行比較 若是當前項大於後一項則 交換位置
    var arr = [29, 10, 34, 40, 18]

    function bubbleSort(arr) {
      arr = arr.slice(0)

      for (var i = 0; i < arr.length - 1; i++) {
        for (var j = 0; j < arr.length - 1 - i; j++) {
          var cur = arr[j]
          if (cur > arr[j + 1]) {
            var temp = arr[j]
            arr[j] = arr[j + 1]
            arr[j + 1] = temp
          }
        }
      }
      return arr
    }
    console.log(bubbleSort(arr)) // [10, 18, 29, 34, 40]


    // 快速排序
    // 建立兩個數組(left right) 用中間項和其它項比較,比中間項小的放在左邊數組 比中間項大的放在右邊數組... 
    // 左邊數組和右邊數組均按照以上思路 進行排序
    function quickSort(arr) {
      if (arr.length <= 1) {
        return arr
      }
      var mind = Math.floor(arr.length / 2)
      var mid = arr.splice(mind, 1)
      var left = []
      var right = []
      for (var i = 0; i < arr.length; i++) {
        var cur = arr[i]
        if (cur < mid) {
          left.push(cur)
        } else {
          right.push(cur)
        }
      }
      return quickSort(left).concat(mid, quickSort(right))
    }
    var arr = [29, 10, 34, 40, 18]

    console.log(quickSort(arr)) // [10, 18, 29, 34, 40]
複製代碼

算法具體實現

冒泡排序

讓當前項和後一項進行比較,若是當前項大於後一項則交換位置。
思想:java

  • 比較相鄰的兩個的元素,若是當前元素大於後一項 則交換位置算法

  • 對每一對相鄰兩項,從開始第一對到結尾的最後一對。每一輪比較結束後,都會有一個最大的數排在後面shell

  • 隨着每輪的比較,愈來愈少的元素重複上面的步驟(後面排列着以前幾輪每輪比較出來的最大數),直到沒有任何一對數字須要比較。數組

// 冒泡排序 bubbleSort
  function bubbleSort(arr) {
    var temp
    for (var i = 0; i < arr.length - 1; i++) { // 控制輪數
      for (var j = 0; j < arr.length - 1 - i; j++) { // 控制每輪的比較次數
        if (arr[j] > arr[j + 1]) {
          temp = arr[j]
          arr[j] = arr[j + 1]
          arr[j + 1] = temp
        }
      }
    }
    return arr
  }
  bubbleSort(arr)
複製代碼

簡單優化 - 對於有序數組無須排序優化

// 冒泡排序 bubbleSort
  function bubbleSort(arr) {
    var temp
    for (var i = 0; i < arr.length - 1; i++) { // 控制輪數
      var isSort = true
      for (var j = 0; j < arr.length - 1 - i; j++) { // 控制每輪的比較次數
        if (arr[j] > arr[j + 1]) {
          temp = arr[j]
          arr[j] = arr[j + 1]
          arr[j + 1] = temp
          isSort = false
        }
      }
      if (isSort) {
        return arr
      }
    }
    return arr
  }
  bubbleSort(arr)
複製代碼

繼續優化-抽象處理交換邏輯swapui

// 冒泡排序 bubbleSort
  function bubbleSort(arr) {
    for (var i = 0; i < arr.length - 1; i++) { // 控制輪數
      var isSort = true
      for (var j = 0; j < arr.length - 1 - i; j++) { // 控制每輪的比較次數
        if (arr[j] > arr[j + 1]) {
          swap(arr, i, j) // 交換位置
          isSort = false
        }
      }
      if (isSort) {
        return arr
      }
    }
    return arr
  }
   
  // 交換swap
  function swap(arr, i, j) {
    var temp = arr[j]
    arr[j] = arr[j + 1]
    arr[j + 1] = temp
  }
  bubbleSort(arr)
複製代碼

插入排序

思想:
  插入排序是從後往前比較, 從第二項開始一次往前比較 若是當前項大於前一項 則中止比較並將當前項插入到前一項的後面spa

function insertC(A) {
  for (let i = 1; i < A.length; i++) {
    // p 指向 下一個要比較的索引
    let p = i - 1

    // 當前要插入項
    let cur = A[i]
    
    // 只要前一項大於當前項就一直循環下去
    while(p >= 0 && A[p] > cur) {
      // 前一項大於當前項 就將前一項日後挪一位
      A[p + 1] = A[p]
      // 每比較完一次 p存儲的索引值 就往前挪一位 進行下次比較
      p--
    }

    // 執行到這一行 說明 當前項cur 大於索引p這一項
    // 則將當前項插入到後面
    A[p + 1] = cur
  }
}

const A5 = [2, 4, 13, 6, 3]
insertC(A5)
console.log(A5) // [ 2, 3, 4, 6, 13 ]
複製代碼
// 插入排序
  function insertSort(arr) {
    var len = arr.length
    var cur
    var prev
    for (var i = 1; i < len; i++) {
      cur = arr[i]
      prev = i - 1
      while (prev > -1 && cur < arr[prev]) {
        arr[prev + 1] = arr[prev]
        prev--
      }
      arr[prev + 1] = cur
    }
    return arr
  }
  insertSort(arr)
複製代碼

快速排序

思想:

1.在待排序的元素任取一個元素做爲基準(一般選第一個元素,但最的選擇方法是從待排序元素中隨機選取一個做爲基準),稱爲基準元素;
2.將待排序的元素進行分區,比基準元素大的元素放在它的右邊,比其小的放在它的左邊;
3.對左右兩個分區重複以上步驟直到全部元素都是有序的。.net

快速排序(大衆版)code

// 快速排序 (大衆版)
function quickSort(arr) {
  if (arr.length <= 1) return arr
  let midIndex = Math.floor(arr.length / 2)
  let midNum = arr.splice(midIndex, 1)[0]
  let left = []
  let right = []
  for (let i = 0; i < arr.length; i++) {
    let cur = arr[i]
    if (cur <= midNum) {
      left.push(cur)
    } else {
      right.push(cur)
    }
  }
  return quickSort(left).concat(midNum, quickSort(right))
}
let arr = [2, 4, 12, 9, 22, 10, 18, 6]
console.log(quickSort(arr))
複製代碼

快速排序(徹底版)

let array = [9, 6, 20, 3, 2];
// let array = [15, 13, 20, 21, 29];

function quickSort(arr, left = 0, right = arr.length - 1) {
  let len = arr.length;
  let partitionIndex;
  // left = typeof left != 'number' ? 0 : left;
  // right = typeof right != 'number' ? len - 1 : right;
  if (left < right) {
    partitionIndex = partition(arr, left, right);
    quickSort(arr, left, partitionIndex - 1);
    quickSort(arr, partitionIndex + 1, right);
  }
  return arr;
}

function partition(arr, left, right) {
  let pivot = left;
  let index = pivot + 1;
  for (let i = index; i <= right; i++) {
    if (arr[i] < arr[pivot]) {
      swap(arr, i, index);
      index++;
    }
  }
  swap(arr, pivot, index - 1);
  return index - 1;
}

function swap(arr, i, index) {
  [arr[i], arr[index]] = [arr[index], arr[i]];
}
console.log(quickSort(array));
複製代碼

快速排序 - 原地排序

function swap(A, i, j) {
  [A[i], A[j]] = [A[j], A[i]]
}

function partition(A, lo, hi) {
  const pivot = A[hi - 1]
  let j = hi - 1
  let i = lo
  while(i !== j) {
    A[i] <= pivot ? i++ : swap(A, i, --j)
  }
  swap(A, j, hi - 1)
  return j
}

function qsort(A, lo = 0, hi = A.length) {
  if (hi - lo <= 1) return
  const p = partition(A, lo, hi)
  qsort(A, lo, p)
  qsort(A, p + 1, hi)
}
const A = [1, 5, 28, 6, 0, 12]
qsort(A)
console.log(A) // [ 0, 1, 5, 6, 12, 28 ]
複製代碼

選擇排序

思想:
 每一次從未排序序列中找到最小(大)元素,存放到排序序列的當前的起始位置。以此類推,直到全部元素均排序完畢。

// 選擇排序 insert_sort
const ary = [1, 24, 8, 19, 10]

function insert_sort(arr) {
  for (let i = 0; i < arr.length - 1; i++) {
    var min = i
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[min]) {
        min = j
      }
    }

    if (i !== min) {
      var temp = arr[i]
      arr[i] = arr[min]
      arr[min] = temp
    }
  }
  return arr
}

console.log(insert_sort(ary))
複製代碼

希爾排序

let array = [5, 13, 20, 3, 2];
// let array = [15, 13, 20, 21, 29];

function shellSort(arr) {
  var len = arr.length,
    temp,
    gap = 1;
  while (gap < len / 3) { //動態定義間隔序列
    gap = gap * 3 + 1;
  }
  for (gap; gap > 0; gap = Math.floor(gap / 3)) {
    for (var i = gap; i < len; i++) {
      temp = arr[i];
      for (var j = i - gap; j >= 0 && arr[j] > temp; j -= gap) {
        arr[j + gap] = arr[j];
      }
      arr[j + gap] = temp;
    }
  }
  return arr;
}

console.log(shellSort(array));
複製代碼

歸併排序

let array = [5, 13, 20, 3, 2];
// let array = [15, 13, 20, 21, 29];

function mergeSort(array) {
  let arr = array.slice(0);
  let len = arr.length;
  if (len < 2) {
    return arr;
  }
  let midIndex = Math.floor(len / 2);
  let left = arr.slice(0, midIndex);
  let right = arr.slice(midIndex);
  return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right) {
  let result = [];
  while(left.length && right.length) {
    result.push(left[0] < right[0] ? left.shift() : right.shift());
  }

  if (left.length && !right.length) {
    result = result.concat(left);
  }

  if (right.length && !left.length) {
    result = result.concat(right);
  }
  return result;
}

console.log(mergeSort(array));
複製代碼

----------------------------------------------------------------------------------------------------------------
參考文章&&強烈推薦:布羅利

相關文章
相關標籤/搜索