數組查找: 線性查找與二分查找

前言

從數組中查找你須要的數據,是一個很常見的需求,那麼當你查找所需數據時,用什麼方法查找速度最快?javascript

本文將經過圖文形式,詳細講解線性查找二分查找,並用JavaScript將其實現,歡迎各位感興趣的前端開發者閱讀本文。前端

線性查找

概念

線性查找是一種在數組中查找數據的算法,從數組的頭部開始按順序往下查找即爲線性查找java

圖解示例

如圖所示,咱們查找數字6在數組中的位置算法

  • 從數組的最左邊開始查找,將其與6進行比較,若是結果一致,查找便結束,不一致則向右檢查下一個數字。

  • 此處不一致,因此向右繼續和下一個數字進行比較。

  • 重複上述操做直到找到數字6爲止

  • 找到6了,查找結束

線性查找須要從頭開始不斷地按順序檢查數據,所以在數據量大且目標數據靠後,或者目標數據不存在時,比較的次數就會更多,也更爲好使。若數據量爲n,線性查找的時間複雜便爲O(n)。數組

用JS實現線性查找

正如圖解示例所述,咱們想要查找某個值在數組中的位置,須要遍歷這個數組,判斷當前遍歷到的值是否與目標值相等。函數

  • 聲明一個函數,參數爲:須要查找的數組,須要查找的數據
  • 遍歷數組
  • 比較須要查找的數據是否與當前遍歷到的數據相等
  • 若是相等則返回當前元素的位置,結束循環

接下來,咱們將上述實現思路轉化爲代碼性能

  • 編寫線性查找函數
/** * 線性查找函數 * @param arr 須要進行查找的數組 * @param target 須要查找的數據 * @returns {number} 返回值 */
const linearSearch = function (arr,target) {
    // 目標元素位置
    let position = -1;
    for (let i = 0; i < arr.length; i++){
        // 若是當前遍歷到的值與目標值相等則返回目標元素的位置
        if(arr[i] === target){
            position = i;
            return position;
        }
    }
    return position;
}
複製代碼

接下來,咱們測試下剛纔編寫的線性查找函數測試

const dataArr = [3,9,8,2,1,4,6,5,7];
const position = linearSearch(dataArr,6);
if(position !== -1){
    console.log(`目標元素在數組中的位置:${position}`);
}else{
    console.log("目標元素不在數組中");
}
複製代碼

二分查找

概念

二分查找也是一種在數組中查找數據的算法,它只能查找已經排序好的數據。ui

二分查找經過比較數組中間的數據與目標數據的大小,能夠得知目標數據是在數組的左邊仍是右邊。spa

所以,比較一次就能夠把查找範圍縮小一半。重複執行該操做接能夠找到目標數據,或者得出目標數據不存在的結論。

圖解示例

如圖所示,咱們查找數字6在數組中的位置

  • 首先,找到數組中間的數字,此處爲5.

  • 將5和要查找的數字6進行比較

  • 把不須要的數字移出查找範圍

  • 在剩下的數組中找到中間的數字,此處爲7

  • 比較6和7

  • 把不須要的數字移出查找範圍

  • 在剩下的數組中找到中間的數字,此處爲6

  • 6=6,成功找到目標數字

用JS實現二分查找

正如圖解示例所述,二分查找只能查找已經排序好的數據,每一次查找均可以將查找範圍減半,查找範圍內只剩一個數據時查找結束。

  • 聲明一個函數,參數爲:要查找的數組,要查找的數據,數組的起點,數組的末尾
  • 找到數組的中間值,將其與目標值進行比較
  • 若是中間值大於目標值,可知目標值在中間值的左側,則對其左邊的數據執行上述操做
  • 若是中間值小於目標值,可知目標值在中間值的右側,則對其右邊的數據執行上述操做
  • 直至中間值等於目標值,則結束上述操做,返回中間值的位置。

咱們將上述思路轉化爲代碼

  • 編寫二分查找函數
/** * 二分查找 * @param arr 查找的數組 * @param target 查找的數據 * @param start 數組的開始位置 * @param end 數組的末尾位置 * @returns {number} */
const binarySearch = function (arr,target,start,end) {
    let targetPosition = -1;
    // 計算中間值
    const median = Math.floor((start + end) / 2);
    // 判斷中間值與目標值是否相等
    if(arr[median] === target){
        targetPosition = median;
        return targetPosition;
    }
    // 未找到
    if(start >= end){
        return targetPosition;
    }
    // 判斷中間值是否大於目標值
    if(arr[median] > target){
        // 遞歸中間值左側的數組
        return binarySearch(arr,target,start,median - 1)
    }else{
        // 遞歸中間值右側的數組
        return binarySearch(arr,target, median + 1, end);
    }
};
複製代碼

接下來,咱們來測試下剛纔編寫的二分查找函數

const dataArr = [1,2,3,4,5,6,7,8,9];
const position = binarySearch(dataArr,6,0,dataArr.length - 1);
if(position !== -1){
    console.log(`目標元素在數組中的位置:${position}`)
}else{
    console.log("目標元素不在數組中");
}
複製代碼

線性查找與二分查找的區別

本質區別

線性查找能夠從亂序數組中找數據,而二分查找只能從已排序好的數組中查找數據。

性能

二分查找利用已排序好的數組,每一次查找均可以將查找範圍減半。若是將數量爲n的數組,將其長度減半log2n次後,其中便只剩一個數據了,所以它的時間複雜度爲O(logn)

線性查找須要從頭開始不斷地按順序檢查數據,所以在數量大且目標數據靠後,或者目標數據不存在時,比較的次數就會更多,也更爲耗時。若是數組的數據量爲n,線性查找的時間複雜度便爲O(n)

從時間複雜度上分析,二分查找相比線性查找速度獲得了指數倍的提高。

使用場景

線性查找,數組中的數據能夠是無序的,添加數據時無需顧慮位置,直接將其插入到數組的末尾便可,不須要耗費時間。

二分查找,數組中的數據必須是有序的,添加數據時就須要考慮位置,須要消耗必定的時間。

綜合上述,若是你查找數據比較頻繁的話二分查找更適合你,不然線性查找更適合你。

寫在最後

  • 文中使用的圖片源自《個人第一本算法書》,如若侵權,請評論區留言,做者當即刪除相關圖片。
  • 文中若有錯誤,歡迎在評論區指正,若是這篇文章幫到了你,歡迎點贊和關注😊
  • 本文首發於掘金,未經許可禁止轉載💌
相關文章
相關標籤/搜索