二分查找、大O表示法
* <第1章> 算法简介 </第1章>
* 1.2 二分查找 示例:{@link BinarySearch}
* 1.2.1 更佳的查找方式
* (1)一般而言,对于包含n个元素的列表,用二分查找最多需要log2 (n)步
* (2)对数运算是幂运算的逆运算
* log2 (8) = 3 <-> 2^3 = 8
* log2 (16) = 4 <-> 2^4 = 16
* log2 (32) = 5 <-> 2^5 = 32
* (3)仅当列表是有序的时候,二分查找才管用
* 1.2.2 运行时间
* (1)最多需要猜测的次数与列表长度相同,这被称为线性时间(linear time):O(n)
* (2)二分查找的运行时间为对数时间(或log时间):O(log n)
*
* 1.3 大O表示法
* 1.3.1 算法的运行时间以不同的速度增加。指出了算法有多块,也就是运行时间(或操作数)的增速
* 1.3.4 一些常见的大O运行时间
* (1)O(log n),也叫对数时间,这样的算法包括二分查找
* (2)O(n),也叫线性时间,这样的算法包括简单查找
* (3)O(n * log n),这样的算法包括快速排序 —— 一种速度较快的排序算法
* (4)O(n²),这样的算法包括简单排序 —— 一种速度较慢的排序算法
* (5)O(n!),这样的算法包括旅行商问题的解决方案 —— 一种非常慢的算法
*
* 1.4 小结
* (1)二分查找的速度比简单查找要快得多
* (2)O(log n)比O(n)快。需要搜索的元素越多,前者比后者就快得越多
* (3)算法运行时间并不以秒为单位
* (4)算法运行时间是从其增速的角度度量的
* (5)算法运行时间用大O表示法表示
/**
* 二分查找
*/
public class BinarySearch {
/**
* 接收一个有序数组和一个元素,返回指定的元素在数组中的位置
*
* @param arr
* @param searchValue
* @return
*/
private static int binarySearch(int[] arr, int searchValue) {
// 查找次数 最多为log2 (arr.length)
int searchCount = 0;
// low和high用于跟踪要在其中查找的列表部分
int low = 0;
int high = arr.length - 1;
// 只要范围没有缩小到只包含一个元素
while (low <= high) {
// 就检测中间元素
int mid = (low + high) / 2;
// 返回中间元素的值
int guess = arr[mid];
searchCount++;
// 如果值与输入的值相同,则返回位置
if (guess == searchValue) {
System.out.println("查找次数:" + searchCount);
return mid;
}
// 如果中间位置的值要大于输入的值,则向左缩小一半范围,反之向右
if (guess > searchValue) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = new int[1000];
for (int i = 0; i < arr.length; i++) {
arr[i] = i + 1;
}
System.out.println(binarySearch(arr, 25));
System.out.println(binarySearch(arr, 456));
System.out.println(binarySearch(arr, 788));
}
}