BINARY SEARCH: Thuật toán tìm kiếm nhị phân

Ngày đăng: 12/09/2020   -    Cập nhật: 23/10/2020

Như vậy là qua các bài trước chúng ta đã tìm hiểu kha khá về các thuật toán sắp xếp. Hôm nay chúng ta cùng tìm hiểu về một thuật toán tìm kiếm nhé. Và mình muốn giới thiệu với bạn thuật toán BINARY SEARCH (thuật toán tìm kiếm nhị phân)

1. Thuật toán BINARY SEARCH là gì?


Thuật toán Binary Search (Tìm kiếm nhị phân)

Thuật toán Binary Search (Tìm kiếm nhị phân)


Thuật toán Binary Serach (Tìm kiếm nhị phân) là một thuật toán tìm kiếm tuyến tính cao cấp hơn với thời gian chạy là O(logN).

Đối với các danh sách lớn, thuật toán này tốt hơn hẳn tìm kiếm tuyến tính, nhưng nó đòi hỏi danh sách phải được sắp xếp từ trước và đòi hỏi khả năng truy nhập ngẫu nhiên (random access).

Thuật toán tìm kiếm nhị phân thường dùng để tìm kiếm phần tử trong một danh sách đã được sắp xếp, ví dụ như trong một danh bạ điện thoại sắp xếp theo tên, có thể tìm kiếm số điện thoại của một người theo tên người đó.

Thuật toán tìm kiếm nhị phân chạy nhanh hơn tìm kiếm tuần tự nhưng cũng có một số nhược điểm. Nó chậm hơn bảng băm.

Nếu nội dung danh sách bị thay đổi thì danh sách phải được sắp xếp lại trước khi sử dụng tìm kiếm nhị phân.

Mà thao tác này thường tốn nhiều thời gian.

2. Ý tưởng và Mô tả thuật toán Binary Search


Vì thuật toán Binary Search yêu cầu mảng đã được sắp xếp. Thế nên, đầu vào của chúng ta là một mảng đã được sắp xếp.

Do đó, thuật toán tìm kiếm nhị phân sẽ so sánh giá trị đích với phần tử ở giữa của mảng (mảng được chia mảng ra làm 2 phần bên trái và bên phải phần tử đó)

Nếu chúng không bằng nhau thì dĩ nhiên một nửa không chứa mục tiêu sẽ bị bỏ đi.

Và việc tìm kiếm tiếp tục ở nửa còn lại, một lần nữa lấy phần tử ở giữa được chọn để so sánh với giá trị đích và lặp lại điều này cho đến khi tìm thấy giá trị đích.

Nếu tìm kiếm kết thúc với nửa còn lại trống, mục tiêu không nằm trong mảng.

Mặc dù ý tưởng rất đơn giản, nhưng việc thực hiện tìm kiếm nhị phân chính xác đòi hỏi phải chú ý đến một số điểm tinh tế về điều kiện thoát và tính toán điểm giữa của nó.


Về cơ bản, các bước thực hiện tìm kiếm nhị x trong mảng như sau:

  • So sánh x với phần tử ở giữa
  • Nếu x khớp với phần tử ở giữa, chúng ta trả về chỉ số giữa
  • Nếu x lớn hơn phần tử giữa, thì x chỉ có thể nằm trong nửa phân đoạn bên phải sau phần tử mid. Vì vậy, chúng ta chỉ tìm kiếm ở nữa phải của mảng
  • Nếu x nhỏ hơn phần tử giữa tiếp tục tìm ở nửa bên trái
  • Lặp lại đến khi tìm ra x hoặc trả về null khi x không nằm trong mảng

Ví dụ, chúng ta có mảng A[2, 4, 9, 10, 11, 22, 24, 31, 48, 56, 76, 86]


  • Nhiệm vụ: Tìm vị trí của số 10 trong mảng
Minh họa thuật toán Binary Search trong Java
 
  • Đầu tiên, ta so sánh số 10 với phần tử ở giữa thì thấy 10 < 22. Bỏ phần bên phải.
Minh họa thuật toán Binary Search trong Java (1)
 
  • Tiếp tục với phần bên trái với phần tử giữa là 9. Ta có 10 > 9. Vì thế ta bỏ phần bên trái.

Minh họa thuật toán Binary Search trong Java (2)
  • Tiếp tục với phần bên phải. So sánh phần tử ở giữa (với Giữa = (Chặn dưới + Chặn trên) / 2). Ta tìm thấy giá trị 10 ở vị trí 3.
Minh họa thuật toán Binary Search trong Java (3)

3. Triển khai thuật toán Binary Search trong Java


Từ ví dụ minh hoạ trên hình ở mục 2, chúng ta hãy triển khai nó sang chương trình trong Java xem như thế nào nhé.


package binary.search.algo;

public class BinarySearch {

    // Trả về chỉ mục của x nếu nó có trong arr[l..r]
    // ngược lại trả về -1
    int binarySearch(int arr[], int lint rint x) {
        if (r >= l) {
            int mid = l + (r - l) / 2;

            // Nếu phần tử có ở chính giữa
            if (arr[mid] == x)
                return mid;

            // Nếu phần tử nhỏ hơn giữa, thì nó chỉ có thể
            // hiện diện trong mảng con bên trái
            if (arr[mid] > x)
                return binarySearch(arrlmid - 1x);

            // Ngược lại, phần tử chỉ có thể có mặt
            // trong mảng con bên phải
            return binarySearch(arrmid + 1rx);
        }

        // Nếu phầnt tử không có trong mảng
        return -1;
    }

    public static void main(String args[]) {
        BinarySearch ob = new BinarySearch();
        int arr[] = { 24910112224314856, 76, 86 };
        int n = arr.length;
        int x = 10;
        int result = ob.binarySearch(arr0n - 1x);
        if (result == -1)
            System.out.println("Phần tử không tồn tại.");
        else
            System.out.println("Phần tử được tìm thấy tại vị trí: " + result);
    }
}
 

Khi chạy chương trình ta có kết quả:


Phần tử được tìm thấy tại vị trí: 3
 

Tuy nhiên thuật toán BinarySearch cũng có thể viết theo một cách khác, tương tự như trên nhưng chúng ta sẽ lặp đi lặp lại phần tử.


package binary.search.algo;

public class IterativeBinarySearch {

    // Trả về chỉ mục của x nếu nó có trong arr[l..r]
    // ngược lại trả về -1
    int binarySearch(int arr[], int x) {
        int l = 0, r = arr.length - 1;
        while (l <= r) {
            int m = l + (r - l) / 2;

            // kiểm tra xem x có ở chính giữa không
            if (arr[m] == x)
                return m;

            // Nếu x lớn hơn, bỏ qua nửa bên trái
            if (arr[m] < x)
                l = m + 1;

            // Nếu x nhỏ hơn, bỏ qua nửa bên phải
            else
                r = m 1;
        }

        // phần tử không tồn tại
        return -1;
    }

    public static void main(String args[]) {
        BinarySearch ob = new BinarySearch();
        int arr[] = { 24910112224314856, 76, 86 };
        int n = arr.length;
        int x = 10;
        int result = ob.binarySearch(arr, x);
        if (result == -1)
            System.out.println("Phần tử không tồn tại.");
        else
            System.out.println("Phần tử được tìm thấy tại vị trí: " + result);
    }
}
 

Chạy chương trình ta có kết quả:


Phần tử được tìm thấy tại vị trí: 3
 


Thuật toán Binary Search có lợi thế lớn về độ phức tạp thời gian khi so sánh với các thuật toán tìm kiếm khác.

Điều đặc biệt đối với tìm kiếm nhị phần là mảng cần phải được sắp xếp trước đó, nên việc bạn áp dụng một thuật toán sắp xếp nào đó mà mình đã chia sẻ hôm trước là một điều gần như là bắt buộc.

Binary Search là thuật toán quan trọng và được ứng dụng nhiều trong cuộc sống. Việc các thuật toán kết hợp và bổ trợ cho nhau là điều không thể tránh khỏi, và việc bạn cần phải biết càng nhiều thuật toán thông dụng cũng là việc bắt buộc nếu muốn thành công trong nghề lập trình này.

> Nếu bạn đang quan tâm đến việc học lập trình với nền tảng vững chắc, đặc biệt là lập trình Java thì tham khảo ngay KHÓA HỌC JAVA (Full stack) ngay!



---
HỌC VIỆN ĐÀO TẠO CNTT NIIT - ICT HÀ NỘI
Học Lập trình chất lượng cao (Since 2002). Học làm Lập trình viên. Hành động ngay!
Đc: Tầng 3, 25T2, N05, Nguyễn Thị Thập, Cầu Giấy, Hà Nội
SĐT: 02435574074 - 0914939543
Email: hello@niithanoi.edu.vn
Fanpage: https://facebook.com/NIIT.ICT/
 
#niit #niithanoi #niiticthanoi #hoclaptrinh #khoahoclaptrinh #hoclaptrinhjava #hoclaptrinhphp #java #php #python
Bình luận Facebook
Đăng ký tư vấn
Nhân viên gọi điện tư vấn miễn phí sau khi đăng ký
Được cập nhật các ưu đãi sớm nhất
Hotline: 0383180086
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Hãy đăng ký để nhận những thông tin mới nhất về học bổng mới nhất tại NIIT - ICT Hà Nội
top
Đóng lại Đăng ký học tại NIIT - ICT Hà Nội
6260+ học viên đã theo học tại NIIT - ICT Hà Nội và có việc làm tốt trong ngành lập trình. Nắm lấy cơ hội ngay hôm nay!
Chọn khóa học
  • KHÓA HỌC LẬP TRÌNH FRONT END VỚI REACT.JS
  • KHÓA HỌC LẬP TRÌNH PHP WEB
  • Khóa học PHP Full stack [2023] cho người mới bắt đầu
  • Khóa học BIG DATA với Hadoop và Spark
  • Khóa học Lập trình Android tại Hà Nội
  • [Tuyển sinh 2023] Lập trình viên Quốc tế DigiNxt
  • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại Hà Nội
  • LẬP TRÌNH GAME
    • Khóa học Lập trình Game Unity
  • LẬP TRÌNH WEB FRONT END
    • KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG
    • KHÓA HỌC ANGULAR & TYPESCRIPT (FRONT END)
  • LẬP TRÌNH WEB BACK END
    • LẬP TRÌNH JAVA WEB VỚI FRAME WORK
    • Lập trình Web với Django
    • Lập trình PHP với Laravel Framework
  • CHƯƠNG TRÌNH ĐÀO TẠO ỨNG DỤNG CÔNG NGHỆ
    • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại TP HCM
  • LẬP TRÌNH WEB FULL STACK
    • Khóa học Java Full stack (IJFD)
  • LẬP TRÌNH MOBILE
    • FRONT-END VỚI REACTJS VÀ REACT NATIVE
    • Lập trình Android Nâng cao
  • ĐÀO TẠO CHO DOANH NGHIỆP
    • KHÓA HỌC BUSINESS ANALYSIC TỪ CƠ BẢN ĐẾN NÂNG CAO 2023
    • Khóa học Magento: Làm chủ CMS TMĐT lớn nhất
    • Khóa học IOT: Xây dựng Sản phẩm IOT với Raspberry Pi
    • Khóa học Automation Testing Chuyên nghiệp
  • KHÓA HỌC DỰ ÁN
    • Học sử dụng bộ Office: Word, Excel, Power Point, Mail chuyên nghiệp
  • KHÓA HỌC KHÁC
    • VBA Excel Toàn Tập (Cơ Bản - Nâng Cao)
    • VBA Excel Nâng cao
    • Khóa học JMeter: Performance Testing
    • Khóa học Tester đạt chuẩn Quốc tế ISTQB Foundation Level
    • Khoá Học Tester đạt chuẩn quốc tế ISTQB Advanced Level
Bạn chưa chọn khóa học cần đăng ký
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Đăng ký học thành công!
Cảm ơn bạn đã đăng ký học tại NIIT - ICT HÀ NỘI!