用js寫插入排序和挑選排序

我以為作為前端學學算法也是有好處的吧,所以本日就先來講講最基本的排序算法。提拔我們程序員的內功~

插進去排序

插進去排序是n^2的基本排序要領,大抵頭腦是假定一個數組的前n個元素已有序,然後斟酌把第n+1個未排序的元素給插進去到有序數組中去。現將n+1和第n個元素比較,假如n+1比n小,那末就交流一下位置。以後我們要排序的元素就在n這個位置上了,接着我們繼承比較n和第n-1個元素的大小。云云重複,直到我們要插進去的元素找到合適他的位置。
下面來樹模一下
6–7–8–9–3–1–4–6–3–8–9–5
6–7–8–9已有序,我們要插進去的元素是n=4這個元素3。比較9和3的大小,9比3大。交流一下位置
6–7–8–3–9,就變成了這個模樣。接着比較8和3的大小,8比3大,交流一下位置
6–7–3–8–9,繼承比較7和3的大小,7比3大,交流一下位置
6–3–7–8–9,繼承比較6和3的大小,6比3大,交流一下位置
3–6–7–8–9。到這裏輪迴完畢,就已排好序了。接着比較第n=5的元素1應當插進去的位置,云云來去就把數組給排好了序了。
一下是代碼。

//寫一個隨機天生數組的函數
function randomArr(count) {
  var arr = []
  for (var i = 0; i < count; i++) {
    var number = Math.ceil(Math.random() * 5000)
    arr.push(number)
  }
  return arr
}
// 交流元素位置的函數
function swap(arr, i, j) {
  var temp = arr[i]
  arr[i] = arr[j]
  arr[j] = temp
}

var arr = randomArr(5000)
// 插進去排序函數
function insertionSort(arr) {
    var length = arr.length
    // 第0個元素默許就是有序的,由於只要一個元素,所以從第一個元素最先。arr[i]就是要插進去的誰人元素
    for (var i = 1; i < length; i++) {
        // 從第i-1個元素往前都是已排好序的元素。所以末了一個最先往前比較
        for (var j = i - 1; j >= 0; j--) {
            // 這裏的j+1即是i這個元素。也就是arr[i] === arr[j+1]
            if (arr[j] > arr[j + 1]) {
                swap(arr, j + 1, j)
            } else {
                break
            }
        }
    }
    return arr
}
insertionSort(arr)

由因而兩層for輪迴,所以它的時刻複雜度是n^2級別的。
到這裏實在還沒有完,插進去排序照樣有能夠優化的處所的。如今的這個插進去排序函數要swap頻仍的交流位置,我們能夠如許

function insertionSort(arr) {
    var length = arr.length
    // 第0個元素默許就是有序的,由於只要一個元素,所以從第一個元素最先。arr[i]就是要插進去的誰人元素
    for (var i = 1; i < length; i++) {
        // **用一個變量保留要插進去的元素**
        var value = arr[i]
        // 從第i-1個元素往前都是已排好序的元素。所以末了一個最先往前比較
        for (var j = i - 1; j >= 0; j--) {
            // 這裏的j+1即是i這個元素。也就是arr[i] === arr[j+1]
            if (arr[j] > value) {
                // 假如比要插進去的元素大,把值arr[j]往右移一名
                arr[j+1] = arr[j]
                // 邊界條件,直到j即是0的時刻停止輪迴,將value賦給arr[0],完畢輪迴
                if (j === 0){arr[j] = value; break}
            } else {
                // 不然把value賦給arr[j]輪迴完畢
                arr[j] = value
                break    
            }
        }
    }
    return arr
}

雖然插進去排序是n^2級別的算法,但是在一個近乎有序的數組裡去完成插進去排序,那末他的效力會變的異常高。

由於插進去排序能夠提早break掉內層輪迴。

有興緻能夠寫一個天生近乎有序數組的函數去試驗一下。

// 近乎有序數組
function nearlySorted(arr) {
  return arr
}

挑選排序

挑選排序就是在輪迴中不斷的挑選最小的元素,然後交流位置。
下面來樹模一下
6–7–8–9–3–1–4–6–3–8–9–5
找到數組中最小的元素1,然後紀錄1的位置是5。接着交流位置變成
1–7–8–9–3–6–4–6–3–8–9–5
接着在剩下的數組裡7–8–9–3–6–4–6–3–8–9–5找到最小的元素3,紀錄下它的下標位置是4,然後交流位置變成
1–3–8–9–7–6–4–6–3–8–9–5。云云來去直到排好序。

function randomArr(count) {
  var arr = []
  for (var i = 0; i < count; i++) {
    var number = Math.ceil(Math.random() * 5000)
    arr.push(number)
  }
  return arr
}
function swap(arr, i, j) {
  var temp = arr[i]
  arr[i] = arr[j]
  arr[j] = temp
}

var arr = randomArr(5000)

function selectionSort(arr) {
  var length = arr.length
  var value, pos
  for (var i = 0; i < length; i++) {
    value = arr[i]
    pos = i
    for (var j = i; j < length; j++) {
      var cur = arr[j]
      if (value > cur) {
        value = cur
        pos = j
      }
    }
    swap(arr, i, pos)
  }
  return arr
}
selectionSort(arr)

到此兩個基本排序就完成了。總結一下,插進去排序優於挑選排序。

插進去排序能夠提早停止內層輪迴,假如數組近乎有序,那末效力會很高。而挑選排序沒法提早停止輪迴。
不過最好的排序算法照樣nlogn級別的算法。如合併排序和疾速排序。
我的寫的不是最好的,僅僅是詮釋觀點,有興緻的同硯能夠本身寫一個更好的插進去排序和挑選排序。

    原文作者:Runnnnn
    原文地址: https://segmentfault.com/a/1190000014529562
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞