java 数组二分查找_循环数组的二分查找--Java实现

/**

* 循环数组的二分查找

* @author Jacky

*测试用数组

*[9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8]

*数组对应下标,方便查看

*[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,12,13,14,15,16,17,18,19]

*/

public class BSearch2 {

public static int BSearch(int[] arr,int left,int right,int value) {

while(left<=right) {

int mid = left+((right-left)>>1);//防止溢出的取中方法

if(value

int lMid = (left+mid)/2;//取左区间的中间值,仅用于判断是否单调增长

if(arr[0]<=arr[lMid]&&arr[lMid]<=arr[mid]) {//如果此时左区间是单调增长

//判断value是否在左边区间,通过与区间另一端的值比较

//如果在左边区间

if(value>=arr[left]) {

//则在左区间做二分查找

int result = BSearch(arr,left,mid-1,value);

if(result!=-1) return result;//需要对返回值进行判断,否则递归没有出口

}else {//如果在右边区间,则要在右区间做二分查找

int result = BSearch(arr,mid+1,right,value);

if(result!=-1) return result;

}

}else {

//在左区间做二分查找

int result = BSearch(arr,left,mid-1,value);

if(result!=-1) return result;

}

}else if(value>arr[mid]) {//同理

int rMid = (right+mid)/2;

if(arr[mid]<=arr[rMid]&&arr[rMid]<=arr[right]) {//单调区间

if(value<=arr[right]) {//在

int result = BSearch(arr,mid+1,right,value);

if(result!=-1) return result;

}else {//不在

int result = BSearch(arr,left,mid-1,value);

if(result!=-1) return result;

}

}else {//非单调区间,一定在

int result = BSearch(arr,mid+1,right,value);

if(result!=-1) return result;

}

}else {

return mid;

}

}

return -1;

}

public static void main(String[] args) {

int arr[] = {9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8};

int i = BSearch(arr,0,arr.length-1,8);

System.out.println(i);

}

}

与普通二分查找的不同:

以上的查找对象为循环数组,而普通二分查找的对象为有序的普通数组;

正因为是循环数组,取中进行判断之后,目标值不一定在普通二分查找所设想的区间,需要进行判断,具体判断如下:

如何判断一段数组是单调递增呢?在该段数组的头、中间、尾三个位置p,m,q取三个值a[p], a[m], a[q],如果是单调递增则一定满足 a[p] >= a[m] >= a[q],否则则非单调递增。

判断目标元素下一步所在区间,有几种情况:

当 x > a[m] 时,

右半边是单调递增区间,并且x在此区间内,下一步则可在此右半边区间内查找

右半边是单调递增区间,并且x不在此区间内,下一步在左半边查找

右半边是非单调递增区间,则x必然在此区间内,下一步在右半边查找

当 x < a[m] 时, 同理类似

左半边是单调递增区间,并且x在此区间内,下一步则可在此左半边区间内查找

左半边是单调递增区间,并且x不在此区间内,下一步在右半边查找

左半边是非单调递增区间,则x必然在此区间内,下一步在左半边查找

判断是否在单调递增部分,只需与区间的另外一头的元素比较一下大小即可知道

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值