C++: Tìm kiếm nhị phân (Binary Search)
Giải phóng thời gian, khai phóng năng lực
Tổng quan
Tìm kiếm nhị phân là một trong những thuật toán khá phổ biến để có thể tìm một phần tử nào đó trong mảng.
Lưu ý: Thuật toán chỉ có tác dụng khi mảng đã được sắp xếp theo một trật tự nào đó (tăng hoặc giảm).
So với thuật toán tìm kiếm tuần tự (linear search) thì độ phức tạp thuật toán của tìm kiếm nhị phân nhỏ hơn khá nhiều. Vậy nên, tìm kiếm nhị phân có thể áp dụng cho mảng dữ liệu lớn.
Cách thức triển khai thuật toán tìm kiếm nhị phân như sau:
Cần tìm phần tử x nào đó có tồn tại trong mảng arr gồm n phần tử thì trước tiên ta tiến hành so sánh x với phần tử nằm ở vị trí chính giữa của mảng (vị trí index = n/2):
- nếu x bằng arr[index] thì trả về index và kết thúc tìm kiếm,
- nếu x < arr[index] thì chắc chắn x sẽ nằm ở phía bên trái của index tức là từ arr[0] đến arr[index-1],
- nếu x > arr[mid] thì chắc chắn x sẽ nằm ở phía bên phải của index tức là từ arr[mid+1] đến arr[n-1].
- tiếp tục thực hiện chia đôi các khoảng tìm kiếm tới khi nào tìm thấy được vị trí của x trong mảng hoặc khi đã duyệt hết mảng.
Độ phực tạp của thụât toán tìm kiếm nhị phân trong trường hợp tốt nhất là O(1), trong trường hợp xấu nhất là O(log2n) và trung bình là O(log2n).
Ví dụ
Hãy nhập vào mảng arr gồm n phần tử thực, sau đó nhập vào một số x rồi tìm xem mảng arr có phần tử nào có giá trị = x hay không.
#include <bits/stdc++.h> using namespace std; //Định nghĩa hàm nhập kích thước mảng: int nhapN(){ int n; do{ cout<<"Moi nhap so luong phan tu: "; cin>>n; }while(n<1); return n; } //Định nghĩa hàm nhập dữ liệu mảng: void nhapMang(float arr[],int n){ cout<<"Moi nhap lieu cho mang:"<<endl; for(int i=0; i<n; i++){ cout<<"arr["<<i<<"] = "; cin>>arr[i]; } } //Hàm thực hiện thuật toán tìm kiếm nhi phân float binarySearch(float arr[], int n, float x) { //Trước tiên cần đặt left là chỉ số của phần //tử đầu tiên, right là chỉ số của phần tử //cuối cùng + 1 int left=0, right=n; //Biến để lưu lại vị trí tìm thấy int index; while(left <= right) { // lấy vị trí chính giữa của mảng: index = (left + right) / 2; // nếu phần từ ở giữa mảng bằng x thì trả về // index if (arr[index] == x) return index; // Nếu x lớn hơn phần tử ở giữa thì vị trí cần tìm // chắc chắn nằm bên phải. if (x > arr[index]) // Lúc này ta thực hiện chia đôi nửa bên phải // bằng cách gán left là index left = index; //Ngược lại thì vị trí cần tìm chắc chẳn ở bên trái else // Lúc này ta thực hiện chia đôi nửa bên trái // bằng cách gán right là index right = index; } //Trả về -1 nếu không tìm thấy vị trí nào. return -1; } int main() { int n; n=nhapN(); //Nhập kích thước mảng float arr[n]; nhapMang(arr,n); //Nhập liệu cho mảng //Tiến hành sắp xếp trước: //Hàm sort sẽ sắp xếp mảng tăng dần sort(arr,arr+n); cout<<"Sau khi sap xep tang dan, ta duoc ket qua:"<<endl; for(int i=0; i<n; i++) cout<<"arr["<<i<<"] = "<<arr[i]<<endl; float x; cout<<"Moi nhap so can tim: "; cin>>x; //Nhập số cần tìm //Rồi mới tiến hành tìm kiếm nhị phân int index = binarySearch(arr, n, x); if(index==-1) cout<<"Khong tim thay phan tu nao co gia tri "<<x<<endl; else cout<<"Tim thay phan tu tai vi tri chi so "<<index; return 0; }
Dưới đây là một kết quả demo:
Moi nhap so luong phan tu: 10
Moi nhap lieu cho mang:
arr[0] = 1
arr[1] = 5
arr[2] = 3
arr[3] = 2
arr[4] = 4
arr[5] = 7
arr[6] = 6
arr[7] = 9
arr[8] = 8
arr[9] = 0
Sau khi sap xep tang dan, ta duoc ket qua:
arr[0] = 0
arr[1] = 1
arr[2] = 2
arr[3] = 3
arr[4] = 4
arr[5] = 5
arr[6] = 6
arr[7] = 7
arr[8] = 8
arr[9] = 9
Moi nhap so can tim: 9
Tim thay phan tu tai vi tri chi so 9
Giải phóng thời gian, khai phóng năng lực