import java.util.Arrays;
/**
 * 二分查找
 * <p>
 * 首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;
 * 否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
 * 重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功
 */
public class BinarySearch {
    public static void main(String[] args) {
        // 测试次数
        int times = 500000;
        int maxNum = 100;
        int maxSize = 100;
        for (int i = 0; i < times; i++) {
            // 生成随机数组
            int[] arr = generateArray(maxNum, maxSize);
            // 排序
            Arrays.sort(arr);
            // 比较查找结果
            if (binarySearch(arr, 50) != arrayContains(arr, 50)) {
                System.out.println("Sort failed!!!");
                System.out.println(binarySearch(arr, 50));
                System.out.println(arrayContains(arr, 50));
                System.out.println(Arrays.toString(arr));
                return;
            }
        }
        System.out.println("Sort success");
    }
    /**
     * 数组是否包含给定数值
     *
     * @param arr 数组
     * @param key 给定数值
     * @return 是否包含
     */
    private static boolean arrayContains(int[] arr, int key) {
        if (arr == null || arr.length == 0) {
            return false;
        }
        for (int value : arr) {
            if (value == key) {
                return true;
            }
        }
        return false;
    }
    /**
     * 二分查找
     *
     * @param arr 数组
     * @param key 给定数值
     * @return 是否包含
     */
    private static boolean binarySearch(int[] arr, int key) {
        if (arr == null || arr.length == 0) {
            return false;
        }
        int left = 0;
        int mid = 0;
        int right = arr.length - 1;
        // 第一种写法
        while (left < right) {
            mid = left + ((right - left) >> 1);
            if (arr[mid] == key) {
                return true;
            } else if (arr[mid] > key) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return arr[left] == key;
        // 第二种写法
//        while (left <= right) {
//            mid = left + ((right - left) >> 1);
//            if (arr[mid] == key) {
//                return true;
//            } else if (arr[mid] > key) {
//                right = mid - 1;
//            } else {
//                left = mid + 1;
//            }
//        }
//        return false;
    }
    /**
     * 生成随机数组
     *
     * @param maxNum  最大数
     * @param maxSize 数组最大大小
     * @return 随机数组
     */
    private static int[] generateArray(int maxNum, int maxSize) {
        int[] arr = new int[(int) (maxSize * Math.random())];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (maxNum * Math.random()) - (int) (maxNum * Math.random());
        }
        return arr;
    }
}