zoukankan      html  css  js  c++  java
  • 八、二分查找

     二分查找常用与一个有序序列或一个具有单调性问题中。

    8.1 编程思路:

    1. 设有一数组 (a[n]) ,数组中的元素按值从小到大排列有序。用变量 (low, high)(mid) 分别指示待查元素所在区间的下界、上界和中间位置。初始时,(low=0,high=n-1) ,查找 (x) 是否在序列中。
    2. (mid = (low+ high) /2) 。(建议写成 (mid = low+(high-low)/2),可以避免数过大越界)
    3. 比较给定值 (x)(a[mid]) 值的大小:
      • (a[mid] == x) ,则查找成功,结束查找;
      • (a[mid]> x) ,则表明给定值 (x) 只可能在区间 (low sim mid-1) 内,修改检索范围。令 (high=mid-1)(low) 值保持不变;
      • (a[mid]< x) ,则表明给定值 (x) 只可能在区间 (mid+1sim high) 内,修改检索范围。令 (low=mid+1,high) 值保持不变。
    4. 比较当前变量 (low)(high) 的值,若 (low≤high) ,重复执行第1、2两步,若 (low>high) ,表明数组中不存在待查找的元素,查找失败。
    • eg : a[]={10,14,21,38,45,47,53,81,87,99},查找47

    8.2 代码实现:

    int binarysearch(int a[],int num,int x){
        int left=0,right=num-1;//查找区间[left,right]
        while(left<=right){//跳出循环时left=right+1
            int mid = left+(right-left)/2;//避免(left+right)溢出
            if(a[mid] == x)return mid;
            if(a[mid] < x)
                left = mid + 1;
            else
                right = mid - 1;
        }
        return -1;//执行到这一步说明个序列中不存在x
    }
    
    • 上面算法在查找一个数是否存在很高效,但存在局限性。
    • 比如说给你有序数组$a[]={1,2,2,2,3}, x=2$,此算法返回的索引是 $2$,没错。但是如果我想得到 (x) 的左侧边界,即索引 $1$,或者我想得到 (x) 的右侧边界,即索引 $3$ ,那我们该如何处理。

    8.2.1 左侧边界代码实现

    int binarysearch(int a[],int num,int x){//查找数组a,[0,num-1]中比x小的个数
        int left=0,right=num;//查找区间[left,right)
        while(left<right){//跳出循环时left=right
            int mid = left+(right-left)/2;//避免(left+right)溢出
            if(a[mid] >= x) //求左边界我们尽量遇到==x的时候右边界往左移
                right = mid;//注意是左闭右开区间右区间缩小不需要减一
            else
                left = mid + 1;//新的区间不包含a[mid]
        }
        return left;//跳出循环时left指向第一个x的位置
    }
    

    8.2.2 右侧边界代码实现

    int binarysearch(int a[],int l,int r,int x){//查找数组a,[l,r]中元素x的位置
        int left=0,right=num;//查找区间[left,right)
        while(left<right){//跳出循环时left=right
            int mid = left+(right-left)/2;//避免(left+right)溢出
            if(a[mid] <= x) //求右边界我们尽量遇到==x的时候左边界往右移
                left = mid+1;//注意是左闭右开区间
            else
                right = mid;//新的区间不包含a[mid]
        }
        return left-1;//注意left要减一,跳出循环时left指向最右x的下一个位置
    }
    
  • 相关阅读:
    WinCE下SQLCE数据库开发(VS,VB.net,VC++)
    基于VC++的WinCE网口通信
    WinCE下的串口通信开发(VS2005,VB.Net,VC++)
    多线程CSerialPort类的多串口通信实现
    双T滤波电路用于PWM方式DAC的分析
    AD9516锁相环功能外接环路滤波器的设计与分析
    块结构中断有序化处理方法(一种单片机单线程方式下处理多中断的方法)
    STM32F10X固件库函数——串口清状态位函数分析
    STM32和STR71X移植uCos-II操作系统比较分析
    基于uIP和uC/OS-II嵌入式网络开发
  • 原文地址:https://www.cnblogs.com/hbhszxyb/p/12232132.html
Copyright © 2011-2022 走看看