学会二分查找

Posted 堆栈树图

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学会二分查找相关的知识,希望对你有一定的参考价值。

我们走进了一家餐厅,找了空桌子坐下,服务员过来递给我们一本菜单。

枇伊:“这家餐厅有一道菜价格17元,特别好吃,你帮我找一找吧。”

我刚要翻开菜单,她马上叫住了我,说到:“这家餐厅的菜单有一个特点,每页有一道菜,价格是递增的,后一页菜的价格一定比前一页贵,每页侧面都有一个突出的标签标明了页数,你试试能不能尽快的找出那道菜。”

我:“没问题交给我吧。(这人好无聊啊,吃个饭还要考我一下二分查找)”。

怎么做二分查找呢

一.基本思想


面对有序的n个数时,要在其中查找出一个数x时,最容易想到的办法是从头到尾遍历,遇到值为x的则输出。如果要查找的x在第一位,马上就可以查找出来;但要查找的x在最后一位,那就需要遍历全部n个数。有没有效率更高的算法呢?当然有,这就是二分查找。首先我们要利用n个数有序的这个性质,假定顺序为升序,并存放在数组Array[]中。取这一组数的查找范围的上边界为low,初值为low=0;查找范围的下边界为high,初值为high=n-1;中间数下标mid=(low+high)/2,若Array[mid]=x,则可以直接输出或返回。若Array[mid]>x,依据升序的原则可以判断出x在前半部分,令high=mid-1。若Array[mid]<x,依据升序的原则可以判断出x在后半部分,令low=mid+1。之后在前半部分或后半部分继续用该思想查找,直到找到目标数。

以故事中的菜单为例,把菜单中各道菜的价格按序放到数组中,查找范围的上边界为low,下边界为high。每次查找的中间值下标为mid,查找的数x=17。


         1.第一次查找

 



         2.第二次查找

 



这时我们发现Array[mid]=x=17,仅仅只是查找了两次就找到了这道菜,如果用从头到尾遍历的方法,需要找五次,而且随着元素数量的增加,二分查找的高效率会反映的更明显。

有人可能会问了,要是查找的数在第一个,那二分查找法的效率就比不上遍历法了。确实,查找的数在第一个的话,那么遍历只要找一次就够了,但是在实际应用时,绝大多数情况还是要查找位于中间的数,在首位的情况只是特例。

当然,这种算法也有不足之处。它只能对有序数列进行查找,对无序数列不能使用这种算法。

二.代码

二分查找有两种实现形式:递归形式和非递归形式。

用两种语言表示程序,递归程序使用C++,非递归程序使用java

递归形式

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int binarysearch(int Array[], int x, int low, int high)
{
  if (low > high)return -1;//Returns -1 if the element is not found
  int mid = (low + high)/2;
  if (Array[mid] == x)//Find the element
  {
    return mid;//return
  }
  else if (Array[mid] > x)//The number found is greater than the target
  {
    return binarysearch(Array, x, low, mid - 1);//Look for the first half
  }
  else//The number found is less than the target
  {
    return binarysearch(Array, x, mid+1, high);//Look for the second half
  }
}
int main()
{
  int Array[1000];
  int n,x;
  scanf("%d", &n);
  for (int i = 0;i < n;i++)
    scanf("%d", &Array[i]);
  scanf("%d", &x);
  sort(Array,Array+n);
  int flag = binarysearch(Array, x, 0, n - 1);
  if (flag == -1)printf("此数不存在\n");
  else printf("此数排序后在第%d个位置", flag + 1);
  return 0;
}

非递归形式

import java.util.Arrays;
import java.util.Scanner;

public class Search {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[] Array1=new int[n];
        for(int i=0;i<n;i++){
            Array1[i]=sc.nextInt();
        }
        Arrays.sort(Array1);
        int x=sc.nextInt();
        int flag=binarysearch(Array1,x,0,n-1);
        if(flag==-1){
            System.out.println("此数不存在");
        }else{
            System.out.printf("此数排序后在第%d个位置",flag+1);
        }
    }
    private static int binarysearch(int[] Array1,int x,int low,int high){
        while(low<=high){
            int mid=(low+high)/2;
            if(Array1[mid]==x){//Find the element
                return mid;//return
            }else if(Array1[mid]>x){//The number found is greater than the target
                high=mid-1;//Look for the first half
            }else{//The number found is less than the target
                low=mid+1;//Look for the second half
            }
        }
        return -1;//Returns -1 if the element is not found
    }
}

以上是关于学会二分查找的主要内容,如果未能解决你的问题,请参考以下文章

猿创征文|python二分查找解密 青少年编程电子学会python编程等级考试三级真题解析2021年03月

猿创征文|python二分查找解密 青少年编程电子学会python编程等级考试三级真题解析2021年03月

算法?日更?第二十四期二分查找和二分答案的区别

[算法总结]二分查找-binarySearch

ACM 选手带你玩转二分查找!

ACM 选手带你玩转二分查找!