Remove ads
搜索算法 来自维基百科,自由的百科全书
在计算机科学中,二分查找算法(英语:binary search algorithm),也称折半搜索算法(英语:half-interval search algorithm)[1]、对数搜索算法(英语:logarithmic search algorithm)[2],是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。
二分查找算法在最坏情况下是对数时间复杂度的,需要进行次比较操作(在此处是数组的元素数量,是大O记号,是对数)。二分查找算法使用常数空间,对于任何大小的输入数据,算法使用的空间都是一样的。除非输入数据数量很少,否则二分查找算法比线性搜索更快,但数组必须事先被排序。尽管一些特定的、为了快速搜索而设计的数据结构更有效(比如哈希表),二分查找算法应用面更广。
二分查找算法有许多种变种。比如分散层叠可以提升在多个数组中对同一个数值的搜索的速度。分散层叠有效的解决了计算几何学和其他领域的许多搜索问题。指数搜索将二分查找算法拓宽到无边界的列表。二叉搜索树和B树数据结构就是基于二分查找算法的。
二分搜索只对有序数组有效。二分搜索先比较数组中位元素和目标值。如果目标值与中位元素相等,则返回其在数组中的位置;如果目标值小于中位元素,则搜索继续在前半部分的数组中进行。如果目标值大于中位元素,则搜索继续在数组上部分进行。由此,算法每次排除掉至少一半的待查数组。
给予一个包含个带值元素的数组或是记录,使,以及目标值,还有下列用来查找在中位置的子程序[3]。
这个迭代步骤会持续透过两个变量追踪搜索的边界。有些实际应用会在算法的最后放入相等比较,让比较循环更快,但平均而言会多一层迭代[4]。
以上程序只适用于完全匹配,也就是查找一个目标值的位置。不过,因为有序数组的顺序性,将二分搜索算法扩展到能适用大致匹配并不是很重要。举例来说,二分搜索算法可以用来计算一个赋值的排名(或称秩,比它更小的元素的数量)、前趋(下一个最小元素)、后继(下一个最大元素)以及最近邻。查找两个值之间的元素数目的范围查询可以借由两个排名查询(又称秩查询)来执行[5]。
除直接在一个数组中查找元素外,可用在插入排序中。
int binary_search(const int arr[], int start, int end, int key) {
if (start > end)
return -1;
int mid = start + (end - start) / 2; //直接平均可能會溢位,所以用此算法
if (arr[mid] > key)
return binary_search(arr, start, mid - 1, key);
else if (arr[mid] < key)
return binary_search(arr, mid + 1, end, key);
else
return mid; //最後檢測相等是因為多數搜尋狀況不是大於要不就小於
}
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; // 单一出口
}
var arr = [1, 3, 5, 7, 9, 10, 11, 12, 14, 15, 19, 20];
const binarySearch = (arr, target) => {
const search = (start, end) => {
if (start > end) return -1;
const mid = start + Math.floor((end - start) / 2);
if (arr[mid] > target) {
return search(0, mid - 1);
} else if (arr[mid] < target) {
return search(mid + 1, end);
} else {
return mid;
}
}
return search(0, arr.length - 1);
}
console.log( binarySearch(arr, 4) );
def binary_search(arr, left, right, key):
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == key:
return mid
elif arr[mid] < key:
left = mid + 1
elif arr[mid] > key:
right = mid - 1
return -1
def binary_search(arr, start, end, key):
if start > end:
return -1
mid = start + (end - start) // 2
if arr[mid] > key:
return binary_search(arr, start, mid - 1, key)
if arr[mid] < key:
return binary_search(arr, mid + 1, end, key)
return mid
static int binary_search(int[] arr, int start, int end, int key)
{
int mid;
while (start <= end)
{
mid = (start + end) / 2;
if (arr[mid] < key)
start = mid + 1;
else if (arr[mid] > key)
end = mid - 1;
else
return mid;
}
return -1;
}
import Foundation
/// 二分搜索完全匹配
///
/// - Parameters:
/// - arr: 有序数组
/// - start: 起始位置
/// - end: 结束点
/// - key: 特点目标值
/// - Returns: 返回查找结果
func binarySearch(arr: [Int], start: Int, end: Int, key: Int) -> Int? {
if start > end {
return nil
}
let mid = start + (end - start) / 2
if arr[mid] > key {
return binarySearch(arr: arr, start: start, end: mid - 1, key: key)
} else if arr[mid] < key {
return binarySearch(arr: arr, start: mid + 1, end: end, key: key)
} else {
return mid
}
}
func binary_search(arr []int, low, high, key int) int {
if low > high {
return -1
}
mid := low + (high-low)/2
if arr[mid] > key {
return binary_search(arr, low, mid-1, key)
} else if arr[mid] < key {
return binary_search(arr, mid+1, high, key)
}
return mid
}
func binarySearch(arr []int, key int) int {
low, high := 0, len(arr)-1
for low <= high {
mid := low + (high-low)/2
if arr[mid] == key {
return mid
} else if key < arr[mid] {
high = mid - 1
} else if key > arr[mid] {
low = mid + 1
}
}
return -1
}
public static int binarySearch(int[] arr, int start, int end, int key){
if (start > end)
return -1;
int mid = start + (end - start)/2; //防止溢位
if (arr[mid] > key)
return binarySearch(arr, start, mid - 1, key);
if (arr[mid] < key)
return binarySearch(arr, mid + 1, end, key);
return mid;
}
public static int binarySearch(int[] arr, int start, int end, int key){
int result = -1;
while (start <= end){
int mid = start + (end - start)/2; //防止溢位
if (arr[mid] > key)
end = mid - 1;
else if (arr[mid] < key)
start = mid + 1;
else {
result = mid ;
break;
}
}
return result;
}
# Julia Sample : BinarySearch
function BinarySearch(A,Key)
left,right = 1,length(A)
while(left<=right)
mid=left+floor(Int,((right-left)/2))
if A[mid]==Key
return mid
elseif Key<A[mid]
right = mid-1
elseif Key>A[mid]
left = mid+1
end
end
return -1
end
# Main Code
A = [1,3,16,31,43,354,586] # Already Arrange
println(A) # Original Array
println(BinarySearch(A,43)) # BinarySearch Search Array
println(BinarySearch(A,354)) # BinarySearch Search Array
println(BinarySearch(A,3)) # BinarySearch Search Array
在1946年,约翰·莫奇利在摩尔学院讲座上第一次提出二分搜索的概念。[8]1957年,威廉·皮特逊发表了第一个应用插值搜索的算法[8][9]。在此时,每个发表的二分搜索算法只对长度为2的幂减一的数组有用。[10]直到1960年,德里克·亨利·莱默发表了一个对于所有长度的数组都适用的算法[11]。1962年,赫尔曼·博滕布鲁赫发表了一个用ALGOL 60写的二分搜索,将判断相等的步骤放到算法末尾。虽然将平均迭代次数增加一,但是每次迭代中的比较次数减少了1次。[12]均匀二分搜索则是斯坦福大学的A. K.钱德拉在1971年发明的[8]。1986年,伯纳德·查泽尔和列奥尼达斯·吉巴斯引入了分散层叠来解决计算几何中大量存在的搜索问题[13][14][15]。
当乔恩·本特利将二分搜索问题布置给专业编程课的学生时,百分之90的学生在花费数小时后还是无法给出正确的解答,主要因为这些错误程序在面对边界值的时候无法运行,或返回错误结果。[16]1988年开展的一项研究显示,20本教科书里只有5本正确实现了二分搜索。[17]不仅如此,本特利自己1986年出版的《编程珠玑》一书中的二分搜索算法存在整数溢出的问题,二十多年来无人发现。Java语言的库所实现的二分搜索算法中同样的溢出问题存在了九年多才被修复。[18]
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.