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 A có n phần tử với các giá trị hoặc bản ghi A_0,A_1,A_2,\ldots,A_{n-1}đã được sắp xếp sao cho A_0 \leq A_1 \leq A_2 \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

và 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 , 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 L và R để 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
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. cho thấy trên mẫu máy tính MIX của ông, được Knuth thiết kế để biểu diễn cho một chiếc máy tính thông thường, rằng thời gian chạy trung bình của cách làm này cho một lần tìm thành công là 17.5 \log_2 n + 17 đơn vị thời gian so với 18 \log_2 n - 16 đơn vị với tìm kiếm nhị phân thông thường. Độ phức tạp thời gian của cách làm này tăng nhẹ ở tốc độ chậm hơn, nhưng độ phức tạp ban đầu lớn hơ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. đã thực hiện phân tích hiệu suất thời gian của cả hai thuật toán tìm kiếm này. Trên chiếc máy tính MIX của Knuth, được ông thiết kế để biểu diễn cho một chiếc máy tính thông thường, tìm kiếm nhị phân trung bình mất 18 \log n - 16 đơn vị thời gian cho một lần tìm kiếm thành công, trong khi tìm kiếm tuyến tính khi có một sentinel node ở cuối danh sách mất 1.75n + 8.5 - \frac{n \text{ mod } 2}{4n} đơn vị. Tìm kiếm tuyến tính có độ phức tạp ban đầu thấp hơn do nó chỉ yêu cầu các tính toán tối thiểu, nhưng sau đó nhanh chóng vượt qua tìm kiếm nhị phân về độ phức tạp. Trên máy tính MIX, binary search only outperforms linear search with a sentinel if n > 44.}} 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
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

Đổ 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

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 \log_2 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. Truy cập ngày 7 tháng 5 năm 2016.}} 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() và 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 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 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

Ghi chú

Chú thích

Tài liệu
-->












Condensed web version ; book version .

}}