僞代碼
- 遞歸
// initially called with low = 0, high = N-1
BinarySearch(A[0..N-1], value, low, high) {
// invariants: value > A[i] for all i < low
value < A[i] for all i > high
if (high < low)
return not_found // value would be inserted at index "low"
mid = (low + high) / 2
if (A[mid] > value)
return BinarySearch(A, value, low, mid-1)
else if (A[mid] < value)
return BinarySearch(A, value, mid+1, high)
else
return mid
}
- 迭代
BinarySearch(A[0..N-1], value) {
low = 0
high = N - 1
while (low <= high) {
// invariants: value > A[i] for all i < low
value < A[i] for all i > high
mid = (low + high) / 2
if (A[mid] > value)
high = mid - 1
else if (A[mid] < value)
low = mid + 1
else
return mid
}
return not_found // value would be inserted at index "low"
}
C
#include <stdio.h>
int bsearch (int *a, int n, int x) {
int i = 0, j = n - 1;
while (i <= j) {
int k = i + ((j - i) / 2);
if (a[k] == x) {
return k;
}
else if (a[k] < x) {
i = k + 1;
}
else {
j = k - 1;
}
}
return -1;
}
int bsearch_r (int *a, int x, int i, int j) {
if (j < i) {
return -1;
}
int k = i + ((j - i) / 2);
if (a[k] == x) {
return k;
}
else if (a[k] < x) {
return bsearch_r(a, x, k + 1, j);
}
else {
return bsearch_r(a, x, i, k - 1);
}
}
int main () {
int a[] = {-31, 0, 1, 2, 2, 4, 65, 83, 99, 782};
int n = sizeof a / sizeof a[0];
int x = 2;
int i = bsearch(a, n, x);
printf("%d is at index %d\n", x, i);
x = 5;
i = bsearch_r(a, x, 0, n - 1);
printf("%d is at index %d\n", x, i);
return 0;
}
輸出:
2 is at index 4
5 is at index -1
C++
- 遞歸
template <class T> int binsearch(const T array[], int low, int high, T value) {
if (high < low) {
return -1;
}
auto mid = (low + high) / 2;
if (value < array[mid]) {
return binsearch(array, low, mid - 1, value);
} else if (value > array[mid]) {
return binsearch(array, mid + 1, high, value);
}
return mid;
}
#include <iostream>
int main()
{
int array[] = {2, 3, 5, 6, 8};
int result1 = binsearch(array, 0, sizeof(array)/sizeof(int), 4),
result2 = binsearch(array, 0, sizeof(array)/sizeof(int), 8);
if (result1 == -1) std::cout << "4 not found!" << std::endl;
else std::cout << "4 found at " << result1 << std::endl;
if (result2 == -1) std::cout << "8 not found!" << std::endl;
else std::cout << "8 found at " << result2 << std::endl;
return 0;
}
- 迭代
template <class T>
int binSearch(const T arr[], int len, T what) {
int low = 0;
int high = len - 1;
while (low <= high) {
int mid = (low + high) / 2;
if (arr[mid] > what)
high = mid - 1;
else if (arr[mid] < what)
low = mid + 1;
else
return mid;
}
return -1; // indicate not found
}
C++標準模板庫有四個二分查找的函數
#include <algorithm>
int *ptr = std::lower_bound(array, array+len, what); // a custom comparator can be given as fourth arg
int *ptr = std::upper_bound(array, array+len, what); // a custom comparator can be given as fourth arg
std::pair<int *, int *> bounds = std::equal_range(array, array+len, what); // a custom comparator can be given as fourth arg
bool found = std::binary_search(array, array+len, what); // a custom comparator can be given as fourth arg
C#
- 遞歸
namespace Search {
using System;
public static partial class Extensions {
/// <summary>Use Binary Search to find index of GLB for value</summary>
/// <typeparam name="T">type of entries and value</typeparam>
/// <param name="entries">array of entries</param>
/// <param name="value">search value</param>
/// <remarks>entries must be in ascending order</remarks>
/// <returns>index into entries of GLB for value</returns>
public static int RecursiveBinarySearchForGLB<T>(this T[] entries, T value)
where T : IComparable {
return entries.RecursiveBinarySearchForGLB(value, 0, entries.Length - 1);
}
/// <summary>Use Binary Search to find index of GLB for value</summary>
/// <typeparam name="T">type of entries and value</typeparam>
/// <param name="entries">array of entries</param>
/// <param name="value">search value</param>
/// <param name="left">leftmost index to search</param>
/// <param name="right">rightmost index to search</param>
/// <remarks>entries must be in ascending order</remarks>
/// <returns>index into entries of GLB for value</returns>
public static int RecursiveBinarySearchForGLB<T>(this T[] entries, T value, int left, int right)
where T : IComparable {
if (left <= right) {
var middle = left + (right - left) / 2;
return entries[middle].CompareTo(value) < 0 ?
entries.RecursiveBinarySearchForGLB(value, middle + 1, right) :
entries.RecursiveBinarySearchForGLB(value, left, middle - 1);
}
//[Assert]left == right + 1
// GLB: entries[right] < value && value <= entries[right + 1]
return right;
}
/// <summary>Use Binary Search to find index of LUB for value</summary>
/// <typeparam name="T">type of entries and value</typeparam>
/// <param name="entries">array of entries</param>
/// <param name="value">search value</param>
/// <remarks>entries must be in ascending order</remarks>
/// <returns>index into entries of LUB for value</returns>
public static int RecursiveBinarySearchForLUB<T>(this T[] entries, T value)
where T : IComparable {
return entries.RecursiveBinarySearchForLUB(value, 0, entries.Length - 1);
}
/// <summary>Use Binary Search to find index of LUB for value</summary>
/// <typeparam name="T">type of entries and value</typeparam>
/// <param name="entries">array of entries</param>
/// <param name="value">search value</param>
/// <param name="left">leftmost index to search</param>
/// <param name="right">rightmost index to search</param>
/// <remarks>entries must be in ascending order</remarks>
/// <returns>index into entries of LUB for value</returns>
public static int RecursiveBinarySearchForLUB<T>(this T[] entries, T value, int left, int right)
where T : IComparable {
if (left <= right) {
var middle = left + (right - left) / 2;
return entries[middle].CompareTo(value) <= 0 ?
entries.RecursiveBinarySearchForLUB(value, middle + 1, right) :
entries.RecursiveBinarySearchForLUB(value, left, middle - 1);
}
//[Assert]left == right + 1
// LUB: entries[left] > value && value >= entries[left - 1]
return left;
}
}
}
- 迭代
namespace Search {
using System;
public static partial class Extensions {
/// <summary>Use Binary Search to find index of GLB for value</summary>
/// <typeparam name="T">type of entries and value</typeparam>
/// <param name="entries">array of entries</param>
/// <param name="value">search value</param>
/// <remarks>entries must be in ascending order</remarks>
/// <returns>index into entries of GLB for value</returns>
public static int BinarySearchForGLB<T>(this T[] entries, T value)
where T : IComparable {
return entries.BinarySearchForGLB(value, 0, entries.Length - 1);
}
/// <summary>Use Binary Search to find index of GLB for value</summary>
/// <typeparam name="T">type of entries and value</typeparam>
/// <param name="entries">array of entries</param>
/// <param name="value">search value</param>
/// <param name="left">leftmost index to search</param>
/// <param name="right">rightmost index to search</param>
/// <remarks>entries must be in ascending order</remarks>
/// <returns>index into entries of GLB for value</returns>
public static int BinarySearchForGLB<T>(this T[] entries, T value, int left, int right)
where T : IComparable {
while (left <= right) {
var middle = left + (right - left) / 2;
if (entries[middle].CompareTo(value) < 0)
left = middle + 1;
else
right = middle - 1;
}
//[Assert]left == right + 1
// GLB: entries[right] < value && value <= entries[right + 1]
return right;
}
/// <summary>Use Binary Search to find index of LUB for value</summary>
/// <typeparam name="T">type of entries and value</typeparam>
/// <param name="entries">array of entries</param>
/// <param name="value">search value</param>
/// <remarks>entries must be in ascending order</remarks>
/// <returns>index into entries of LUB for value</returns>
public static int BinarySearchForLUB<T>(this T[] entries, T value)
where T : IComparable {
return entries.BinarySearchForLUB(value, 0, entries.Length - 1);
}
/// <summary>Use Binary Search to find index of LUB for value</summary>
/// <typeparam name="T">type of entries and value</typeparam>
/// <param name="entries">array of entries</param>
/// <param name="value">search value</param>
/// <param name="left">leftmost index to search</param>
/// <param name="right">rightmost index to search</param>
/// <remarks>entries must be in ascending order</remarks>
/// <returns>index into entries of LUB for value</returns>
public static int BinarySearchForLUB<T>(this T[] entries, T value, int left, int right)
where T : IComparable {
while (left <= right) {
var middle = left + (right - left) / 2;
if (entries[middle].CompareTo(value) <= 0)
left = middle + 1;
else
right = middle - 1;
}
//[Assert]left == right + 1
// LUB: entries[left] > value && value >= entries[left - 1]
return left;
}
}
}
Go
- 遞歸
func binarySearch(a []float64, value float64, low int, high int) int {
if high < low {
return -1
}
mid := (low + high) / 2
if a[mid] > value {
return binarySearch(a, value, low, mid-1)
} else if a[mid] < value {
return binarySearch(a, value, mid+1, high)
}
return mid
}
- 迭代
func binarySearch(a []float64, value float64) int {
low := 0
high := len(a) - 1
for low <= high {
mid := (low + high) / 2
if a[mid] > value {
high = mid - 1
} else if a[mid] < value {
low = mid + 1
} else {
return mid
}
}
return -1
}
Java
- 遞歸
public class BinarySearchRecursive {
public static int binarySearch(int[] haystack, int needle, int lo, int hi) {
if (hi < lo) {
return -1;
}
int guess = (hi + lo) / 2;
if (haystack[guess] > needle) {
return binarySearch(haystack, needle, lo, guess - 1);
} else if (haystack[guess] < needle) {
return binarySearch(haystack, needle, guess + 1, hi);
}
return guess;
}
public static void main(String[] args) {
int[] haystack = {1, 5, 6, 7, 8, 11};
int needle = 5;
int index = binarySearch(haystack, needle, 0, haystack.length);
if (index == -1) {
System.out.println(needle + " is not in the array");
} else {
System.out.println(needle + " is at index " + index);
}
}
}
- 迭代
public class BinarySearchIterative {
public static int binarySearch(int[] nums, int check) {
int hi = nums.length - 1;
int lo = 0;
while (hi >= lo) {
int guess = (lo + hi) >>> 1; // from OpenJDK
if (nums[guess] > check) {
hi = guess - 1;
} else if (nums[guess] < check) {
lo = guess + 1;
} else {
return guess;
}
}
return -1;
}
public static void main(String[] args) {
int[] haystack = {1, 5, 6, 7, 8, 11};
int needle = 5;
int index = binarySearch(haystack, needle);
if (index == -1) {
System.out.println(needle + " is not in the array");
} else {
System.out.println(needle + " is at index " + index);
}
}
}
JavaScript
ES5
- 遞歸
function binary_search_recursive(a, value, lo, hi) {
if (hi < lo) { return null; }
var mid = Math.floor((lo + hi) / 2);
if (a[mid] > value) {
return binary_search_recursive(a, value, lo, mid - 1);
}
if (a[mid] < value) {
return binary_search_recursive(a, value, mid + 1, hi);
}
return mid;
}
- 迭代
function binary_search_iterative(a, value) {
var mid, lo = 0,
hi = a.length - 1;
while (lo <= hi) {
mid = Math.floor((lo + hi) / 2);
if (a[mid] > value) {
hi = mid - 1;
} else if (a[mid] < value) {
lo = mid + 1;
} else {
return mid;
}
}
return null;
}
ES6
(() => {
'use strict';
const main = () => {
// findRecursive :: a -> [a] -> Either String Int
const findRecursive = (x, xs) => {
const go = (lo, hi) => {
if (hi < lo) {
return Left('not found');
} else {
const
mid = div(lo + hi, 2),
v = xs[mid];
return v > x ? (
go(lo, mid - 1)
) : v < x ? (
go(mid + 1, hi)
) : Right(mid);
}
};
return go(0, xs.length);
};
// findRecursive :: a -> [a] -> Either String Int
const findIter = (x, xs) => {
const [m, l, h] = until(
([mid, lo, hi]) => lo > hi || lo === mid,
([mid, lo, hi]) => {
const
m = div(lo + hi, 2),
v = xs[m];
return v > x ? [
m, lo, m - 1
] : v < x ? [
m, m + 1, hi
] : [m, m, hi];
},
[div(xs.length / 2), 0, xs.length - 1]
);
return l > h ? (
Left('not found')
) : Right(m);
};
// TESTS ------------------------------------------
const
// (pre-sorted AZ)
xs = ["alpha", "beta", "delta", "epsilon", "eta", "gamma",
"iota", "kappa", "lambda", "mu", "nu", "theta", "zeta"
];
return JSON.stringify([
'Recursive',
map(x => either(
l => "'" + x + "' " + l,
r => "'" + x + "' found at index " + r,
findRecursive(x, xs)
),
knuthShuffle(['cape'].concat(xs).concat('cairo'))
),
'',
'Iterative:',
map(x => either(
l => "'" + x + "' " + l,
r => "'" + x + "' found at index " + r,
findIter(x, xs)
),
knuthShuffle(['cape'].concat(xs).concat('cairo'))
)
], null, 2);
};
// GENERIC FUNCTIONS ----------------------------------
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
// div :: Int -> Int -> Int
const div = (x, y) => Math.floor(x / y);
// either :: (a -> c) -> (b -> c) -> Either a b -> c
const either = (fl, fr, e) =>
'Either' === e.type ? (
undefined !== e.Left ? (
fl(e.Left)
) : fr(e.Right)
) : undefined;
// Abbreviation for quick testing
// enumFromTo :: (Int, Int) -> [Int]
const enumFromTo = (m, n) =>
Array.from({
length: 1 + n - m
}, (_, i) => m + i);
// FOR TESTS
// knuthShuffle :: [a] -> [a]
const knuthShuffle = xs => {
const swapped = (iFrom, iTo, xs) =>
xs.map(
(x, i) => iFrom !== i ? (
iTo !== i ? x : xs[iFrom]
) : xs[iTo]
);
return enumFromTo(0, xs.length - 1)
.reduceRight((a, i) => {
const iRand = randomRInt(0, i)();
return i !== iRand ? (
swapped(i, iRand, a)
) : a;
}, xs);
};
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) =>
(Array.isArray(xs) ? (
xs
) : xs.split('')).map(f);
// FOR TESTS
// randomRInt :: Int -> Int -> IO () -> Int
const randomRInt = (low, high) => () =>
low + Math.floor(
(Math.random() * ((high - low) + 1))
);
// reverse :: [a] -> [a]
const reverse = xs =>
'string' !== typeof xs ? (
xs.slice(0).reverse()
) : xs.split('').reverse().join('');
// until :: (a -> Bool) -> (a -> a) -> a -> a
const until = (p, f, x) => {
let v = x;
while (!p(v)) v = f(v);
return v;
};
// MAIN ---
return main();
})();
輸出:
[
"Recursive",
[
"'delta' found at index 2",
"'cairo' not found",
"'cape' not found",
"'gamma' found at index 5",
"'eta' found at index 4",
"'kappa' found at index 7",
"'alpha' found at index 0",
"'mu' found at index 9",
"'beta' found at index 1",
"'epsilon' found at index 3",
"'nu' found at index 10",
"'iota' found at index 6",
"'theta' found at index 11",
"'lambda' found at index 8",
"'zeta' found at index 12"
],
"",
"Iterative:",
[
"'theta' found at index 11",
"'kappa' found at index 7",
"'zeta' found at index 12",
"'cairo' not found",
"'epsilon' found at index 3",
"'beta' found at index 1",
"'nu' found at index 10",
"'eta' found at index 4",
"'alpha' found at index 0",
"'lambda' found at index 8",
"'iota' found at index 6",
"'mu' found at index 9",
"'gamma' found at index 5",
"'delta' found at index 2",
"'cape' not found"
]
]
Kotlin
fun <T : Comparable<T>> Array<T>.iterativeBinarySearch(target: T): Int {
var hi = size - 1
var lo = 0
while (hi >= lo) {
val guess = lo + (hi - lo) / 2
if (this[guess] > target) hi = guess - 1
else if (this[guess] < target) lo = guess + 1
else return guess
}
return -1
}
fun <T : Comparable<T>> Array<T>.recursiveBinarySearch(target: T, lo: Int, hi: Int): Int {
if (hi < lo) return -1
val guess = (hi + lo) / 2
return if (this[guess] > target) recursiveBinarySearch(target, lo, guess - 1)
else if (this[guess] < target) recursiveBinarySearch(target, guess + 1, hi)
else guess
}
fun main(args: Array<String>) {
val a = arrayOf(1, 3, 4, 5, 6, 7, 8, 9, 10)
var target = 6
var r = a.iterativeBinarySearch(target)
println(if (r < 0) "$target not found" else "$target found at index $r")
target = 250
r = a.iterativeBinarySearch(target)
println(if (r < 0) "$target not found" else "$target found at index $r")
target = 6
r = a.recursiveBinarySearch(target, 0, a.size)
println(if (r < 0) "$target not found" else "$target found at index $r")
target = 250
r = a.recursiveBinarySearch(target, 0, a.size)
println(if (r < 0) "$target not found" else "$target found at index $r")
}
PHP
- 遞歸
function binary_search( $array, $secret, $start, $end ){
$guess = (int)($start + ( ( $end - $start ) / 2 ));
if ( $end < $start)
return -1;
if ( $array[$guess] > $secret )
return (binary_search( $array, $secret, $start, $guess ));
if ( $array[$guess] < $secret )
return (binary_search( $array, $secret, $guess, $end ) );
return $guess;
}
- 迭代
function binary_search( $array, $secret, $start, $end ){
do
{
$guess = (int)($start + ( ( $end - $start ) / 2 ));
if ( $array[$guess] > $secret )
$end = $guess;
if ( $array[$guess] < $secret )
$start = $guess;
if ( $end < $start)
return -1;
} while ( $array[$guess] != $secret );
return $guess;
}
Python
- 遞歸
def binary_search(l, value, low = 0, high = -1):
if not l: return -1
if(high == -1): high = len(l)-1
if low >= high:
if l[low] == value: return low
else: return -1
mid = (low+high)//2
if l[mid] > value: return binary_search(l, value, low, mid-1)
elif l[mid] < value: return binary_search(l, value, mid+1, high)
else: return mid
- 迭代
def binary_search(l, value):
low = 0
high = len(l)-1
while low <= high:
mid = (low+high)//2
if l[mid] > value: high = mid-1
elif l[mid] < value: low = mid+1
else: return mid
return -1