經典排序、搜索算法

GITHUB

https://github.com/nebulium/Sortinggit

參考書

  • 《學習JavaScript數據結構與算法》

冒泡排序

  • 兩層循環,外層循環作計數,內層循環每次完成一個循環的時候確保未排序部分最大的值「冒泡」到數組最末端,下面是i=0的狀況:
  • 顯然,每次j=length-1的時候,未排序部分的最大值已經到達右端了(由於比較的是o[j+1]和o[j]),即已經冒泡完畢。因此沒有必要每次在內層循環都對這些已經排序完畢的進行比較。所以有改進的冒泡排序。
  • 改進的冒泡排序:修改內層循環中j的上限:j < length-1-i;
  • 算法複雜度:O(n2)

選擇排序:

  • 原址比較排序算法
  • 算法複雜度:O(n2)
  • 一樣兩層循環,外層循環作計數,且每次預設第i個值爲最小值(minIndex)。內層循環每次完成一個循環都確保未排序部分的最小的值被選中(minIndex),繼而與預設的索引指向的值交換。下面是i=0的狀況:

插入排序:

  • 每次比較一個數組項。先默認第一項已經排序完畢,考慮第二項應該放在第一項的左邊仍是右邊;第二項插入完畢後,認爲第一項和第二項都已經排序完畢,考慮第三項應該插入第一項的左邊仍是第一二項的中間亦或者第二項的右邊…依次類推,直到全部項排序完畢。注意須要進行數組項的移位:

    a. 從i=1開始考慮(由於i=0的狀況顯然已經「排序完畢」了)。github

    b. 將當前值「取出」給temp。依次與前面的已經排序號的數組項進行比較。算法

    c. 若是比前一個值(即已經升序排序完畢的數組項的最後一個值)大,則不須要進一步排序,由於包含當前值的數組項已經升序排序好了。數組

       d. 若是比前一個值小,則須要將前一個值移位值當前值,並繼續與更前面的一個值比較。直到找到合適的位置(升序排列的合適的位置),將取出的值  (temp)插入到那個位置。數據結構

  • 算法複雜度:一樣有兩重循環,在排序小型數組的時候,性能比冒泡排序和選擇排序都好。

歸併排序:

  • 遞歸算法,算法複雜度爲O(nlogn)
  • 使用分治的方法。將數組分解,直至分解爲只含有一個值的數組,再調用merge函數,對其進行合併以及排序。

快速排序

  • 一樣用分治的方法,將數組分解。可是因爲對數組的分解並非比較均勻的,分解的函數甚至有重疊的狀況。因此若是想要直觀的理解比較困難。此處列出算法。建議理解代碼。我的看來,這個排序算法的實現用到的遞歸比歸併排序的好理解:

a. 首先須要進行劃分操做:找到一個主元、並定義兩個做爲左右指針的變量,一個取索引0,一個取索引length-1.函數

b. 左指針從左向右找到一個比主元大的值,右指針從右向左找到一個比主元小的值,直到兩者發生交錯(left>right)。也就是說,基本上按照升序排列,要求主元左邊的值都大於右邊的。性能

c. 找到對應的兩個值以後交換。學習

d. 如今獲得兩個新的數組分區,即從0索引到移動後的左指針的位置(其實是-1處),以及左指針到數組最右端(length-1)處。對這兩段分區再一次調用劃分操做的函數,進行遞歸處理。3d

e. 直到數組排序完成(left大於index-1,right小於index,即數組沒法繼續進行劃分)指針

  • 算法複雜度:O(nlogn),但性能比前面的都要好。

搜索算法

  • 順序搜索:順序進行搜索,效率低。
  • 二分搜索

a. 二分搜索的前提,就是先調用排序算法、將數組從小到大排序。

b. 而後取其中間的數值,與要搜索的值進行比較:若是小於該值,則應該在右半部分進行進一步的二分搜索;若是大於該值,則在左半部分進行;等於該值,則搜索成功。

  • 具體搜索的方式能夠根據數據結構進行靈活的調整。好比說二叉樹的搜索就是一種通過修改的二分搜索。
相關文章
相關標籤/搜索