✨Tìm kiếm nhị phân

Tìm kiếm nhị phân

Trong khoa học máy tính, tìm kiếm nhị phân (), còn gọi là tìm kiếm nửa khoảng (half-interval search), tìm kiếm logarit (logarithmic search), hay chặt nhị phân (binary chop), là một thuật toán tìm kiếm xác định vị trí của một giá trị cần tìm trong một mảng đã được sắp xếp. Thuật toán tiến hành so sánh giá trị cần tìm với phần tử đứng giữa mảng. Nếu hai giá trị không bằng nhau, phần nửa mảng không chứa giá trị cần tìm sẽ bị bỏ qua và tiếp tục tìm kiếm trên nửa còn lại, một lần nữa lấy phần tử ở giữa và so sánh với giá trị cần tìm, cứ thế lặp lại cho đến khi tìm thấy giá trị đó. Nếu phép tìm kiếm kết thúc khi nửa còn lại trống thì giá trị cần tìm không có trong mảng.

Tìm kiếm nhị phân chạy theo thời gian logarit trong trường hợp tệ nhất, thực hiện O(\log n) bước so sánh, trong đó n là số phần tử trong mảng, O là kí hiệu O lớn, và \log là phép toán logarit. Thuật toán tìm kiếm nhị phân nhanh hơn so với tìm kiếm tuyến tính, ngoại trừ các trường hợp mảng có kích thước nhỏ. Tuy nhiên, mảng phải được sắp xếp trước khi áp dụng tìm kiếm nhị phân. Một số cấu trúc dữ liệu chuyên dụng được thiết kế cho việc tìm kiếm nhanh, ví dụ như bảng băm, có thể thực hiện tìm hiệu quả hơn tìm kiếm nhị phân. Tuy nhiên, thuật toán này có thể dùng để giải quyết nhiều loại vấn đề hơn, như tìm phần tử nhỏ nhất hoặc lớn nhất tiếp theo trong mảng so với giá trị cho trước, kể cả khi nó không có trong mảng.

Có nhiều biến thể của phép tìm kiếm nhị phân. Cụ thể, phương pháp "đổ xuống một phần" (fractional cascading) giúp tăng tốc tìm kiếm nhị phân với cùng một giá trị trong nhiều mảng. Phương pháp này cho phép giải quyết hiệu quả một số vấn đề về tìm kiếm trong hình học tính toán và nhiều lĩnh vực khác. Thuật toán tìm kiếm mũ (exponential search) mở rộng tìm kiếm nhị phân sang các danh sách không có giới hạn. Các cấu trúc dữ liệu cây tìm kiếm nhị phân và B-cây được xây dựng dựa trên tìm kiếm nhị phân.

Thuật toán

Thuật toán tìm kiếm nhị phân hoạt động trên các mảng đã được sắp xếp. Thuật toán bắt đầu bằng việc so sánh một phần tử đứng chính giữa mảng với giá trị cần tìm. Nếu bằng nhau, vị trí của nó trong mảng sẽ được trả về. Nếu giá trị cần tìm nhỏ hơn phần tử này, quá trình tìm kiếm tiếp tục ở nửa nhỏ hơn của mảng. Nếu giá trị cần tìm lớn hơn phần tử ở giữa, quá trình tìm kiếm tiếp tục ở nửa lớn hơn của mảng. Bằng cách này, ở mỗi phép lặp thuật toán có thể loại bỏ nửa mảng mà giá trị cần tìm chắc chắn không xuất hiện.

Quy trình

Cho một mảng An phần tử với các giá trị hoặc bản ghi A_0,A_1,A2,\ldots,A{n-1}đã được sắp xếp sao cho A_0 \leq A_1 \leq A2 \leq \cdots \leq A{n-1}, và giá trị cần tìm T, chương trình con sau đây sử dụng tìm kiếm nhị phân để tìm chỉ số của T trong A.

Gán L với giá trị 0

R với giá trị n-1. # Nếu L>R, quá trình tìm kiếm thất bại. # Gán m (vị trí của phần tử đứng giữa) với giá trị floor của \frac{L+R}{2}, tức là số nguyên lớn nhất nhỏ hơn hoặc bằng \frac{L+R}{2}. # Nếu A_m < T, gán L với m+1 và quay lại bước 2. # Nếu A_m > T, gán R với m-1 và quay lại bước 2. # Khi A_m = T, quá trình tìm kiếm hoàn tất; trả về m.

Quy trình lặp này dùng hai biến LR để lưu giới hạn tìm kiếm. Quy trình này có thể diễn giải bằng mã giả như dưới đây, trong đó tên các biến và kiểu giữ nguyên so với như trên, floor là hàm floor, và không_thành_công là một giá trị cụ thể thông báo tìm kiếm thất bại.

function binary_search(A, n, T) is L:= 0 R:= n − 1 while L ≤ R do m:= floor((L + R) / 2) if A[m] < T then L:= m + 1 else if A[m] > T then R:= m - 1 else: return m return không_thành_công

Ngoài ra, thuật toán có thể lấy giá trị ceiling của \frac{L+R}{2}. Điều này có thể thay đổi kết quả nếu giá trị cần tìm xuất hiện nhiều hơn một lần trong mảng.

Cách làm khác

Trong quy trình trên, thuật toán kiểm tra phần tử ở giữa (m) có bằng giá trị cần tìm (T) không ở mỗi phép lặp. Một số cách làm bỏ qua bước này ở mỗi phép lặp. Khi đó thuật toán chỉ kiểm tra điều này khi chỉ còn một phần tử còn lại (khi L=R). Nhờ đó mà vòng lặp so sánh được thực hiện nhanh hơn do mỗi phép lặp đã loại bỏ được một bước so sánh. Tuy nhiên, với cách làm này thì số phép lặp trung bình tăng lên.

Hermann Bottenbruch cho xuất bản cách áp dụng đầu tiên bỏ qua bước kiểm tra này vào năm 1962. Do đó, độ phức tạp không gian của tìm kiếm nhị phân là O(\log n). Ngoài ra, thuật toán còn cần O(n) không gian để lưu trữ mảng.

Trường hợp trung bình

Số phép lặp trung bình được thực hiện bởi thuật toán tùy thuộc vào xác suất mỗi phần tử được thực hiện tìm kiếm. Trường hợp trung bình khi tìm kiếm thành công và không thành công là khác nhau. Ta giả sử mỗi phần tử có xác suất được tìm như nhau nếu tìm kiếm thành công. Nếu tìm kiếm không thành công, ta giả sử các khoảng giữa và ngoài các phần tử có xác suất được tìm giống nhau. Trường hợp trung bình khi tìm kiếm thành công là số phép lặp cần thực hiện để tìm mọi phần tử chính xác một lần, chia cho n, số phần tử trong mảng. Trường hợp trung bình khi tìm kiếm không thành công là số phép lặp cần thực hiện để tìm một phần tử trong mọi khoảng chính xác một lần, chia cho n + 1 khoảng.

Tìm kiếm thành công

Khi biểu diễn bằng cây nhị phân, một lần tìm kiếm thành công có thể được biểu diễn bằng một đường đi từ gốc tới nút cần tìm, gọi là đường đi trong (internal path). Độ dài của một đường đi là số cạnh (đường nối giữa các nút) mà đường đó đi qua. Số phép lặp mà một lần tìm kiếm thực hiện, với điều kiện độ dài của đường đi tương ứng với lần tìm đó là l, là l + 1 tính cả phép lặp ban đầu. Độ dài đường đi trong (internal path length) là tổng độ dài tất cả các đường đi trong. Do chỉ có một đường đi duy nhất từ gốc tới bất cứ nút nào, mỗi đường trong đó biểu diễn cho một phép tìm kiếm phần tử tương ứng. Nếu có n phần tử, và độ dài đường trong là I(n), thì số phép lặp trung bình cho một lần tìm kiếm thành công là T(n) = 1 + \frac{I(n)}{n}, trong đó đã cộng thêm một bước lặp ở đầu.

Do tìm kiếm nhị phân là thuật toán tối ưu cho việc tìm kiếm bằng cách so sánh, bài toán được đơn giản hóa thành việc tính độ dài đường đi trong tối thiểu của tất cả cây nhị phân có n nút, tức là bằng:

I(n) = \sum_{k=1}^n \left \lfloor \log_2(k) \right \rfloor

Ví dụ, với một mảng 7 phần tử, phần tử gốc cần một phép lặp, hai phần tử bên dưới gốc cần hai phép lặp, và bốn phần tử dưới nữa gần ba phép lặp. Trong trường hợp này, độ dài đường đi trong là:

\sum_{k=1}^7 \left \lfloor \log_2(k) \right \rfloor = 0 + 2(1) + 4(2) = 2 + 8 = 10

Số phép lặp trung bình sẽ là 1 + \frac{10}{7} = 2 \frac{3}{7} dựa theo công thức với trường hợp trung bình. Tổng I(n) có thể rút gọn thành:

I(n) = \sum_{k=1}^n \left \lfloor \log_2(k) \right \rfloor = (n + 1)\left \lfloor \log_2(n + 1) \right \rfloor - 2^{\left \lfloor \log_2(n+1) \right \rfloor + 1} + 2

Thay I(n) vào phương trình T(n):

T(n) = 1 + \frac{(n + 1)\left \lfloor \log_2(n + 1) \right \rfloor - 2^{\left \lfloor \log_2(n+1) \right \rfloor + 1} + 2}{n} = \lfloor \log_2 (n) \rfloor + 1 - (2^{\lfloor \log_2 (n) \rfloor + 1} - \lfloor \log_2 (n) \rfloor - 2)/n

Với n là một số nguyên, phương trình trên tương đương với phương trình trong trường hợp trung bình cho một lần tìm kiếm thành công như đã chỉ ra ở trên.

Tìm kiếm không thành công

Ta có thể biểu diễn lần tìm kiếm không thành công bằng cách thêm vào cây các nút ngoài, tạo thành cây nhị phân mở rộng. Nếu một nút trong, hoặc một nút có trong cây, có ít hơn hai nút con, thì ta sẽ thêm vào các nút con bổ sung, gọi là các nút ngoài, để mỗi nút trong đều có hai nút con. By doing so, an unsuccessful search can be represented as a path to an external node, whose parent is the single element that remains during the last iteration. Đường đi ngoài (external path) là đường đi từ gốc đến một nút ngoài. Độ dài đường đi ngoài (external path length) là tổng độ dài tất cả đường đi ngoài unique. Nếu số phần tử là n (n là số nguyên dương), và độ dài đường đi ngoài là E(n), thì số phép lặp trung bình cho một lần tìm kiếm không thành công là T'(n)=\frac{E(n)}{n+1}, trong đó đã tính một phép lặp lúc đầu. Trong công thức này, ta lấy độ dài đường đi ngoài chia cho n+1 chứ không phải n vì có n+1 đường đi ngoài biểu diễn cho các khoảng giữa và ngoài các phần tử trong mảng.

Tương tự, bài toán này có thể đơn giản hóa thành bài toán tính độ dài đường đi ngoài tối thiếu của tất cả cây nhị phân có n nút. Với tất cả các cây nhị phân, độ dài đường đi ngoài bằng độ dài đường đi trong cộng với 2n. Thay I(n) vào ta có:

E(n) = I(n) + 2n = \left[(n + 1)\left \lfloor \log_2(n + 1) \right \rfloor - 2^{\left \lfloor \log_2(n+1) \right \rfloor + 1} + 2\right] + 2n = (n + 1) (\lfloor \log_2 (n) \rfloor + 2) - 2^{\lfloor \log_2 (n) \rfloor + 1}

Thay E(n) vào công thức tính T'(n), ta có thể xác định trường hợp trung bình cho những lần tìm kiếm không thành công:

T'(n) = \frac{(n + 1) (\lfloor \log_2 (n) \rfloor + 2) - 2^{\lfloor \log_2 (n) \rfloor + 1{(n+1)} = \lfloor \log_2 (n) \rfloor + 2 - 2^{\lfloor \log_2 (n) \rfloor + 1}/(n + 1)

Hiệu suất của các cách thay thế

Mỗi phép lặp trong cách tìm kiếm nhị phân trên thực hiện một hoặc hai lần so sánh để kiểm tra phần tử ở giữa có bằng với giá trị cần tìm không. Giả sử mỗi phần tử có xác suất được tìm bằng nhau, mỗi phép lặp thực hiện trung bình 1,5 lần so sánh. Một cách làm khác của thuật toán sẽ thực hiện kiểm tra phần tử giữa ở cuối mỗi lần tìm kiếm. Theo cách này, trung bình mỗi phép lặp bỏ qua 0,5 lần so sánh, tiết kiệm thời gian hơn một chút trên mỗi phép lặp ở hầu hết các loại máy tính. Tuy nhiên, cách này lại khiến mỗi lần tìm kiếm luôn phải thực hiện số phép lặp tối đa, trung bình mỗi lần tìm cộng thêm một phép lặp. Vì vòng lặp so sánh chỉ được thực hiện \lfloor \log_2 (n) + 1 \rfloor lần trong trường hợp tệ nhất, việc tăng nhẹ hiệu suất ở mỗi phép lặp không thể bù lại cho phép lặp cần thực hiện thêm khi n không lớn.

Thời gian chạy và mức sử dụng cache

Trong quá trình phân tích hiệu suất của thuật toán, một vấn đề khác cần lưu ý là thời gian cần để so sánh hai phần tử. Với các số nguyên và chuỗi ký tự, khoảng thời gian này tăng tuyến tính do độ dài mã hóa (thường là số bit) của các phần tử tăng theo. Ví dụ, một cặp số nguyên dương 64 bit sẽ cần phải so sánh số bit gấp đôi so với một cặp số nguyên dương 32 bit. Trường hợp tệ nhất được đạt đến khi hai số nguyên bằng nhau. Điều này có thể đáng lưu tâm khi độ dài mã hóa của các phần tử ở mức lớn, ví dụ như khi so sánh các số thuộc kiểu nguyên lớn hơn hay so sánh các chuỗi ký tự dài, khiến cho việc so sánh rất tốn thời gian. Hơn nữa, so với các số nguyên hoặc chuỗi ký tự ngắn thì so sánh các giá trị dấu phẩy động (cách biểu diễn số thông dụng nhất của số thực) thường còn tốn thời gian hơn..

Trên hầu hết các kiểu kiến trúc máy tính, bộ vi xử lý có bộ nhớ cache riêng tách biệt khỏi RAM. Do nằm ngay trong bộ xử lý, bộ nhớ cache có thể truy cập nhanh hơn nhưng thường chỉ chứa được ít dữ liệu hơn RAM. Do đó, hầu hết các bộ xử lý lưu địa chỉ những vùng bộ nhớ đã được truy cập gần đây và cả những vùng bộ nhớ xung quanh chúng. Ví dụ, khi truy cập vào một phần tử trong mảng, phần tử này, cùng với cả những phần tử được lưu gần đó, có thể được lưu vào trong RAM để sau đó có thể truy cập nhanh hơn được vào các phần tử khác liền kề (tính địa phương trong truy xuất - locality of reference). Với một mảng đã sắp xếp, quá trình tìm kiếm nhị phân có thể phải nhảy sang các vùng bộ nhớ nằm xa nếu mảng có kích thước lớn, không giống như các thuật toán (như tìm kiếm tuyến tính hay dò tuyến tính trong bảng băm) truy cập các phần tử theo thứ tự lần lượt. Điều này làm thời gian chạy của thuật toán tăng lên đôi chút với các mảng lớn trên hầu hết các hệ thống.

Tìm kiếm nhị phân với các hệ thống khác

Áp dụng tìm kiếm nhị phân với các mảng đã được sắp xếp là một giải pháp rất không hiệu quả khi xen giữa các phép chèn và xóa còn là các phép truy hồi, mỗi thao tác đó phải mất O(n) thời gian để thực hiện. Ngoài ra, yêu cầu phải sắp xếp trước các mảng có thể làm phức tạp việc sử dụng bộ nhớ, đặc biệt là khi các phần tử thường được chèn vào trong mảng. Một số cấu trúc dữ liệu khác có thể hỗ trợ các thao tác chèn và xóa hiệu quả hơn nhiều. Tìm kiếm nhị phân có thể được dùng để thực hiện so khớp chính xác và thao tác quan hệ tập hợp (xác định giá trị cần tìm có phải là một tập hợp nhiều giá trị không). Hai bài toán này cũng có thể được thực hiện nhanh hơn trên các cấu trúc dữ liệu khác. Tuy nhiên, khác với các hệ thống tìm kiếm khác, tìm kiếm nhị phân hiệu quả hơn trong phép so khớp xấp xỉ, thường chỉ thực hiện trong O(\log n) thời gian bất kể kiểu hay cấu trúc của các giá trị. Ngoài ra còn có một số phép toán, như tìm phần tử nhỏ nhất và lớn nhất, có thể được thực hiện hiệu quả trên mảng đã được sắp xếp.

Tìm kiếm tuyến tính

Tìm kiếm tuyến tính là một thuật toán tìm kiếm đơn giản: nó kiểm tra mọi bản ghi cho tới khi tìm thấy giá trị cần tìm. Tìm kiếm tuyến tính có thể được thực hiện trên danh sách liên kết, cho phép các thao tác chèn và xóa nhanh hơn so với mảng. Tìm kiếm nhị phân nhanh hơn tìm kiếm tuyến tính trên các mảng đã được sắp xếp trừ khi mảng có kích thước nhỏ, mặc dù trước khi tìm kiếm cần phải thực hiện sắp xếp lại mảng trước. Tất cả các thuật toán sắp xếp dựa trên thao tác so sánh các phần tử, như sắp xếp nhanh và sắp xếp trộn, cần ít nhất O(n \log n) phép so sánh trong trường hợp tệ nhất. Khác với tìm kiếm tuyến tính, tìm kiếm nhị phân có thể được ứng dụng để tìm so khớp xấp xỉ một cách hiệu quả. Một số thao tác như tìm phần tử nhỏ nhất và lớn nhất có thể được thực hiện hiệu quả chỉ khi mảng đã được sắp xếp.

Cây

thumb|upright=1.0|Phép tìm kiếm trên [[cây tìm kiếm nhị phân sử dụng một thuật toán tương tự tìm kiếm nhị phân.]]

Cây tìm kiếm nhị phân là một cấu trúc dữ liệu dạng cây nhị phân hoạt động dựa trên nguyên lý của tìm kiếm nhị phân. Các bản ghi trong cây được biểu diễn theo thứ tự đã được sắp xếp, và mỗi bản ghi có thể được tìm bằng một thuật toán tương tự tìm kiếm nhị phân, thực hiện trung bình theo thời gian logarit. Các phép chèn và xóa cũng cần trung bình thời gian logarit trong cây tìm kiếm nhị phân. Chúng có thể được thực hiện nhanh hơn so với các thao tác chèn và xóa theo thời gian tuyến tính trên các mảng đã được sắp xếp, đồng thời các thao tác có thể thực hiện trên mảng đã được sắp xếp cũng có thể được thực hiện trên cây nhị phân, bao gồm cả các phép truy vấn khoảng và truy vấn xấp xỉ. Tuy nhiên, việc băm có thể không hữu ích khi thực hiện các bài toán so khớp xấp xỉ, ví dụ như tính khóa nhỏ nhất tiếp theo, khóa lớn nhất tiếp theo và khóa gần nhất, do khi tìm kiếm thất bại, thông tin duy nhất được đưa ra là giá trị cần tìm không có trong bất cứ bản ghi nào. Tìm kiếm nhị phân là cách làm lý tưởng đối với những bài toán như vậy, khi chỉ thực hiện với thời gian chạy logarit. Tìm kiếm nhị phân cũng hỗ trợ so khớp xấp xỉ. Một số phép toán, như tìm phần tử nhỏ nhất và lớn nhất, có thể được thực hiện hiệu quả trên các mảng đã được sắp xếp, nhưng không thể trên bảng băm.

Nếu chỉ cần kết quả xấp xỉ, ta có thể sử dụng bộ lọc Bloom, một cấu trúc dữ liệu xác suất khác dựa trên hàm băm, lưu trữ một tập hợp các khóa bằng cách sử dụng một mảng bit và nhiều hàm băm để mã hóa các khóa. Các bộ lọc Bloom chiếm ít không gian hơn nhiều so với các mảng bit trong hầu hết mọi trường hợp và không hoạt động chậm hơn là bao: với k hàm băm, các phép truy vấn kiểm tra phần tử chỉ cần thời gian O(k). Tuy nhiên, sử dụng bộ lọc Bloom có thể đem kết quả dương tính giả.

Các cấu trúc dữ liệu khác

Còn có các cấu trúc dữ liệu khác có thể cải thiện tìm kiếm nhị phân trong một số trường hợp với cả mục đích tìm kiếm lẫn các thao tác khác có thể được thực hiện trên các mảng đã được sắp xếp. Ví dụ, các phép tìm kiếm, so khớp xấp xỉ và các thao tác khác trên mảng đã được sắp xếp có thể được thực hiện hiệu quả hơn tìm kiếm nhị phân nếu áp dụng trên các cấu trúc dữ liệu chuyên biệt như cây van Emde Boas, fusion trees, trie và mảng bit. Các cấu trúc dữ liệu chuyên biệt này thường chỉ nhanh hơn vì chúng sử dụng các tính chất của những khóa có điều kiện nhất định (thông thường những khóa này là các số nguyên nhỏ), và do đó thời gian chạy hoặc không gian cần sử dụng có thể lớn nếu không đáp ứng được các điều kiện ấy.

Trong thực tế, tìm kiếm nội suy chạy chậm hơn tìm kiếm nhị phân đối với các mảng nhỏ, do tìm kiếm nội suy cần nhiều tính toán hơn. Độ phức tạp thời gian của thuật toán này tăng chậm hơn so với tìm kiếm nhị phân, nhưng chỉ bù đắp được cho phần tính toán cộng thêm khi mảng có kích thước lớn.

Đổ xuống một phần

thumb|upright=2.5|Trong đổ xuống một phần, mỗi mảng chứa các con trỏ trỏ tới mỗi phần tử thứ hai của một mảng khác, do đó chỉ cần thực hiện một lần tìm kiếm nhị phân để tìm trong tất cả các mảng. Đổ xuống một phần là kỹ thuật nhằm làm tăng tốc tìm kiếm nhị phân với cùng một giá trị trong nhiều mảng khác nhau đã được sắp xếp. Nếu thực hiện tìm từng mảng tách riêng nhau ta phải cần O(k \log n) thời gian, trong đó k là số mảng. Phương pháp đổ xuống một phần làm giảm con số này xuống còn O(k + \log n) bằng cách lưu các thông tin cụ thể ở mỗi mảng về mỗi phần tử và vị trí của chúng ở các mảng khác.

Phương pháp đổ xuống một phần ban đầu được phát triển để giải quyết các bài toán trong hình học tính toán. Phương pháp này đã được áp dụng trong nhiều lĩnh vực khác, như khai phá dữ liệu và định tuyến giao thức Internet.

Tìm kiếm nhị phân nhiễu

thumb|upright=1.5|Trong tìm kiếm nhị phân nhiễu, chắc chắn tồn tại xác suất phép so sánh cho kết quả sai. Các thuật toán tìm kiếm nhị phân nhiễu (noisy binary search) có thể giải quyết các trường hợp mà thuật toán không thể so sánh chính xác các phần tử trong mảng. Ở mỗi cặp phần tử đều tồn tại một xác suất nhất định rằng thuật toán thực hiện sai phép so sánh. Tìm kiếm nhị phân nhiễu có thể tìm vị trí chính xác của giá trị cần tìm với một xác suất cho trước, nhằm kiểm soát độ chính xác của kết quả. Mỗi lần tìm kiếm nhị phân nhiễu phải thực hiện trung bình ít nhất (1 - \tau)\frac{\log_2 (n)}{H(p)} - \frac{10}{H(p)} phép so sánh, trong đó H(p) = -p \log_2 (p) - (1 - p) \log_2 (1 - p) là hàm entropy nhị phân và \tau là xác suất một lần tìm kiếm cho ra kết quả sai. Bài toán tìm kiếm nhị phân nhiễu có thể được coi là một trường hợp của trò chơi Rényi-Ulam, một biến thể của trò chơi Hai mươi câu hỏi trong đó các câu trả lời có thể sai.

Tìm kiếm nhị phân lượng tử

Các máy tính cổ điển khi thực hiện tìm kiếm nhị phân bị giới hạn số phép lặp ở mức \lfloor \log_2 n + 1 \rfloor trong trường hợp tệ nhất. Các thuật toán lượng tử dành cho tìm kiếm nhị phân vẫn chỉ bó buộc trong khoảng \log_2 n phép truy vấn (biểu diễn cho phép lặp trong trường hợp cổ điển), nhưng có hệ số nhỏ hơn một, do đó làm giảm độ phức tạp thời gian trên các máy tính lượng tử. Bất cứ thao tác tìm kiếm nhị phân lượng tử chính xác nào—tức là thao tác luôn cho kết quả đúng—cần ít nhất \frac{1}{\pi}(\ln n - 1) \approx 0.22 \log2 n phép truy vấn ở trường hợp tệ nhất, trong đó \ln là hàm logarit tự nhiên. Có một phương pháp tìm kiếm nhị phân lượng tử chính xác chạy trong 4 \log{605} n \approx 0.433 \log_2 n phép truy vấn ở trường hợp tệ nhất. So với các thuật toán khác, thuật toán Grover là thuật toán lượng tử tối ưu cho việc tìm kiếm trong một danh sách các phần tử chưa được sắp xếp, với O(\sqrt{n}) phép truy vấn.

Lịch sử

Ý tưởng về việc sắp xếp một danh sách để tìm kiếm được nhanh hơn đã có từ thời cổ xưa. Ví dụ được biết tới sớm nhất là tấm bảng của Inakibit-Anu từ thời Babylon vào . Tấm bảng này chứa khoảng 500 con số ở hệ thập lục phân và các số nghịch đảo của chúng được sắp xếp theo thứ tự từ điển, khiến việc tìm kiếm dễ dàng hơn. Ngoài ra trên Quần đảo Aegean còn phát hiện được một vài danh sách những cái tên được sắp xếp theo chữ cái đầu tiên. Catholicon, một cuốn từ điển Latin được hoàn thành vào năm 1286 SCN, là tác phẩm đầu tiên mô tả các quy tắc sắp xếp các từ theo thứ tự bảng chữ cái, thay vì chỉ theo vài ký tự đầu tiên.

Vào năm 1946, John Mauchly là người đầu tiên nhắc tới tìm kiếm nhị phân trong Moore School Lectures, một khóa học về máy tính tại Trường Kỹ thuật Điện tử Moore, Đại học Pennsylvania. Năm 1957, William Wesley Peterson xuất bản phương pháp đầu tiên cho giải thuật tìm kiếm nội suy. Mọi thuật toán tìm kiếm nhị phân đã được xuất bản chỉ hoạt động với các mảng có độ dài ở dạng 2^\alpha - 1 cho tới năm 1960, khi Derrick Henry Lehmer cho xuất bản một thuật toán tìm kiếm nhị phân có thể hoạt động với mọi mảng. Năm 1962, Hermann Bottenbruch trình bày thuật toán tìm kiếm nhị phân được áp dụng bằng ngôn ngữ ALGOL 60, trong đó bước kiểm tra phần tử giữa được đưa xuống cuối, làm tăng số phép lặp trung bình thêm một, nhưng giảm được một bước so sánh mỗi phép lặp.

Thư viện hỗ trợ

Nhiều thư viện chuẩn của các ngôn ngữ có các chương trình con thực hiện tìm kiếm nhị phân:

  • C cung cấp hàm bsearch() trong thư viện chuẩn, thường được triển khai bằng tìm kiếm nhị phân, mặc dù tiêu chuẩn chính thức không yêu cầu.
  • Standard Template Library của C++ cung cấp các hàm binary_search(), lower_bound(), upper_bound()equal_range().
  • COBOL cung cấp động từ SEARCH ALL có chức năng thực hiện tìm kiếm nhị phân trên các bảng được sắp xếp trong COBOL.
  • Gói thư viện chuẩn sort của Go cung cấp các hàm Search, SearchInts, SearchFloat64s, và SearchStrings, lần lượt có chức năng thực hiện tìm kiếm nhị phân tổng quát, tìm kiếm các lát số nguyên, số thập phân dấu phẩy động và chuỗi ký tự.
  • Java cung cấp một bộ các phương thức static chồng binarySearch() trong các lớp và chứa trong gói java.util chuẩn, lần lượt có chức năng thực hiện tìm kiếm nhị phân trên các mảng trong Java và trên các List.
  • Microsoft's .NET Framework 2.0 cung cấp các phiên bản static tổng quát của thuật toán tìm kiếm nhị phân trong các lớp collection base. Ví dụ như phương thức BinarySearch(T[] array, T value) trong System.Array
  • Với Objective-C, framework Cocoa cung cấp phương thức [https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html#//apple_ref/occ/instm/NSArray/indexOfObject:inSortedRange:options:usingComparator: NSArray -indexOfObject:inSortedRange:options:usingComparator:] trong Mac OS X từ bản 10.6 trở lên. Framework Core Foundation C của Apple cũng chứa hàm [https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFArrayRef/Reference/reference.html#//apple_ref/c/func/CFArrayBSearchValues CFArrayBSearchValues()].
  • Python cung cấp mô đun bisect.
  • Lớp Array của Ruby có chứa phương thức bsearch có cả chức năng so khớp xấp xỉ.

Ghi chú và tham khảo

👁️ 0 | 🔗 | 💖 | ✨ | 🌍 | ⌚
Trong khoa học máy tính, **tìm kiếm nhị phân** (), còn gọi là **tìm kiếm nửa khoảng** (_half-interval search_), **tìm kiếm logarit** (_logarithmic search_), hay **chặt nhị phân** (_binary chop_), là một thuật toán tìm
**Cây tìm kiếm nhị phân** (viết tắt tiếng Anh: BST - _Binary Search Tree_) là một cấu trúc dữ liệu rất thuận lợi cho bài toán tìm kiếm. Mỗi cây tìm kiếm nhị phân đều
Trong khoa học máy tính, **Phép quay** trên các cây nhị phân là một phép biến đổi làm thay đổi vai trò cha con giữa 2 nút trên cây. Có hai phép quay là quay
Trong ngành khoa học máy tính, một **giải thuật tìm kiếm** là một thuật toán lấy đầu vào là một bài toán và trả về kết quả là một lời giải cho bài toán đó,
Trong Khoa học máy tính **tìm kiếm tuần tự** (tiếng Anh _Sequential search_) hay **tìm kiếm tuyến tính** (tiếng Anh _linear search_) là một phương pháp tìm kiếm một phần tử cho trước trong một
thumbnail|right|upright=1.35|Đồ thị của dưới dạng là hàm của một số thực dương Trong toán học, **logarit nhị phân** () là lũy thừa mà số cần phải được nâng lên để được số , nghĩa là
thumb|Một chương trình tìm kiếm tài năng của trường Trung học St Ninian tại [[Glasgow, Scotland.]] Một **chương trình tìm kiếm tài năng** là một sự kiện nơi các thí sinh biểu diễn các tiết
thumb|Một cây nhị phân được gắn nhãn có kích thước là 9 và chiều cao là 3, với nút gốc có giá trị là 2. Cây trên không cân bằng và không được sắp xếp.
nhỏ| Để tìm kiếm một mục đã cho trong một danh sách theo thứ tự nhất định, có thể sử dụng cả thuật toán [[Tìm kiếm tuần tự|tìm kiếm nhị phân và tuyến tính (bỏ
Trong khoa học máy tính, **treap** và **cây tìm kiếm nhị phân ngẫu nhiên hóa** là hai dạng cấu trúc dữ liệu cây tìm kiếm nhị phân liên quan chặt chẽ đến nhau. Chúng lưu
**Cây splay** là một cây tìm kiếm nhị phân tự cân bằng. Nó có thực hiện các thao tác cơ bản như chèn, tìm, và xóa trong thời gian trừ dần O(log n). Với nhiều
Máy đo nhịp tim em bé này là một thiết bị sản khoa cầm tay, có thể được sử dụng trong bệnh viện, phòng khám và nhà để tự kiểm tra nhịp tim thai nhi
Một **đống nhị phân** là một cấu trúc dữ liệu đống dựa trên cây nhị phân. Đống nhị phân thường được sử dụng để triển khai hàng đợi ưu tiên. Đống nhị phân được giới
**Hệ nhị phân** (hay **hệ đếm cơ số hai** hoặc ** mã nhị phân**) là một hệ đếm dùng hai ký tự để biểu đạt một giá trị số, bằng tổng số các lũy thừa
nhỏ|315x315px|Một danh bạ điện thoại nhỏ được xem như một bảng băm. Trong khoa học máy tính, **bảng băm** là một cấu trúc dữ liệu sử dụng hàm băm để ánh xạ từ giá trị
**_Tìm kiếm Tài năng Úc - Australia's Got Talent_** là một truyền hình thực tế chương trình tài năng của Úc. Chương trình dựa trên định dạng chuỗi _ Got Talent_ bắt nguồn từ Vương
Trong phát sinh chủng loại học, **khóa** **lưỡng phân** (tiếng Anh: **single-access key**, **dichotomous key**, **sequential key**, **analytical key**, **pathway key**) là khóa nhận dạng (_Identification key_) trong đó trình tự và cấu trúc của
Thất kiếm anh hùng là bộ phim hoạt hình do Trung Quốc dựa theo bộ phim cùng tên do hai nhà làm phim Trung Quốc là Vương Hồng và Hạ Mộng Phàm dựng lên, dựa
thế=Các quốc gia đã gửi thông điệp chia buồn, viện trợ nhân đạo sau trận động đất Thổ Nhĩ Kỳ–Syria 2023.|nhỏ|Các quốc gia/vùng lãnh thổ đã gửi thông điệp chia buồn, viện trợ nhân đạo
**_Thư kiếm ân cừu lục_** (書劍恩仇錄) là một tiểu thuyết võ hiệp của nhà văn Kim Dung, được đăng trên _Tân vãn báo_ của Hồng Kông từ ngày 8 tháng 2 năm 1955 đến ngày
Mô tảHàng mới 100% và chất lượng caoMàu sắc: Như hình ảnh hiển thịDOPPLER thai nhi bỏ túi là một thiết bị sản khoa cầm tay, áp dụng cho bệnh viện, phòng khám và nhà
**Tim Mực** (Tiếng Đức: _Tintenherz_) là cuốn tiểu thuyết giả tưởng dành cho trẻ em của Cornelia Funke, cuốn sách đầu tiên của bộ ba Inkworld. Tim mực là câu chuyện kể về Motimer (Mo)
**Mai Hồng Ngọc** (sinh ngày 13 tháng 10 năm 1988), thường được biết đến với nghệ danh **Đông Nhi**, là một nữ ca sĩ, nhạc sĩ, nhà sản xuất thu âm kiêm diễn viên người
**Nhịp tim** là tốc độ nhịp tim đo bằng số lần co thắt (nhịp đập) của tim mỗi phút (bpm - beat per minute). Nhịp tim có thể thay đổi theo nhu cầu thể chất
**Động đất Thổ Nhĩ Kỳ – Syria 2023**, hay **Trận động đất ở Thổ Nhĩ Kỳ và Syria** (theo cách gọi của báo chí), là hai trận động đất xảy ra ở miền nam và
Thông tin sản phẩm Chế độ sản phẩm: FD-270B Đầu dò tần số:2. 0 MHz Tỷ lệ phạm vi hiển thị:50-230Bpm Phạm vi lỗi:± 2bpm Ngày Hiệu Quả:5 năm Kích thước:14 Cm(L) * 10.5 Cm(W)
Thông tin sản phẩm Chế độ sản phẩm: FD-270B Đầu dò tần số:2. 0 MHz Tỷ lệ phạm vi hiển thị:50-230Bpm Phạm vi lỗi:± 2bpm Ngày Hiệu Quả:5 năm Kích thước:14 Cm(L) * 10.5 Cm(W)
Thông tin sản phẩm Chế độ sản phẩm: FD-270C Đầu dò tần số:2. 0 MHz Tỷ lệ phạm vi hiển thị:50-230Bpm Phạm vi lỗi:± 2bpm Ngày Hiệu Quả:5 năm Kích thước:14 Cm(L) * 10.5 Cm(W)
Thông tin sản phẩm Chế độ sản phẩm: FD-270G Đầu dò tần số:2. 0 MHz Tỷ lệ phạm vi hiển thị:50-230Bpm Phạm vi lỗi:± 2bpm Ngày Hiệu Quả:5 năm Kích thước:14Cm(L) * 10.5Cm(W) * 3Cm(H)
Phần mềm là các lệnh được lập trình mà được lưu trữ trong bộ nhớ được lưu trữ của các máy tính kỹ thuật số để bộ xử lý thực hiện. Phần mềm là một
Thông tin sản phẩm Chế độ sản phẩm: FD-270B Đầu dò tần số:2. 0 MHz Tỷ lệ phạm vi hiển thị:50-230Bpm Phạm vi lỗi:± 1bpm Ngày Hiệu Quả:5 năm Kích cỡ:14Cm(L) * 10.5Cm(W) * 3Cm(H)
Thông tin sản phẩm Chế độ sản phẩm: FD-270B Đầu dò tần số:2. 0 MHz Tỷ lệ phạm vi hiển thị:50-230Bpm Phạm vi lỗi:± 1bpm Ngày Hiệu Quả:5 năm Kích cỡ:14Cm(L) * 10.5Cm(W) * 3Cm(H)
Thông tin sản phẩm Chế độ sản phẩm: FD-270B Đầu dò tần số:2. 0 MHz Tỷ lệ phạm vi hiển thị:50-230Bpm Phạm vi lỗi:± 1bpm Ngày Hiệu Quả:5 năm Kích cỡ:14Cm(L) * 10.5Cm(W) * 3Cm(H)
**Đại chiến Thổ Nhĩ Kỳ** (Tiếng Đức: _Großer Türkenkrieg_), còn được gọi là **Chiến tranh Liên đoàn Thần thánh** (Tiếng Thổ Nhĩ Kỳ: _Kutsal İttifak Savaşları_), là một loạt các cuộc xung đột giữa Đế
liên_kết=https://en.wikipedia.org/wiki/File:ClamTk_5.27.png|nhỏ|300x300px|[[ClamTk, một phần mềm diệt vi-rút mã nguồn mở dựa trên công cụ diệt virus ClamAV, ban đầu được Tomasz Kojm phát triển vào năm 2001.]] nhỏ|255x255px|Ảnh chụp giao diện phần mềm diệt virus có
Nhiều nguồn tin cho biết TikTok đang kiểm duyệt nội dung chính trị liên quan đến Trung Quốc và một số quốc gia khác, cũng như các nội dung do người dùng thiểu số tạo
**Van tim** là những lá mỏng, mềm dẻo, được cấu tạo bởi tổ chức liên kết được bao quanh bởi nội tâm mạch. Van tim quyết định hướng chảy tuần hoàn máu theo một chiều
**Phẫu thuật tim** (còn gọi là phẫu thuật lồng ngực) là lĩnh vực y khoa liên quan đến phẫu thuật điều trị các cơ quan bên trong lồng ngực (ngực). Điều trị chung các tình
nhỏ| Một sơ đồ cho thấy cách người dùng tương tác với [[phần mềm ứng dụng trên một máy tính để bàn thông thường. Lớp phần mềm ứng dụng giao tiếp với hệ điều hành,
Quốc hội Trung Quốc đã bỏ phiếu cho các luật về kiểm duyệt thông tin trên mạng Internet. Với luật này, chính quyền Trung Quốc đã sử dụng nhiều biện pháp khác nhau để thực
Mối **quan hệ ngoại giao Thổ Nhĩ Kỳ - Israel** được thiết lập tháng 3 năm 1949 khi Thổ Nhĩ Kỳ trở thành quốc gia đa số người Hồi giáo đầu tiên (trước Iran vào
Bánh gạo mầm tím than là một lựa chọn dinh dưỡng tuyệt vời cho những ai đang tìm kiếm một loại thực phẩm vừa ngon miệng vừa có lợi cho sức khỏe.Bánh gạo mầm tím
Bánh gạo mầm tím than là một lựa chọn dinh dưỡng tuyệt vời cho những ai đang tìm kiếm một loại thực phẩm vừa ngon miệng vừa có lợi cho sức khỏe.Bánh gạo mầm tím
Thổ Nhĩ Kỳ là thành viên sáng lập của OECD và G20, đồng thời được xếp vào nhóm các quốc gia E7 , EAGLEs và NIC. Tính đến năm 2023, nền kinh tế Thổ Nhĩ
Đây là danh sách các phản ứng đối với các cuộc biểu tình chống dự luật dẫn độ năm 2019 tại Hồng Kông. ## Phản ứng quốc tế Trước các cuộc biểu tình đang diễn
Sản phẩmTHÔNG SỐ Thương hiệu:Cofoe y tếKhớp nối siêu âm Đặc điểm kỹ thuật: 250ml Ngày sản xuất: tháng 11 năm 2019 Ngày hết hạn: tháng 11 năm 2022 Cách sử dụng: Bóp một lượng
Sản phẩmThông số Nhãn hiệu: cofoe medicalultrasonic couplant Đặc điểm kỹ thuật: 250ml Ngày sản xuất: tháng 11 năm 2019 Ngày hết hạn: tháng 11 năm 2022 Cách sử dụng: Bóp một lượng thích hợp
Một **bản phân phối ****Linux** (thường được gọi tắt là **distro**) là một hệ điều hành được tạo dựng từ tập hợp nhiều phần mềm dựa trên hạt nhân Linux và thường có một hệ
Một đồ thị với ba thành phần liên thông. Trong lý thuyết đồ thị, một **thành phần liên thông** của một đồ thị vô hướng là một đồ thị con trong đó giữa bất kì
MÔ TẢ SẢN PHẨMBESTSALE - Váy hoa nhí đỏ dáng chữ A mặc đi biển cực nổi bật❤️Thông tin sản phẩm : - Váy hoa nhí đỏ vải nhập qc cực đẹp lên dáng cực