書籍資訊

  • 書名:《圖解演算法:使用 C#》
  • 類型:演算法與搜尋方法整理

這篇在講什麼

這一篇是在整理幾種常見搜尋法,重點不是列舉公式,而是先判斷:

  • 資料有沒有排序
  • 資料量大不大
  • 資料分布是否均勻

不同前提下,適合的搜尋法會完全不同。

搜尋前的基本分類

在挑搜尋法前,先問三件事:

  • 資料有沒有先排好序
  • 要不要支援頻繁更新
  • 搜尋成本能不能換取前置處理成本

如果資料沒有排序,很多高效率搜尋法都用不上。
如果資料會一直改動,維持排序本身也有成本。

線性搜尋

線性搜尋最直接:

  • 從頭找到尾
  • 看到目標就停

它的優點是:

  • 不需要排序
  • 實作最簡單
  • 任何可遍歷資料都能用

缺點也很明顯:

  • 平均和最差通常是 O(n)
  • 資料量大時效率不理想
public static bool LinearSearch(int[] nums, int target)
{
    foreach (int num in nums)
    {
        if (num == target)
        {
            return true;
        }
    }

    return false;
}

二分搜尋

二分搜尋的前提很重要:

  • 資料必須已排序

做法是每次看中間值,再決定往左半還是右半繼續找。
因為每次都砍掉一半範圍,所以時間複雜度是 O(log n)

public static int BinarySearch(int[] nums, int target)
{
    int left = 0;
    int right = nums.Length - 1;

    while (left <= right)
    {
        int mid = left + (right - left) / 2;

        if (nums[mid] == target)
        {
            return mid;
        }

        if (nums[mid] < target)
        {
            left = mid + 1;
        }
        else
        {
            right = mid - 1;
        }
    }

    return -1;
}

插值搜尋

插值搜尋可以看成是「會猜位置」的二分搜尋。

它不是每次都切正中間,而是根據數值分布去估計 target 比較可能落在哪裡。
所以它比較適合:

  • 資料已排序
  • 數值分布相對均勻

如果分布很不平均,它的表現就未必比二分搜尋好。

費波那契搜尋

費波那契搜尋同樣屬於有序資料上的搜尋法,只是切分方式改成利用費波那契數列。

它的思路可以理解成:

  • 不用每次取正中間
  • 而是依照費波那契比例來縮小區間

這類方法比較偏演算法教材中的經典技巧,實務上最常見的主力仍然是二分搜尋。

我自己的整理

如果今天只是要快速做選擇,我會先這樣想:

  • 沒排序:先線性搜尋
  • 已排序:先二分搜尋
  • 已排序且分布均勻:才考慮插值搜尋
  • 想理解經典技巧:再看費波那契搜尋

換句話說,搜尋法不是越複雜越好,而是越符合前提越好。

先記住的重點

  • 二分搜尋的最大前提是資料已排序
  • 線性搜尋雖慢,但通用性最高
  • 插值搜尋吃資料分布,條件不對時不一定划算
  • 費波那契搜尋是經典方法,但實務主力通常仍是二分搜尋
  • 搜尋效率常常不是只看搜尋本身,還要把前置排序成本一起算進去