使用场景
- 要查找的元素集必须有序。
- 只需判断要查找的元素是否在集合中,对元素的位置无要求,因为如果元素在集合中有重复,则无法保证找到的是哪个。
JDK中的应用
- Arrays类
private static int binarySearch0(long[] a, int fromIndex, int toIndex, long key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;//相当于 /2,位运算效率高
long midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
- Collections类
private static final int BINARYSEARCH_THRESHOLD = 5000;
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
//列表元素支持随机快速访问的(如ArrayList)或者元素个数小于5000进行索引获取元素
//RandomAccess接口可以看做一个标志,实现了此接口的类,采用遍历方式效率高,相反,实现了Sequence List的类使用迭代器效率高
//对List特别是大量数据需要遍历的时候,推荐先判断是否实现了RandomAccess接口来选取最高效的遍历方式
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);//元素数>=5000或者实现了sequence List则使用迭代器获取元素
}
对于索引查找元素
//和数组遍历方式类似
private static <T> int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
int low = 0;
int high = list.size()-1;
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable<? super T> midVal = list.get(mid);
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}
通过迭代器查找元素
private static <T> int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
{
int low = 0;
int high = list.size()-1;
ListIterator<? extends Comparable<? super T>> i = list.listIterator();//获得双向列表迭代器
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable<? super T> midVal = get(i, mid);//通过双向列表迭代器获取指定索引的元素值
int cmp = midVal.compareTo(key);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found
}
private static <T> T get(ListIterator<? extends T> i, int index) {
T obj = null;
int pos = i.nextIndex();
if (pos <= index) { //指定索引位于迭代器后边则迭代器由开始位置逐步向后移动直至到指定索引位置
do {
obj = i.next();
} while (pos++ < index);
} else { //指定索引位于迭代器前边则迭代器由开始位置逐步向前移动直至到指定索引位置
do {
obj = i.previous();
} while (--pos > index);
}
return obj;
}
本文详细解析了二分查找算法的原理与应用,探讨了其在JDK中的具体实现,包括Arrays类和Collections类的使用场景。介绍了算法的运行机制,以及在不同数据结构上的性能表现。
1万+

被折叠的 条评论
为什么被折叠?



