Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Binary Search ใน C++ (การค้นหาแบบทวิภาค)

Binary Search เป็นอัลกอริทึมค้นหาใน อาร์เรย์ที่เรียงลำดับแล้ว โดยแบ่งช่วงค้นหาลงครึ่งเรื่อยๆ

เงื่อนไข

  • อาร์เรย์ต้อง เรียงลำดับแล้ว (Sorted)
  • เข้าถึงแบบ Random Access ได้ (Array, Vector)

หลักการทำงาน

  1. ตั้งค่า low = 0, high = n-1
  2. คำนวณ mid = (low + high) / 2
  3. เปรียบเทียบ arr[mid] กับค่าที่หา (target)
  4. ถ้าเท่ากัน → หาเจอ คืนค่า index
  5. ถ้า target น้อยกว่า → ค้นหาครึ่งซ้าย (high = mid - 1)
  6. ถ้า target มากกว่า → ค้นหาครึ่งขวา (low = mid + 1)
  7. ทำซ้ำจน low > high (ไม่เจอ)

โค้ด Recursive Version

#include <iostream>
using namespace std;

int binarySearch(int arr[], int low, int high, int target) {
    if (low > high)
        return -1;  // ไม่เจอ
    
    int mid = low + (high - low) / 2;  // ป้องกัน overflow
    
    if (arr[mid] == target)
        return mid;
    else if (arr[mid] > target)
        return binarySearch(arr, low, mid - 1, target);
    else
        return binarySearch(arr, mid + 1, high, target);
}

int main() {
    int arr[] = {1, 3, 7, 15, 18, 20, 25, 33, 36, 40};
    int n = sizeof(arr) / sizeof(arr[0]);
    int target;
    
    cout << "Enter number to search: ";
    cin >> target;
    
    int index = binarySearch(arr, 0, n - 1, target);
    
    if (index == -1)
        cout << target << " not found in array" << endl;
    else
        cout << target << " found at index " << index << endl;
    
    return 0;
}

โค้ด Iterative Version (แนะนำ)

int binarySearchIterative(int arr[], int n, int target) {
    int low = 0, high = n - 1;
    
    while (low <= high) {
        int mid = low + (high - low) / 2;
        
        if (arr[mid] == target)
            return mid;
        else if (arr[mid] < target)
            low = mid + 1;
        else
            high = mid - 1;
    }
    return -1;
}

ผลลัพธ์ตัวอย่าง

Enter number to search: 20
20 found at index 5

Enter number to search: 100
100 not found in array

Complexity

Metric Complexity
Time - BestO(1)
Time - AverageO(log n)
Time - WorstO(log n)
Space (Recursive)O(log n)
Space (Iterative)O(1)

Lower Bound / Upper Bound (C++ STL)

#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> v = {1, 3, 7, 15, 18, 20, 25, 33, 36, 40};
    int target = 20;
    
    // lower_bound: ตำแหน่งแรกที่ >= target
    auto itLow = lower_bound(v.begin(), v.end(), target);
    
    // upper_bound: ตำแหน่งแรกที่ > target
    auto itUp = upper_bound(v.begin(), v.end(), target);
    
    // binary_search: พบหรือไม่ (bool)
    bool found = binary_search(v.begin(), v.end(), target);
    
    // equal_range: คู่ [lower, upper)
    auto range = equal_range(v.begin(), v.end(), target);
    
    cout << "Found: " << found << endl;
    cout << "Lower bound index: " << (itLow - v.begin()) << endl;
    cout << "Upper bound index: " << (itUp - v.begin()) << endl;
    cout << "Count of " << target << ": " << (range.second - range.first) << endl;
    
    return 0;
}

ผลลัพธ์ STL

Found: 1
Lower bound index: 5
Upper bound index: 6
Count of 20: 1

Binary Search บนเงื่อนไข (Predicate)

ใช้หาค่า น้อยที่สุดที่ทำให้เงื่อนไขเป็นจริง (Lower Bound on Answer)

// หา x น้อยที่สุดที่ f(x) = true
// f(x) ต้องเป็น monotonic (false...false true...true)

int binarySearchPredicate(int low, int high) {
    while (low < high) {
        int mid = low + (high - low) / 2;
        if (f(mid))
            high = mid;
        else
            low = mid + 1;
    }
    return low;  // หรือ high
}

ข้อผิดพลาดทั่วไป

  • ❌ mid = (low + high) / 2 → อาจ Overflow → ใช้ low + (high - low) / 2
  • ❌ ลืมตรวจสอบ low <= high ใน while loop
  • ❌ ใช้กับอาร์เรย์ที่ ไม่ได้เรียง
  • ❌ คืนค่า mid แทน low หรือ high ในบางรูปแบบ