二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
查找过程
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
算法要求
1.必须采用顺序存储结构。
2.必须按关键字大小有序排列。
比较次数
计算公式:
当顺序表有n个关键字时:
查找失败时,至少比较a次关键字;查找成功时,最多比较关键字次数是b。
注意:a,b,n均为正整数。
算法复杂度
二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x.
时间复杂度即是while循环的次数。
总共有n个元素,
渐渐跟下去就是n,n/2,n/4,….n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数
由于你n/2^k取整后>=1
即令n/2^k=1
可得k=log2n,(是以2为底,n的对数)
所以时间复杂度可以表示O(h)=O(log2n)
下面提供一段二分查找实现的伪代码:
BinarySearch(max,min,des)
mid-<(max+min)/2
while(min<=max)
mid=(min+max)/2
if mid=des then
return mid
elseif mid >des then
max=mid-1
else
min=mid+1
return max
折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log n)完成搜索任务。它的基本思想是:(这里假设数组元素呈升序排列)将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止;如 果x<a[n/2],则我们只要在数组a的左半部继续搜索x;如果x>a[n/2],则我们只要在数组a的右 半部继续搜索x。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public static int Method(int[] nums, int low, int high, int target) { while (low <= high) { int middle = (low + high) / 2; if (target == nums[middle]) { return middle; } else if (target > nums[middle]) { low = middle + 1; } else if (target < nums[middle]) { high = middle – 1; } } return -1; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | func binarySearch(checkSlice []int, findVal int) int {
pos := -1
left, right := 0, len(checkSlice) //此处right长度不减1 , 如果最大值为查找值,此处减一代码进入死循环
Loop:
for {
if(left >= right){ break Loop }
mid := (left + right) / 2
switch true {
case checkSlice[mid] < findVal : left = mid case checkSlice[mid] == findVal : pos = mid break Loop case checkSlice[mid] > findVal : right = mid
}
}
return pos
} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | func BinarySearch(n []int, target int) int { length := len(n) low := 0 high := length – 1 for low <= high { mid := (low + high) / 2 if n[mid] > target { high = mid – 1 } else if n[mid] < target { low = mid + 1 } else { return mid } } return -1 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | func binarySearch<T: Comparable>(_ a: [T], key: T) -> Int? { var lowerBound = 0 var upperBound = a.count while lowerBound < upperBound { let midIndex = lowerBound + (upperBound – lowerBound) / 2 if a[midIndex] == key { return midIndex } else if a[midIndex] < key { lowerBound = midIndex + 1 } else { upperBound = midIndex } } return nil } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def bin_search(data_list, val): low = 0 # 最小数下标 high = len(data_list) – 1 # 最大数下标 while low <= high: mid = (low + high) // 2 # 中间数下标 if data_list[mid] == val: # 如果中间数下标等于val, 返回 return mid elif data_list[mid] > val: # 如果val在中间数左边, 移动high下标 high = mid – 1 else: # 如果val在中间数右边, 移动low下标 low = mid + 1 return # val不存在, 返回None ret = bin_search(list(range(1, 10)), 3) print(ret) |
以上参考资料来源于
pascal源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | programjjzx(input,output); var a:array[1..10]ofinteger; i,j,n,x:integer; begin ['输入10个从小到大的数:'] for i:=1 to 10 do read(a[i]); ['输入要查找的数:'] readln(x); i:=1;n:=10;j:=trunc((i+n)/2); repeat if a[j]>x then begin n:=j-1;j:=trunc((i+n)/2) end else if a[j]<x then begin i:=j+1;j:=trunc((i+n)/2) end; until(a[j]=x)or(i>=n);{为什么是这个结束循环条件——i>n表示所查找的范围已经空了(就是没找到)} if a[j]=x then writeln('查找成功!位置是:',j:3) else writeln('查找失败,数组中无此元素!') end. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | var a:array[1..100001] of longint; n,m,i,t:longint;
function search(k:longint):longint; var l,r,mid:longint; begin l:=1; r:=n; mid:=(l+r) div 2; while (a[mid]<>k) and (l<=r) do begin if a[mid]>k then r:=mid-1 else l:=mid+1; mid:=(l+r) div 2; end; if l>r then exit(0); exit(mid); end;
begin readln(n,m); for i:=1 to n do read(a[i]); for i:=1 to n do begin read(t); if search(t)=0 then writeln('no') else writeln(search(t)); end; end. |
C和C++代码
<C和C++的语法基本相同>
循环实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | int BinSearch(SeqList *R,int n,KeyType K) { //在有序表R[0..n-1]中进行二分查找,成功时返回结点的位置,失败时返回-1 int low=0,high=n-1,mid; //置当前查找区间上、下界的初值 while(low<=high) { if(R[low].key==K) return low; if(R[high].key==k) return high; //当前查找区间R[low..high]非空 mid=low+(high-low)/2; /*使用(low+high)/2会有整数溢出的问题 (问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时, 这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2) 不存在这个问题*/ if(R[mid].key==K) return mid; //查找成功返回 if(R[mid].key<K) low=mid+1; //继续在R[mid+1..high]中查找 else high=mid-1; //继续在R[low..mid-1]中查找 } if(low>high) return -1;//当low>high时表示所查找区间内没有结果,查找失败 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int bsearchWithoutRecursion(int array[],int low,int high,int target) { while(low<=high) { int mid=low+(high-low)/2;//还是溢出问题 if(array[mid]>target) high=mid-1; else if(array[mid]<target) low=mid+1; else return mid; } return-1; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | int binSearch(const int *Array,int start,int end,int key) { int left,right; int mid; left=start; right=end; while(left<=right)
{ mid=left+(right-left)/2;//还是溢出问题 if(key==Array[mid]) return mid; else if(key<Array[mid]) right=mid-1; else if(key>Array[mid]) left=mid+1;
} return -1; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function binarySearch(arr,target){ if(!arr.length) return -1;// 考虑边界值 if(arr.length == 1)return 0;//只有一位无需进入循环 let start = 0; let end = arr.length-1; while(start <= end){ let mid = Math.floor((start + end) / 2);//取中位数,可能除不尽向下取整 if(arr[mid] === target){ return mid; }else if(target > arr[mid]){// 若目标值大于中位值 start = mid +1 //则说明目标值在更右侧,将初始下标右移至中位数右侧,再次循环 }else{// 若目标值小于中位值 end = mid -1 //则说明目标值在更左侧,将结束下标左移至中位数左侧,再次循环 } } return -1 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include<iostream> using namespace std; int a[100]={1,2,3,5,12,12,12,15,29,55};//数组中的数(由小到大) int k;//要找的数字 int found(int x,int y) { int m=x+(y-x)/2; if(x>y)//查找完毕没有找到答案,返回-1 return -1; else { if(a[m]==k) return m;//找到!返回位置. else if(a[m]>k) return found(x,m-1);//找左边 else return found(m+1,y);//找右边 } } int main() { cin>>k;//输入要找的数字c语言把cin换为scanf即可 cout<<found(0,9);//从数组a[0]到a[9]c语言把cout换为printf即可 return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public static int binarySearch(Integer[] srcArray, int des) { //定义初始最小、最大索引 int start = 0; int end = srcArray.length – 1; //确保不会出现重复查找,越界 while (start <= end) { //计算出中间索引值 int middle = (end + start)>>>1 ;//防止溢出 if (des == srcArray[middle]) { return middle; //判断下限 } else if (des < srcArray[middle]) { end = middle – 1; //判断上限 } else { start = middle + 1; } } //若没有,则返回-1 return -1; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | //二分查找 functionbinSearch(t,v){ varp=#t; varp2; varb=0; do{ p2=p; p=b+math.floor((p-b)/2)//二分折半运算 if(p==b)return; if(t[p]<v){//判断下限 b=p; p=p2; } }while(t[p]>v)//判断上限 returnt[p]==v&&p; } //测试 tab={} //创建数组,每个元素都是随机数 for(i=1;10;1){ tab[i]=math.random(1,10000) } //插入一个已知数 table.push(tab,5632) //排序 table.sort(tab) io.open() io.print("数组",table.tostring(tab)) io.print("使用二分查找,找到5632在位置:",binSearch(tab,5632)) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | function binsearch($x,$a){ $c=count($a); $lower=0; $high=$c-1; while($lower<=$high){ $middle=intval(($lower+$high)/2); if($a[$middle]>$x){ $high=$middle-1; } elseif($a[$middle]<$x){ $lower=$middle+1; } else{ return $middle; } } return -1; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | publicstaticfunctionbinSearch(list:Array,low:int,high:int,key:int):int{ if(low>high) return-1; varmid:int=low+int((high-low)/2); varindex:int=-1 if(list[mid]==key){ index=mid; }elseif(list[mid]<key){ low=mid+1; index=binSearch(list,low,high,key); }else{ high=mid-1; index=binSearch(list,low,high,key); }returnindex; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | var Arr = [3, 5, 6, 7, 9, 12, 15]; function binary(find, arr, low, high) { if (low <= high) { if (arr[low] == find) { return low; } if (arr[high] == find) { return high; } var mid = Math.ceil((high + low) / 2); if (arr[mid] == find) { return mid; } else if (arr[mid] > find) { return binary(find, arr, low, mid – 1); } else { return binary(find, arr, mid + 1, high); } } return -1; } binary(15, Arr, 0, Arr.length – 1); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /*二分查找:前提,该数组已经是一个有序数组,必须先排序,再查找。*/ function binarySearch(&$array,$findVal,$leftIndex,$rightIndex){ $middleIndex=round(($rightIndex+$leftIndex)/2); if($leftIndex>$rightIndex){ echo'查无此数<br/>'; return; } if($findVal>$array[$middleIndex]){ binarySearch($array,$findVal,$middleIndex+1,$rightIndex); }elseif($findVal<$array[$middleIndex]){ binarySearch($array,$findVal,$leftIndex,$middleIndex-1); }else{ echo"找到数据:index=$middleIndex;value=$array[$middleIndex]<br/>"; if($array[$middleIndex+1]==$array[$middleIndex]&&$leftIndex<$rightIndex){ binarySearch($array,$findVal,$middleIndex+1,$rightIndex); } if($array[$middleIndex-1]==$array[$middleIndex]&&$leftIndex<$rightIndex){ binarySearch($array,$findVal,$leftIndex,$middleIndex-1); } } } |
该文章由作者:【超狗】发布,本站仅提供存储、如有版权、错误、违法等相关信息请联系,本站会在1个工作日内进行整改,谢谢!