java算法基础--二分查找

[b]基本概念[/b]:二分查找又称折半查找,要求待查找数组有序;优点是比较次数少,查找速度快;其缺点是要求待查表为有序表。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。

[b]基本思想[/b]:首先假设已排序好的序列是升序,将要查找的元素与序列中间的元素比较,若相等,则查找成功;若待查找元素比中间元素大,则查找除去中间元素的后半部分序列,反之,则查找去除中间元素的前半部分序列,直到查到相同的元素或者所查找的序列范围为空为止。

[b]实现思路[/b]:还是假设数组元素是升序的,将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的value作比较,如果value=a[n/2]则找到value,算法终止。如 果value<a[n/2],则我们只要在数组a的左半部继续查找value。如果value>a[n/2],则我们只要在数组a的右半部继续查找value。

[b]性能分析[/b]:若数组长度为n,则算法复杂度为O(log n)

[b]具体代码:(非递归版)[/b]

public class binarySearchTest {

public static int binarySearch(int[] a,int value)
{
//若数组为空,则返回-1
if(a.length == 0 )
{
return -1;
}

int low = 0;
int high = a.length - 1;

while(low <= high)
{
int mid = (low + high) / 2;//这个是有BUG的

//打印中间元素选取过程,只是显示过程,与算法本身无关
for(int i = 0;i < a.length;i++)
{
System.out.print(a[i]);
if(i == mid)
{
System.out.print("#");//用#号表示中间元素
}
System.out.print(" ");//各个元素用空格隔开
}
System.out.println();//每次选取过程换行

//核心
if(value == a[mid])
{
return mid;
}
else if(value > a[mid])
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}

return -1; //不存在该元素则返回-1
}
public static void main(String[] args) {
int[] a={1,3,4,5,8,7,9,11,15};
System.out.println(binarySearch(a,9));

}
}


[b]具体代码:(递归版)[/b]

public class binarySearchRecursionTest {

public static int binarySearchRecursion(int[] a,int fromIndex,int toIndex,int key)
{
if(fromIndex > toIndex) return -1;
int midIndex = (fromIndex + toIndex) / 2;//这个是有BUG的
int midVal = a[midIndex];

if(midVal > key)
{
return binarySearchRecursion(a,fromIndex,midIndex - 1,key);
}
else if(midVal <key)
{
return binarySearchRecursion(a, midIndex + 1, toIndex, key);
}
else
{
return midIndex;
}

}

public static void main(String[] args) {
int[] a={1,3,4,5,8,7,9,11,15};
System.out.println(binarySearchRecursion(a,0,a.length,9));
}
}


[b]代码分析[/b]:[color=red]早前的jdk中Arrays类中的二分查找存在一个临界值的bug,bug在代码中的int mid = (low + high) / 2;当low + high大于正int范围时就会溢出,会抛出ArrayIndexOutOfBoundsException 异常。[/color]

[b]解决办法:将int mid = (low + high) / 2修改为
int mid = low + ((high - low) / 2);
或者 int mid = (low + high) >>> 1;(最新的java.util.Arrays中用的是这个办法)[/b]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值