算法描述:
假定有n个不同的整数n>=1,且它们已经排序并且存放在数组list中.也就是说,list[0]<=list[1]<=......<=list[n-1].要求判定某个整数searchnum是否在数组list中,如果在数组中,则返回下标i,使list[i]=searchnum.如果不在数组list中,就返回-1.如果此数组已经被排序,则可以采用下面所描述的方法来查找.
设两个变量left和right分别表示被查找表的左边界和右边界,初始化时,left=0,right=n-1.令middle=(left+right)/2为list的中间位置.如果将list[middle]与searchnum进行比较,则会出现下列三种情况:(1)searchnum<list[middle].此时,如果searchnum在数组中,则其一定在0到middle-1之间.因此,把查找右边界right设置为middle-1.
(2)searchnum=list[middle].此时,返回middle.
(3)searchmun>list[middle].此时,如果searchnum在数组中,则其一定在0到middle+1到n-1之间,因此,把查找左边界left设定为middle+1.
图解为一个折半查找树
如图,若要查找8,则第一个mid即命中,若要查找12,则需要查找mid+1到right内.....
非递归实现:
#include<iostream>
#include<stdio.h>
using namespace std;
const int MAX = 20;
/**
*@brief:有序顺序表的折半查找
*非递归版本
*param[in] arr 已经排好序的数组
*param[in] n 数组长度
*param[in] x 待查元素值
*找不到返回-1
*/
int binary_search(int arr[],int n,int x)
{
int left = 0,right = n-1,mid;
while(left < right)
{
mid = left + (right - left)/2;
if(x > arr[mid])
{
left = mid + 1;
}else if(x < arr[mid])
{
right = mid - 1;
}else
{
return mid;
}
}
return -1;
}
int
main(void)
{
int arr[MAX];
int n,x;
scanf("%d%d",&n,&x);
for(int i=0;i<n;i++)
scanf("%d",&arr[i]);
printf("%d\n",binary_search(arr,n,x)+1);
}
递归实现:
#include<iostream>
#include<stdio.h>
using namespace std;
const int MAX = 20;
/**
*@brief:有序顺序表的折半查找
*递归版本
*param[in] arr 已经排好序的数组
*param[in] left 查找左边界
*param[in] right 查找右边界
*param[in] x 待查元素值
*找不到返回-1
*/
int rbinary_search(int arr[],int x,int left,int right)
{
int mid = (left+right)/2;
if(x > arr[mid])
{
return rbinary_search(arr,x,mid+1,right);
}else if(x < arr[mid])
{
return rbinary_search(arr,x,left,mid-1);
}else
{
return mid;
}
}
int
main(void)
{
int arr[MAX];
int n,x;
scanf("%d%d",&n,&x);
for(int i=0;i<n;i++)
scanf("%d",&arr[i]);
printf("%d\n",rbinary_search(arr,x,0,n-1)+1);//第几个数
}