二 分 搜 尋 演算 法
复杂 | |
---|---|
迭代: 递归: (无 | |
Yes | |
二分查找算法在情况下的复杂度是对数时间,进行
二分查找算法有许多中变种。
演算 法
二分搜索只对有序数组有效。二分搜索先比较数组中位元素和目标值。如果
步 驟
令 為 ,為 。- 如果 ,
則 搜 尋 以失敗 告 終 。 令 (中間 值元素 )為 。(具体 实现中 ,为防止 算術 溢出,一般 采 用 代替 。)- 如果 ,
令 為 並 回 到 步 驟二。 - 如果 ,
令 為 並 回 到 步 驟二。 當 ,搜 尋 結束 ;回 傳 值 。
這個
大 致匹配
排 名 查詢可 以使用 調整 版 的 二 分 搜索 來 執行 。藉由在 成功 的 搜索 回 傳 ,以及在 失敗 的 搜索 回 傳 ,就會取 而代之 地 回 傳 了 比 起 目標 值小的 元素 數 目 [5]。前 趨和後繼 查詢可 以藉由 排 名 查詢來 執行 。一旦知道目標值的排名,其前趨就會 是 那 個 位 於其排 名 位置 的 元素 ,或 者 排 名 位置 的 上 一 个元素 (因 為 它是小 於目標 值的最大 元素 )。其後繼 是 (陣列 中 的 )下 一 個 元素 ,或 是 (非 陣列 中 的 )前 趨的下 一 個 元素 [6]。目標 值的最近 鄰可能 是 前 趨或後繼 ,取 決 於何者 較為接近 。範圍 查詢也是直接 了 當 的 。一旦知道兩個值的排名,不 小 於第一個值且小於第二個值的元素數量就會是兩者排名的差。這個值可以根據 範圍 的 端點 是 否 算 在 範圍 內,或 是 陣列 是 否 包含 其端點 的 對應 鍵 來 增加 或 減少 1[7]。
复杂度 分析
应用
示 例 代 码
C 版本 - 递归
int binary_search(const int arr[], int start, int end, int khey) {
if (start > end)
return -1;
int mid = start + (end - start) / 2; //直接 平均 可能 會 溢位,所以 用 此算法
if (arr[mid] > khey)
return binary_search(arr, start, mid - 1, khey);
else if (arr[mid] < khey)
return binary_search(arr, mid + 1, end, khey);
else
return mid; //最後 檢 測 相等 是 因 為 多數 搜 尋 狀況 不 是 大 於要不 就小於
}
C 版本 - while 循环
int binary_search(const int arr[], int start, int end, int key) {
int ret = -1; // 未 搜索 到 数 据 返 回 -1下 标
int mid;
while (start <= end) {
mid = start + (end - start) / 2; //直接 平均 可能 會 溢位,所以 用 此算法
if (arr[mid] < key)
start = mid + 1;
else if (arr[mid] > key)
end = mid - 1;
else { // 最後 檢 測 相等 是 因 為 多數 搜 尋 狀況 不 是 大 於要不 就小於
ret = mid;
break;
}
}
return ret; // 单一出口
}
javascript 版本
var arr = [1, 3, 5, 7, 9, 10, 11, 12, 14, 15, 19, 20];
function binarySearch (arr, val) {
var low = 0,
high = arr.length - 1;
while (low <= high) {
var mid = parseInt( (low + high) / 2 );
if (val == arr[mid]) {
return mid;
}else if (val > arr[mid]) {
low = mid + 1;
}else if (val < arr[mid]) {
high = mid - 1;
}
}
return -1;
};
console.log( binarySearch(arr, 4) );
Python3 版本 while 循环
def binary_search(arr, left, right, hkey):
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == hkey:
return mid
elif arr[mid] < hkey:
left = mid + 1
elif arr[mid] > hkey:
right = mid - 1
return -1
Python3 版本 递归
def binary_search(arr, start, end, hkey):
if start > end:
return -1
mid = start + (end - start) / 2
if arr[mid] > hkey:
return binary_search(arr, start, mid - 1, hkey)
if arr[mid] < hkey:
return binary_search(arr, mid + 1, end, hkey)
return mid
C# 版本
static int binary_search(int[] arr, int start, int end, int khey)
{
int mid;
while (start <= end)
{
mid = (start + end) / 2;
if (arr[mid] < khey)
start = mid + 1;
else if (arr[mid] > khey)
end = mid - 1;
else
return mid;
}
return -1;
}
Swift 版本
import Foundation
/// 二分 搜索 完全 匹 配
///
/// - Parameters:
/// - arr: 有 序 数 组
/// - start: 起 始 位置
/// - end: 结束点
/// - khey: 特 点 目 标值
/// - Returns: 返 回 查找结果
func binarySearch(arr: [Int], start: Int, end: Int, khey: Int) -> Int? {
if start > end {
return nil
}
let mid = start + (end - start) / 2
if arr[mid] > khey {
return binarySearch(arr: arr, start: start, end: mid - 1, khey: khey)
} else if arr[mid] < khey {
return binarySearch(arr: arr, start: mid + 1, end: end, khey: khey)
} else {
return mid
}
}
golang 递归版本
func binary_search(arr []int, low, high, hkey int) int {
if low > high {
return -1
}
mid := low + (high-low)/2
if arr[mid] > hkey {
return binary_search(arr, low, mid-1, hkey)
} else if arr[mid] < hkey {
return binary_search(arr, mid+1, high, hkey)
}
return mid
}
golang 非 递归版本
func binarySearch(arr []int, low, high, hkey int) int {
for low <= high {
mid := low + (high-low)/2
if arr[mid] == hkey {
return mid
} else if hkey < arr[mid] {
high = mid - 1
} else if hkey > arr[mid] {
low = mid + 1
}
}
return -1
}
Java 递归
public static int binarySearch(int[] arr, int start, int end, int hkey){
if (start > end)
return -1;
int mid = start + (end - start)/2; //防止 溢位
if (arr[mid] > hkey)
return binarySearch(arr, start, mid - 1, hkey);
if (arr[mid] < hkey)
return binarySearch(arr, mid + 1, end, hkey);
return mid;
}
Java while 循环
public static int binarySearch(int[] arr, int start, int end, int hkey){
int result = -1;
while (start <= end){
int mid = start + (end - start)/2; //防止 溢位
if (arr[mid] > hkey)
end = mid - 1;
else if (arr[mid] < hkey)
start = mid + 1;
else {
result = mid ;
break;
}
}
return result;
}
历史
实现中 的 问题
参考
- ^ Willams, Jr., Louis F. A modification to the half-interval search (binary search) method. Proceedings of the 14th ACM Southeast Conference: 95–101. 1975. doi:10.1145/503561.503582.
- ^ 2.0 2.1 Knuth 1998,§6.2.1 ("Searching an ordered table"), subsection "Binary search".
- ^ Knuth 1998,§6.2.1 ("Searching an ordered table"), subsection "Algorithm B".
- ^ Bottenbruch, Hermann. Structure and Use of ALGOL 60. Journal of the ACM. 1962, 9 (2): 161–211. Procedure is described at p. 214 (§43), titled "Program for Binary Search".
- ^ 5.0 5.1 Sedgewick & Wayne 2011,§3.1, subsection "Rank and selection".
- ^ Goldman & Goldman 2008,
第 461–463頁 . - ^ Sedgewick & Wayne 2011,§3.1, subsection "Range queries".
- ^ 8.0 8.1 8.2 Knuth 1998,§6.2.1 ("Searching an ordered table"), subsection "History and bibliography".
- ^ Peterson, William Wesley. Addressing for random-access storage. IBM Journal of Research and Development. 1957, 1 (2): 130–146. doi:10.1147/rd.12.0130.
- ^ "2n−1". OEIS A000225 互联网档
案 馆的 存 檔,存 档日期 8 June 2016.. Retrieved 7 May 2016. - ^ Lehmer, Derrick. Teaching combinatorial tricks to a computer. Proceedings of Symposia in Applied Mathematics 10. 1960: 180–181. doi:10.1090/psapm/010.
参 数 |journal=
与 模 板 {{cite conference}}
不 匹 配 (建 议改用 {{cite journal}}
或 |book-title=
) (帮助) - ^ Bottenbruch, Hermann. Structure and use of ALGOL 60. Journal of the ACM. 1 April 1962, 9 (2): 161–221. ISSN 0004-5411. doi:10.1145/321119.321120. Procedure is described at p. 214 (§43), titled "Program for Binary Search".
- ^ Chazelle, Bernard; Liu, Ding. Lower bounds for intersection searching and fractional cascading in higher dimension. 33rd ACM Symposium on Theory of Computing. ACM: 322–329. 6 July 2001 [30 June 2018]. ISBN 978-1-58113-349-3. doi:10.1145/380752.380818.
- ^ Chazelle, Bernard; Guibas, Leonidas J. Fractional cascading: I. A data structuring technique (PDF). Algorithmica. 1986, 1 (1-4): 133–162. CiteSeerX 10.1.1.117.8349 . doi:10.1007/BF01840440.
- ^ Chazelle, Bernard; Guibas, Leonidas J., Fractional cascading: II. Applications (PDF), Algorithmica, 1986, 1 (1-4): 163–191, doi:10.1007/BF01840441
- ^ Bentley 2000,§4.1 ("The Challenge of Binary Search").
- ^ Pattis, Richard E. Textbook errors in binary searching. SIGCSE Bulletin. 1988, 20: 190–194. doi:10.1145/52965.53012.
- ^ Bloch, Joshua. Extra, extra – read all about it: nearly all binary searches and mergesorts are broken. Google Research Blog. 2 June 2006 [21 April 2016]. (
原始 内容 存 档于1 April 2016).已 忽 略 未知 参 数 |df=
(帮助)
- Sahni, Sartaj. Data Structures, Algorithms, and Applications in C++. McGraw2-Hill. 1998. ISBN 978-0072362268.
- Knuth, Donald. Fundamental algorithms. The Art of Computer Programming 1 3rd. Reading, MA: Addison-Wesley Professional. 1997. ISBN 978-0-201-89683-1.
- Knuth, Donald. Sorting and searching. The Art of Computer Programming 3 2nd. Reading, MA: Addison-Wesley Professional. 1998. ISBN 978-0-201-89685-5.
- Knuth, Donald. Combinatorial algorithms. The Art of Computer Programming 4A 1st. Reading, MA: Addison-Wesley Professional. 2011. ISBN 978-0-201-03804-0.
- Moffat, Alistair; Turpin, Andrew. Compression and coding algorithms. Hamburg, Germany: Kluwer Academic Publishers. 2002. ISBN 978-0-7923-7668-2. doi:10.1007/978-1-4615-0935-6.
- Sedgewick, Robert; Wayne, Kevin. Algorithms 4th. Upper Saddle River, New Jersey: Addison-Wesley Professional. 2011. ISBN 978-0-321-57351-3. Condensed web version: ; book version .
- Stroustrup, Bjarne. The C++ programming language 4th. Upper Saddle River, New Jersey: Addison-Wesley Professional. 2013. ISBN 978-0-321-56384-2.
外部 链接
- NIST Dictionary of Algorithms and Data Structures: binary search
- Google Research: Nearly All Binary Searches and Mergesorts are Broken.
- Binary search implemented in 12 languages.
程 序 员编程 艺术第 二 十 五 章 :Jon Bentley:90%无法正 确实现二 分 查找- https://leetcode.com/explore/learn/card/binary-search