码迷,mamicode.com
首页 > 编程语言 > 详细

基础算法介绍 —— 二分查找算法

时间:2016-07-10 06:21:18      阅读:286      评论:0      收藏:0      [点我收藏+]

标签:

    不知不觉在目前的公司待满3年了,打算回家找份工作。面试中被问到关于算法的题目:有哪些常见的查找算法?下来就把我所掌握的查找算法分享给大家,本文主要介绍二分查找算法。

    算法定义(摘自百度):二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

    上述定义可以看到这种二分查找算法是基于一个有序序列的算法,因此仅适用于已经排好顺序的情况下使用,否则需要先对序列进行排序。

    下面用Java代码来描述两种形式的二分查找算法:

     一、递归二分查找算法

 1 package algorithm;
 2 
 3 /**
 4  * 题目: 现有一个int型数组,其元素顺序排列。现给出一个数字,返回其在数组中的下标,如不存在返回-1.
 5  *
 6  */
 7 public class BinarySearch {
 8 
 9     // 用来记录查找次数
10     private static int count = 0;
11 
12     /**
13      * 
14      * @param number
15      *            待查找数字
16      * @param array
17      *            待查找数组
18      * @return 数组下标或-1
19      */
20     public static int getIndex(int number, int[] array) {
21         count = 0;
22         if (array == null || array.length == 0) { // 如果数组对象为空或者数组元素个数为0,直接返回-1
23             count++;
24             return -1;
25         }
26         return binarySearch(0, array.length - 1, array, number); // 调用递归方法
27     }
28 
29     /**
30      * 
31      * @param startIndex
32      *            起始下标
33      * @param endIndex
34      *            结束下标
35      * @param array
36      *            数组
37      * @param number
38      *            待查找数字
39      * @return 数组下标或-1
40      */
41     private static int binarySearch(int startIndex, int endIndex, int[] array, int number) {
42         count++;
43         // startIndex大于endIndex,说明已查找完成但并未查找到number
44         if (startIndex > endIndex) {
45             return -1;
46         }
47         // 获取中间元素下标
48         int index = (startIndex + endIndex) / 2;
49         // 获取中间元素数值
50         int _number = array[index];
51         // 比较中间元素与待查找数字
52         if (_number < number) {
53             // 如果中间元素数值小与待查找数字,则将查找范围缩小至 起始下标+1~中间元素下标
54             return binarySearch(index + 1, endIndex, array, number);
55         } else if (_number > number) {
56             // 如果中间元素数值大与待查找数字,则将查找范围缩小至 中间元素下标~中间元素下标-1
57             return binarySearch(startIndex, index - 1, array, number);
58         }
59         return index;
60     }
61 
62     public static int getCount() {
63         return count;
64     }
65 
66 }

 

 

    二、非递归二分查找算法:

 1 package algorithm;
 2 
 3 public class BinarySearchNonRecursive {
 4 
 5     // 记录循环次数
 6     private static int count = 0;
 7 
 8     public static int getIndex(int number, int[] array) {
 9 
10         // 判断数组是否为空,判断数组长度
11         if (array == null || array.length == 0) {
12             return -1;
13         }
14 
15         // 初始化起始下标、结束下标、返回值
16         int startIndex = 0;
17         int endIndex = array.length - 1;
18 
19         while (startIndex <= endIndex) {
20             count++;
21             int middleIndex = (startIndex + endIndex) / 2;
22             int _number = array[middleIndex];
23 
24             if (_number < number) {
25                 // _number小于number,下次循环查找的起始下标为middleIndex + 1;
26                 startIndex = middleIndex + 1;
27             } else if (_number > number) {
28                 // _number大于number,下次循环查找的结束下标为middleIndex - 1;
29                 endIndex = middleIndex - 1;
30             } else {
31                 // _number等于number,查找到数字,返回结果
32                 return middleIndex;
33             }
34         }
35 
36         // 当startIndex > endIndex时,说明未查找到数字。结束循环,返回-1
37         return -1;
38 
39     }
40 
41     public static int getCount() {
42         return count;
43     }
44 
45 }

 

    下面是测试代码:

 1 package algorithm;
 2 
 3 import org.junit.Before;
 4 import org.junit.Test;
 5 
 6 public class BinarySearchTest {
 7 
 8     private int[] array;
 9     private int[] testArray;
10 
11     @Before
12     public void setUp() throws Exception {
13         array = new int[] { 1, 2, 3, 9, 15, 26, 37, 48, 69, 110, 116, 117, 244, 374, 529 };
14         testArray = new int[] { 1, 5, 3, 9, 37, 48, 22, 69, 244, 529, -888 };
15     }
16 
17     @Test
18     public void test() {
19 
20         System.out.println("====递归二分查找算法====");
21         for (int i = 0; i < testArray.length; i++) {
22             System.out.println("测试数值为 : " + testArray[i]);
23 
24             int result = BinarySearch.getIndex(testArray[i], array);
25 
26             System.out.println("查找结果为 : " + result);
27             System.out.println("查询次数 : " + BinarySearch.getCount() + "\n");
28 
29         }
30         System.out.println("\n====非递归二分查找算法====");
31         for (int i = 0; i < testArray.length; i++) {
32             System.out.println("测试数值为 : " + testArray[i]);
33 
34             int result = BinarySearchNonRecursive.getIndex(testArray[i], array);
35 
36             System.out.println("查找结果为 : " + result);
37             System.out.println("循环次数 : " + BinarySearchNonRecursive.getCount() + "\n");
38 
39         }
40 
41     }
42 
43 }

 

    输出测试结果:

====递归二分查找算法====
测试数值为 : 1
查找结果为 : 0
查询次数 : 4

测试数值为 : 5
查找结果为 : -1
查询次数 : 5

测试数值为 : 3
查找结果为 : 2
查询次数 : 4

测试数值为 : 9
查找结果为 : 3
查询次数 : 2

测试数值为 : 37
查找结果为 : 6
查询次数 : 4

测试数值为 : 48
查找结果为 : 7
查询次数 : 1

测试数值为 : 22
查找结果为 : -1
查询次数 : 5

测试数值为 : 69
查找结果为 : 8
查询次数 : 4

测试数值为 : 244
查找结果为 : 12
查询次数 : 4

测试数值为 : 529
查找结果为 : 14
查询次数 : 4

测试数值为 : -888
查找结果为 : -1
查询次数 : 5


====非递归二分查找算法====
测试数值为 : 1
查找结果为 : 0
循环次数 : 4

测试数值为 : 5
查找结果为 : -1
循环次数 : 4

测试数值为 : 3
查找结果为 : 2
循环次数 : 4

测试数值为 : 9
查找结果为 : 3
循环次数 : 2

测试数值为 : 37
查找结果为 : 6
循环次数 : 4

测试数值为 : 48
查找结果为 : 7
循环次数 : 1

测试数值为 : 22
查找结果为 : -1
循环次数 : 4

测试数值为 : 69
查找结果为 : 8
循环次数 : 4

测试数值为 : 244
查找结果为 : 12
循环次数 : 4

测试数值为 : 529
查找结果为 : 14
循环次数 : 4

测试数值为 : -888
查找结果为 : -1
循环次数 : 4

    从console内容可以看出,两种不同形式二分查找算法的结果是相同的。

    注:一些情况下同样的测试数据,递归二分查找和非递归二分查找的执行次数不一致,这是因为在非递归二分查找算法中,当startIndex>endIndex时,没有进入while语句中,count没有自增;而在递归二分查找算法中,startIndex>endIndex作为一个结束条件,是在递归函数内部判断的,因此记录调用递归函数次数的count自增。这里笔者没有对执行count++的位置进行特殊处理,是为了更好的体现出两种形式的算法的执行步骤。

    总结:两种形式的二分查找算法本质思想都是一样的,即每次将查找数据与中间元素对比大小,未匹配则缩小二分之一的查找范围,直到最终查找到元素或返回未查找到结果。

    最后,希望本文能帮助到有需要的朋友,同时也欢迎大家批评指正文中的不足之处。

 

基础算法介绍 —— 二分查找算法

标签:

原文地址:http://www.cnblogs.com/zfLee/p/5654296.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!