1. 程式人生 > >前端面試必備——基本排序演算法

前端面試必備——基本排序演算法

排序演算法是面試及筆試中必考點,本文通過動畫方式演示,通過例項講解,最後給出JavaScript版的排序演算法

插入排序

演算法描述:
1. 從第一個元素開始,該元素可以認為已經被排序
2. 取出下一個元素,在已經排序的元素序列中從後向前掃描
3. 如果該元素(已排序)大於新元素,將該元素移到下一位置
4. 重複步驟 3,直到找到已排序的元素小於或者等於新元素的位置
5. 將新元素插入到該位置後
6. 重複步驟 2~5

現有一組陣列 arr = [5, 6, 3, 1, 8, 7, 2, 4]

[5] 6 3 1 8 7 2 4  //第一個元素被認為已經被排序
[5,6] 3 1 8 7 2 4 //6與5比較,放在5的右邊 [3,5,6] 1 8 7 2 4 //3與6和5比較,都小,則放入陣列頭部 [1,3,5,6] 8 7 2 4 //1與3,5,6比較,則放入頭部 [1,3,5,6,8] 7 2 4 [1,3,5,6,7,8] 2 4 [1,2,3,5,6,7,8] 4 [1,2,3,4,5,6,7,8]

程式設計思路:雙層迴圈,外迴圈控制未排序的元素,內迴圈控制已排序的元素,將未排序元素設為標杆,與已排序的元素進行比較,小於則交換位置,大於則位置不動

function insertSort(arr){
    var
tmp; for(var i=1;i<arr.length;i++){ tmp = arr[i]; for(var j=i;j>=0;j--){ if(arr[j-1]>tmp){ arr[j]=arr[j-1]; }else{ arr[j]=tmp; break; } } } return arr }

時間複雜度O(n^2)

選擇排序

演算法描述:直接從待排序陣列中選擇一個最小(或最大)數字,放入新陣列中。

[1] 5 6 3  8 7 2 4 
[1,2] 5 6 3  8 7  4 
[1,2,3] 5 6  8 7 2 4 
[1,2,3,4] 5 6 8 7
[1,2,3,4,5] 6  8 7 
[1,2,3,4,5,6] 8 7  
[1,2,3,4,5,6,7] 8  
[1,2,3,4,5,6,7,8] 

程式設計思路:先假設第一個元素為最小的,然後通過迴圈找出最小元素,然後同第一個元素交換,接著假設第二個元素,重複上述操作即可

function selectSort(array) {
  var length = array.length,
      i,
      j,
      minIndex,
      minValue,
      temp;
  for (i = 0; i < length - 1; i++) {
    minIndex = i;
    minValue = array[minIndex];
    for (j = i + 1; j < length; j++) {//通過迴圈選出最小的
      if (array[j] < minValue) {
        minIndex = j;
        minValue = array[minIndex];
      }
    }
    // 交換位置
    temp = array[i];
    array[i] = minValue;
    array[minIndex] = temp;
  }
  return array
}

時間複雜度O(n^2)

歸併排序

演算法描述:
1. 把 n 個記錄看成 n 個長度為 l 的有序子表
2. 進行兩兩歸併使記錄關鍵字有序,得到 n/2 個長度為 2 的有序子表
3. 重複第 2 步直到所有記錄歸併成一個長度為 n 的有序表為止。

5 6 3 1 8 7 2 4

[5,6] [3,1] [8,7] [2,4]

[5,6] [1,3] [7,8] [2,4]

[5,6,1,3] [7,8,2,4]

[1,3,5,6] [2,4,7,8]

[1,2,3,4,5,6,7,8]

程式設計思路:將陣列一直等分,然後合併

function merge(left, right) {
  var tmp = [];

  while (left.length && right.length) {
    if (left[0] < right[0])
      tmp.push(left.shift());
    else
      tmp.push(right.shift());
  }

  return tmp.concat(left, right);
}

function mergeSort(a) {
  if (a.length === 1) 
    return a;

  var mid = Math.floor(a.length / 2)
    , left = a.slice(0, mid)
    , right = a.slice(mid);

  return merge(mergeSort(left), mergeSort(right));
}

時間複雜度O(nlogn)

快速排序

演算法描述:

  1. 在資料集之中,選擇一個元素作為”基準”(pivot)。
  2. 所有小於”基準”的元素,都移到”基準”的左邊;所有大於”基準”的元素,都移到”基準”的右邊。這個操作稱為分割槽 (partition)操作,分割槽操作結束後,基準元素所處的位置就是最終排序後它的位置。
  3. 對”基準”左邊和右邊的兩個子集,不斷重複第一步和第二步,直到所有子集只剩下一個元素為止。
5 6 3 1 8 7 2 4

pivot
|
5 6 3 1 9 7 2 4
|
storeIndex

5 6 3 1 9 7 2 4//將5同6比較,大於則不更換
|
storeIndex

3 6 5 1 9 7 2 4//將5同3比較,小於則更換
  |
  storeIndex

3 6 1 5 9 7 2 4//將5同1比較,小於則不更換
    |
   storeIndex
...

3 6 1 4 9 7 2 5//將5同4比較,小於則更換
      |
      storeIndex

3 6 1 4 5 7 2 9//將標準元素放到正確位置
      |
storeIndex pivot

上述講解了分割槽的過程,然後就是對每個子區進行同樣做法

function quickSort(arr){
    if(arr.length<=1) return arr;
    var partitionIndex=Math.floor(arr.length/2);
    var tmp=arr[partitionIndex];
    var left=[];
    var right=[];
    for(var i=0;i<arr.length;i++){
        if(arr[i]<tmp){
            left.push(arr[i])
        }else{
            right.push(arr[i])
        }
    }
    return quickSort(left).concat([tmp],quickSort(right))
}

上述版本會造成堆疊溢位,所以建議使用下面版本

原地分割槽版:主要區別在於先進行分割槽處理,將陣列分為左小右大

function quickSort(arr){
    function swap(arr,right,left){
        var tmp = arr[right];
        arr[right]=arr[left];
        arr[left]=tmp;
    }
    function partition(arr,left,right){//分割槽操作,
        var pivotValue=arr[right]//最右面設為標準
        var storeIndex=left;
        for(var i=left;i<right;i++){
            if(arr[i]<=pivotValue){
                swap(arr,storeIndex,i);
                storeIndex++;
            }
        }
        swap(arr,right,storeIndex);
        return storeIndex//返回標杆元素的索引值
    }
    function sort(arr,left,right){
        if(left>right) return;
        var storeIndex=partition(arr,left,right);
        sort(arr,left,storeIndex-1);
        sort(arr,storeIndex+1,right);
    }
    sort(arr,0,arr.length-1);
    return arr;
}

時間複雜度O(nlogn)

氣泡排序

演算法描述:
1. 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
2. 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。
3. 針對所有的元素重複以上的步驟,除了最後一個。
4. 持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。5.

5 6 3 1 8 7 2 4

[5 6] 3 1 8 7 2 4 //比較5和6

5 [6 3] 1 8 7 2 4

5 3 [6 1] 8 7 2 4

5 3 1 [6 8] 7 2 4

5 3 1 6 [8 7] 2 4

5 3 1 6 7 [8 2] 4

5 3 1 6 7 2 [8 4]

5 3 1 6 7 2 4 8  // 這樣最後一個元素已經在正確位置,所以下一次開始時候就不需要再比較最後一個

程式設計思路:外迴圈控制需要比較的元素,比如第一次排序後,最後一個元素就不需要比較了,內迴圈則負責兩兩元素比較,將元素放到正確位置上

function bubbleSort(arr){
    var len=arr.length;
    for(var i=len-1;i>0;i--){
        for(var j=0;j<i;j++){
            if(arr[j]>arr[j+1]){
                var tmp = arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=tmp
            }
        }
    }
    return arr;
}

時間複雜度O(n^2)

參考資料

歡迎訂閱[]和知乎專欄

相關推薦

前端面試必備——基本排序演算法

排序演算法是面試及筆試中必考點,本文通過動畫方式演示,通過例項講解,最後給出JavaScript版的排序演算法 插入排序 演算法描述: 1. 從第一個元素開始,該元素可以認為已經被排序 2. 取出下一個元素,在已經排序的元素序列中從後向前

面試必備:高頻演算法題彙總「圖文解析 + 教學視訊 + 範例程式碼」必知必會 排序 + 二叉樹 部分!

排序 所謂排序演算法,即通過特定的演算法因式將一組或多組資料按照既定模式進行重新排序。這種新序列遵循著一定的規則,體現出一定的規律,因此,經處理後的資料便於篩選和計算,大大提高了計算效率。 對於排序: 我們首先要求其具有一定的穩定性 即當兩個相同的元素同時出現於某個序列之中 則經過一定的排序演算法之後

資料結構與演算法JavaScript描述讀書筆記(基本排序演算法

前提準備 //自動生成陣列的函式,n:整數個數,數字在l-r之間 function setData(n,l,r){ var dataStore = []; for(var i=0;i<n;i++){ dataStore[i] = Math.floor(

基本排序演算法-java實現

最近重新學習了排序演算法,之前每次看完當時理解了,但是過一段時間就又忘了,尤其是程式碼,如果放一段時間有很多base case不知道怎麼寫了,所以還是應該詳細的解讀一下再不斷了敲程式碼才能理解比較深刻。 1.氣泡排序(bubble sort) 氣泡排序是一種簡單的排序演算法。其基本思

基本排序演算法的總結

# 插入排序 public static int[] insertSort2(int[] arr) { if (arr.length < 2 || arr == null) { return arr; } // 假設

java基本排序演算法之選擇排序和插入排序

一.選擇排序 一種簡單直觀的排序演算法,特點是效率低,容易實現,速度較氣泡排序快。 思想:遍歷,每一趟從待排序的序列裡取出一個最小的數排在排好序的序列裡面,剩下的重複上述步驟直到排完。 比較簡單直接貼程式碼: public static void xuanze(int

基本排序演算法

文章目錄氣泡排序法選擇排序法插入排序法 氣泡排序法 氣泡排序法是最簡單的一種排序方法他的基本思想就是有一行數字讓他們左右相互比較(a<b)誰小或者誰大就往後面拍,如果這個if不成立就不變(這個是看你是從大往小排還是從小往大排),一直排到第n-1<n

面試常考排序演算法

#include<iostream> #include<algorithm> using namespace std; //快排(最好結果是nlogn,最壞情況是n*n) v

HTTP協議-前端面試必備

HTTP 本文主要介紹面試可能會問到的關於http方面的問題。都是比較基礎的問題,需要自己理解記憶,面試的時候能回答出來即可。更深入的問題,以後可能會再列舉補充。 1. HTTP協議的主要特點 其特點主要有四個:簡單快速、靈活、無連線、無狀態。 簡單快速:統一資源服,

演算法基礎(面試面試中的排序演算法總結

面試中的排序演算法總結   前言   查詢和排序演算法是演算法的入門知識,其經典思想可以用於很多演算法當中。因為其實現程式碼較短,應用較常見。所以在面試中經常會問到排序演算法及其相關的問題。但萬變不離其宗,只要熟悉了思想,靈活運用也不是難事。一般在面試中最常考的是快速排

三個基本排序演算法執行效率比較(氣泡排序,選擇排序和插入排序

1、冒泡演算法。 冒泡演算法是最基礎的一個排序演算法,每次使用第一個值和身後相鄰的值進行比較,如果是升序將大數向左邊交換,降序則向右邊交換。最終將大數移動到一邊,最終排成一個序列: public class Sorting { public void Bubble

筆試面試常考排序演算法總結

在筆試面試的過程中,常常會考察一下常見的幾種排序演算法,包括氣泡排序,插入排序,希爾排序,直接選擇排序,歸併排序,快速排序,堆排序等7種排序演算法,下面將分別進行講解。另外,我自己在學習這幾種演算法過程中,主要參考了MoreWindows Blog中的排序演算法

kotlin 基本排序演算法(冒泡、快排、二分....)與java對比

先還是把這個大神的引用地址貼上,要用到圖片 搞懂基本排序演算法  基本演算法不管是哪種程式都會涉及,只是android用的比較少,很容易忘記,所以能掌握幾種是幾種吧!然而java和kotlin的寫法稍微有點出入。 先來看圖: 懂得理論的話,仔細看還是能看的明

面試系列之排序演算法總結(C/C++版本)

氣泡排序/* 氣泡排序是一種流行但低效的演算法, 它的作用是反覆交換相鄰的未按次序排列的元素 */ #include <stdio.h> void Exchange(int &a,int &b) { // 使用位運算,秀一秀自己的實力

常用演算法--基本排序演算法(氣泡排序,選擇排序,插入排序,快速排序,歸併排序,桶排序)

1.氣泡排序: 思想:以小到大排序為例,對無序的資料兩兩進行比較,大的放在右面,小的放在左面. (1,2),(1,3)...(2,3),(2,4)...(n-1,n-1),(n-1,n) 時間複雜度: O(n) ~ O(n2)O(n2~ Java程式碼實現: p

九種基本排序演算法總結

排序分類: 1、插入排序:直接插入排序,二分法插入排序,希爾排序; 2、選擇排序:簡單選擇排序,堆排序; 3、交換排序:氣泡排序,快速排序; 4、歸併排序; 5、基數排序; (1)直接插入排序:(穩定排序)     基本思想:將每個待排序的記錄,按照其順序碼的大小插入到前

淺談演算法和資料結構: 二 基本排序演算法

本篇開始學習排序演算法。排序與我們日常生活中息息相關,比如,我們要從電話簿中找到某個聯絡人首先會按照姓氏排序、買火車票會按照出發時間或者時長排序、買東西會按照銷量或者好評度排序、查詢檔案會按照修改時間排序等等。在計算機程式設計中,排序和查詢也是最基本的演算法,很多其他的演算法都是以排序演算法為基礎,在一般的資

【C++實現】基本排序演算法 插入排序——歸併排序——快速排序——堆排序

/* 排序總結:(基於100w隨機數,有序數、重複數測試) 1、插入排序適合近乎有序的序列 2、歸併排序優化:(優化前       120S) 1)資料小於15時採用插入排序 10S 2)避免頻繁動態申請記憶體 memcpy(dest,src,sizeof(int)*len)

7種基本排序演算法--java實現

7種基本排序演算法有:直接插入排序、希爾排序;直接選擇排序、堆排序;氣泡排序、快速排序;歸併排序。實現如下:import java.util.Arrays; public class SortAlogrithm { public static void main(St

前端面試必備的css盒子模型

ima 通過 元素 add red 有一種 margin borde 試題 今天同學發給了我一份前端基礎的面試題,第一道便是對css盒子模型的理解,我看到的第一眼想到的是div,然後就...懵逼了,知其然不知其所以然。所以打算寫一寫盒子模型的概念理解啥的,如有