二分查找(计算机领域术语)

二分查找也称折半查找(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。

代码示例

C#代码

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;

        }

Go源代码

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

 

}

Go源代码修正

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

}

Swift源代码

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

}

Python源代码

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;

}

JavaScript

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;

    }

Java代码

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;

}

AAuto代码

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))

}

PHP代码

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;

}

AS3代码

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;

}

JavaScript代码

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个工作日内进行整改,谢谢!

发表回复

登录后才能评论