欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

二分查找-最基本的实现-小白初识

程序员文章站 2022-04-28 12:49:33
二分查找特别好理解,就类似于快排和归并当中用到的分治的思想,每次取中间数与目标数相比较,然后确定是大了还是小了,区间折半。 就比如: 小红选中了1-100中的某个数字(这个数字是56),要小明来猜,产生如下对话: 小明第一次猜测:68 小红:大了 小明第二次猜测:35 小红:小了 小明第三次猜测:5 ......

二分查找-最基本的实现-小白初识

 

二分查找特别好理解,就类似于快排和归并当中用到的分治的思想,每次取中间数与目标数相比较,然后确定是大了还是小了,区间折半。

就比如:

小红选中了1-100中的某个数字(这个数字是56),要小明来猜,产生如下对话:

小明第一次猜测:68

小红:大了

小明第二次猜测:35

小红:小了

小明第三次猜测:58

小红:大了

小明第四次猜测:49

小红:小了

小明第五次猜测:54

小红:小了

小明第六次猜测:56

小红:bingo!!!

 

我们可以看到在上面的对话中,小明每次猜测都可以缩小区间,直到回答正确。

二分查找就是这样的,比如我们现在有数组8,11,19,23,27,33,45,55,67,98,用二分查找如下图:

二分查找-最基本的实现-小白初识

  每次都可以缩小一半的区间,我们可以看到区间变化如下:

  二分查找-最基本的实现-小白初识

  当区间大小无限接近1的时候k = log2n,所以时间复杂度为o(logn)。

  

  是不是特别好理解,下面是我用java实现的简单的二分查找(备注:是最简单的实现,二分查找的变体很复杂还没掌握)

  

 1 package com.structure.search;
 2 
 3 /**
 4  * 二分查找法
 5  *
 6  * @author zhangxingrui
 7  * @create 2019-02-15 21:29
 8  **/
 9 public class binarysearch {
10 
11     public static void main(string[] args) {
12         int[] nums = new int[]{4, 6, 9, 19, 30, 40, 500, 3450, 50004, 4334343};
13         system.out.println(binarysearch(nums, 0, nums.length - 1, 30));
14         system.out.println(binarysearch(nums, 50004));
15     }
16 
17     /**
18      * @author: xingrui
19      * @description: 二分查找法(针对有序数组且不存在重复元素-递归方式实现)
20      * @date: 21:37 2019/2/15
21      */
22     private static int binarysearch(int[] nums, int p, int r, int k){
23         if(p > r)
24             return -1;
25 
26         int mid = (p + r) / 2;
27         if(nums[mid] == k)
28             return mid;
29 
30         if(k > nums[mid])
31             return binarysearch(nums, mid + 1, r, k);
32         else
33             return binarysearch(nums, p,  mid - 1, k);
34     }
35 
36     /**
37      * @author: xingrui
38      * @description: 二分查找法(针对有序数组且不存在重复元素-循环实现)
39      * @date: 21:37 2019/2/15
40      */
41     private static int binarysearch(int[] nums, int k){
42         int p = 0;
43         int r = nums.length - 1;
44         while (p <= r){
45             int mid = (p + r) / 2;
46 
47             if(nums[mid] == k)
48                 return mid;
49 
50             if(k > nums[p])
51                 p = mid + 1;
52             else
53                 r = mid - 1;
54         }
55         return -1;
56     }
57 
58 }

  代码很简单,其中需要注意的就是边界条件p<=r。

  从代码也可以看出,简单实现有很大的局限性,只能适用于有序的不存在重复数据的数组。

  并且二分查找不太适合小规模的数据查询(因为小规模的数据查询没有必要),这个好理解;同时呢,也不适合太大的数据的查询,这又是为啥子呢?

  就是因为上面提到的:二分查找适合底层使用数组的数据,但是数组呢又是一段连续的内存空间,当数据很大的时候如果要用二分查找,那么数据的底层实现就

  只能用数组,这样就不太好了。假设我的数据有一个g,那么我就要申请1个g的连续内存空间,妈哟,怕吃饱球了。