| Mô phỏng Tìm kiếm Nhị phân (Binary Search): Thuật toán “Chia để trị” kinh điển

Được viết bởi thanhdt vào ngày 26/02/2026 lúc 11:34 | 14 lượt xem

Trong thế giới lập trình và cấu trúc dữ liệu, việc tìm kiếm một phần tử cụ thể trong hàng triệu, hàng tỷ bản ghi dữ liệu là một bài toán hằng ngày. Nếu bạn tìm kiếm tuyến tính (Linear Search) bằng cách quét qua từng phần tử một từ đầu đến cuối, hệ thống của bạn sẽ sụp đổ vì quá chậm.

Đó là lúc phép màu của Tìm kiếm Nhị phân (Binary Search) xuất hiện. Trong bài viết này, Hướng Nghiệp Dữ Liệu sẽ mô phỏng chi tiết cách hoạt động của thuật toán kinh điển này theo cách dễ hiểu nhất, kèm theo ứng dụng thực tế.

1. Tìm kiếm Nhị phân là gì? Phương pháp “Lật từ điển”

Hãy tưởng tượng bạn đang cầm trên tay một cuốn từ điển dày 1000 trang và muốn tìm từ “Lập trình”. Bạn sẽ không bao giờ lật từ trang 1, trang 2, trang 3… đúng không? Bạn sẽ mở thẳng vào giữa cuốn sách (trang 500). – Nếu trang 500 bắt đầu bằng vần ‘M’, bạn biết từ khóa ‘L’ nằm ở nửa đầu cuốn sách. Bạn ngay lập tức xé bỏ/loại trừ 500 trang nửa sau. – Tiếp tục mở giữa nửa đầu (trang 250). Nếu nó bắt đầu bằng vần ‘H’, bạn lại biết từ khóa ‘L’ nằm ở nửa sau (từ 250 – 500). Bạn lại loại trừ một nửa nữa.

Bạn cứ lặp lại quá trình “Bổ đôi” này cho đến khi tìm đúng trang. Đó chính xác là Binary Search.

Điều kiện tiên quyết tuyệt đối: Mảng dữ liệu buộc phải được SẮP XẾP SẴN (Tăng dần hoặc giảm dần) thì thuật toán mới có thể hoạt động. Cuốn từ điển đã được xếp theo thứ tự A-Z.

2. Mô phỏng thuật toán từng bước (Simulation)

Cùng mô phỏng việc tìm số 37 trong một mảng đã sắp xếp gồm 10 phần tử: Mảng: [2, 5, 8, 12, 16, 23, 37, 45, 56, 72]

Chúng ta sử dụng 2 con trỏ: Left (Đầu mảng) và Right (Cuối mảng).

Lần lặp 1:Left = 0 (Giá trị 2), Right = 9 (Giá trị 72). – Lấy điểm Giữa Mid = (0 + 9) / 2 = 4 (Phần nguyên). Giá trị tại vị trí số 4 là 16. – So sánh: 16 nhỏ hơn 37. Vậy số 37 chắc chắn nằm bên phải số 16. – Hành động: Di chuyển Left lên vị trí Mid + 1 (Tức là vị trí số 5).

Lần lặp 2:Left = 5 (Giá trị 23), Right = 9 (Giá trị 72). – Tính lại Mid = (5 + 9) / 2 = 7. Giá trị tại vị trí 7 là 45. – So sánh: 45 lớn hơn 37. Vậy số 37 chắc chắn nằm ở bên trái của số 45. – Hành động: Giữ nguyên Left, thu hẹp Right về Mid - 1 (Tức là vị trí số 6).

Lần lặp 3:Left = 5 (Giá trị 23), Right = 6 (Giá trị 37). – Lấy Mid = (5 + 6) / 2 = 5. Giá trị tại vị trí 5 là 23. – So sánh: 23 nhỏ hơn 37. Nằm bên phải. – Hành động: Kéo Left lên Mid + 1 (Tức là vị trí 6).

Lần lặp 4:Left = 6, Right = 6. – Mid = (6 + 6) / 2 = 6. Giá trị tại vị trí 6 là 37. – BINGO! Đã tìm thấy số 37. Kết thúc thuật toán. Quá trình chỉ tốn 4 phép thử.

3. Tại sao Binary Search lại được gọi là “Sức mạnh thao túng Dữ liệu lớn”?

  • Độ phức tạp tuyến tính (Linear Search): Khối lượng công việc là O(N). Nếu tìm trong 1 tỷ dữ liệu thẻ tín dụng, trường hợp xui nhất máy tính phải quét 1 tỷ lần. Mất hàng giây đến vài chục giây.
  • Độ phức tạp nhị phân (Binary Search): Khối lượng công việc là O(log N) (Log cơ số 2 của N).
    • Để tìm kiếm trong 1 Tỷ dữ liệu ($10^9$), con số kỳ diệu của phép tính $\log_2(1,000,000,000)$ chỉ xấp xỉ 30.
    • Việc loại trừ 50% dữ liệu sau mỗi câu hỏi giúp CPU chỉ cần tối đa 30 lần mở “từ điển” là tìm ra vị trí chính xác trong 1 Tỷ phần tử. Tốc độ xảy ra trong chưa tới 1 mili-giây. Sức mạnh này khủng khiếp đến ngỡ ngàng!

4. Hiện thực hóa bằng Code Python

Sau đây là cách lập trình vòng lặp while cơ bản cho Thuật toán Tìm kiếm Nhị phân:

def binary_search(arr, target):
    left = 0
    right = len(arr) - 1

    while left <= right:
        mid = (left + right) // 2

        # Nếu phần tử nằm ở chính giữa
        if arr[mid] == target:
            return mid

        # Nếu target lớn hơn giá trị ở Mid, nó phải nằm ở nửa sau (Bên phải)
        elif arr[mid] < target:
            left = mid + 1

        # Ngược lại, target nhỏ hơn giá trị ở Mid, nó nằm nửa đầu (Bên trái)
        else:
            right = mid - 1

    # Phần tử không tồn tại trong mảng
    return -1

# Khai báo mảng đã sắp xếp và chạy thử nghiệm
sorted_array = [2, 5, 8, 12, 16, 23, 37, 45, 56, 72]
result_index = binary_search(sorted_array, 37)

print(f"Giá trị nằm ở chỉ mục: {result_index}") # Output: 6

Kết Luận

Hiểu rõ mô phỏng Tìm Kiếm Nhị Phân (Binary Search) là yêu cầu nhập môn bất di bất dịch của mọi lập trình viên chuyên nghiệp trước khi bước vào các thuật toán phức tạp hơn (như Cây nhị phân, Đồ thị…). Nó phản ánh hoàn hảo tư duy “Chia để trị” (Divide and Conquer) – Khi gặp một bãi rác dữ liệu khổng lồ, đừng cắm đầu đào bới, hãy dọn dẹp (Sort) và chặt đôi vấn đề ra để giải quyết nhanh gọn nhất!