当前位置首页 > 百科> 正文

二分查找

2019-05-27 05:06:47 百科
二分查找

二分查找

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须採用顺序存储结构,而且表中元素按关键字有序排列。

基本介绍

  • 中文名:二分查找
  • 外文名:Binary Search
  • 别称:折半查找
  • 提出者:John Mauchly
  • 提出时间:1946
  • 套用学科:计算机
  • 适用领域範围:程式语言
  • 优点:查找速度快
  • 缺点:待查表为有序表
  • 时间複杂度:O(log2n) 

查找过程

首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重複以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

算法要求

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。

代码示例

C#代码
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;        }
Go原始码
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}
Swift原始码
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}
Python原始码
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不存在, 返回Noneret = bin_search(list(range(1, 10)), 3)print(ret)
pascal原始码
第一种
programjjzx(input,output);vara: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);repeatif a[j]>x thenbeginn:=j-1;j:=trunc((i+n)/2)endelse if a[j]<x thenbegini:=j+1;j:=trunc((i+n)/2)end;until(a[j]=x)or(i>=n);{为什幺是这个结束循环条件——i>n表示所查找的範围已经空了(就是没找到)}if a[j]=x thenwriteln('查找成功!位置是:',j:3)elsewriteln('查找失败,数组中无此元素!')end.
第二种
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++的语法基本相同>
循环实现
第一种
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时表示所查找区间内没有结果,查找失败}
第二种
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;}
第三种
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;}
递归实现(可直接编译)
#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;    }
Java代码
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;}
AAuto代码
//二分查找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))}
PHP代码
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;}
AS3代码
publicstaticfunctionbinSearch(list:Array,low:int,high:int,key:int):int{if(low>high)return-1;varmid:int=low+int((high-low)/2);varindex:int=-1if(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;}
JavaScript代码
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);
PHP代码
/*二分查找:前提,该数组已经是一个有序数组,必须先排序,再查找。*/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);}}}
声明:此文信息来源于网络,登载此文只为提供信息参考,并不用于任何商业目的。如有侵权,请及时联系我们:baisebaisebaise@yeah.net