算法_001_二分查找算法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法_001_二分查找算法相关的知识,希望对你有一定的参考价值。
二分查找算法是在有序数组中用到的较为频繁的一种算法,在未接触二分查找算法时,最通用的一种做法是,对数组进行遍历,跟每个元素进行比较,其时间为O(n).但二分查找算法则更优,因为其查找时间为O(lgn),譬如数组{1, 2, 3, 4, 5, 6, 7, 8, 9},查找元素6,用二分查找的算法执行的话,其顺序为:
1.第一步查找中间元素,即5,由于5<6,则6必然在5之后的数组元素中,那么就在{6, 7, 8, 9}中查找,
2.寻找{6, 7, 8, 9}的中位数,为7,7>6,则6应该在7左边的数组元素中,那么只剩下6,即找到了。
二分查找算法就是不断将数组进行对半分割,每次拿中间元素和goal进行比较。
二分查找法——Java代码的实现
1、前提:二分查找的前提是需要查找的数组必须是已排序的,我们这里的实现默认为升序
2、原理:将数组分为三部分,依次是中值(所谓的中值就是数组中间位置的那个值)前,中值,中值后;将要查找的值和数组的中值进行比较,若小于中值则在中值前面找,若大于中值则在中值后面找,等于中值时直接返回。然后依次是一个递归过程,将前半部分或者后半部分继续分解为三部分。可能描述得不是很清楚,若是不理解可以去网上找。从描述上就可以看出这个算法适合用递归来实现,可以用递归的都可以用循环来实现。所以我们的实现分为递归和循环两种,可以根据代码来理解算法
3、实现:代码如下
- package org.cyxl.algorithm.search;
- /**
- * 二分查找
- * @author cyxl
- *
- */
- public class BinarySearch {
- private int rCount=0;
- private int lCount=0;
- /**
- * 获取递归的次数
- * @return
- */
- public int getrCount() {
- return rCount;
- }
- /**
- * 获取循环的次数
- * @return
- */
- public int getlCount() {
- return lCount;
- }
- /**
- * 执行递归二分查找,返回第一次出现该值的位置
- * @param sortedData 已排序的数组
- * @param start 开始位置
- * @param end 结束位置
- * @param findValue 需要找的值
- * @return 值在数组中的位置,从0开始。找不到返回-1
- */
- public int searchRecursive(int[] sortedData,int start,int end,int findValue)
- {
- rCount++;
- if(start<=end)
- {
- //中间位置
- int middle=(start+end)>>1; //相当于(start+end)/2
- //中值
- int middleValue=sortedData[middle];
- if(findValue==middleValue)
- {
- //等于中值直接返回
- return middle;
- }
- else if(findValue<middleValue)
- {
- //小于中值时在中值前面找
- return searchRecursive(sortedData,start,middle-1,findValue);
- }
- else
- {
- //大于中值在中值后面找
- return searchRecursive(sortedData,middle+1,end,findValue);
- }
- }
- else
- {
- //找不到
- return -1;
- }
- }
- /**
- * 循环二分查找,返回第一次出现该值的位置
- * @param sortedData 已排序的数组
- * @param findValue 需要找的值
- * @return 值在数组中的位置,从0开始。找不到返回-1
- */
- public int searchLoop(int[] sortedData,int findValue)
- {
- int start=0;
- int end=sortedData.length-1;
- while(start<=end)
- {
- lCount++;
- //中间位置
- int middle=(start+end)>>1; //相当于(start+end)/2
- //中值
- int middleValue=sortedData[middle];
- if(findValue==middleValue)
- {
- //等于中值直接返回
- return middle;
- }
- else if(findValue<middleValue)
- {
- //小于中值时在中值前面找
- end=middle-1;
- }
- else
- {
- //大于中值在中值后面找
- start=middle+1;
- }
- }
- //找不到
- return -1;
- }
- }
4、测试代码
- package org.cyxl.algorithm.search.test;
- import org.cyxl.algorithm.search.BinarySearch;
- import org.junit.Test;
- public class BinarySearchTest {
- @Test
- public void testSearch()
- {
- BinarySearch bs=new BinarySearch();
- int[] sortedData={1,2,3,4,5,6,6,7,8,8,9,10};
- int findValue=9;
- int length=sortedData.length;
- int pos=bs.searchRecursive(sortedData, 0, length-1, findValue);
- System.out.println("Recursice:"+findValue+" found in pos "+pos+";count:"+bs.getrCount());
- int pos2=bs.searchLoop(sortedData, findValue);
- System.out.println("Loop:"+findValue+" found in pos "+pos+";count:"+bs.getlCount());
- }
- }
5、总结:这种查找方式的使用场合为已排序的数组。可以发现递归和循环的次数是一样的
以上是关于算法_001_二分查找算法的主要内容,如果未能解决你的问题,请参考以下文章
Python 查找算法_众里寻他千百度,蓦然回首那人却在灯火阑珊处(线性二分,分块插值查找算法)