搜索之线性搜索和二分搜索
2017-02-04 22:45
260 查看
今天介绍下搜索的方法,其实对于今天介绍的两种搜索方式是很简单的,尤其是线性搜索,但是本着完整性的心态,还是不想把搜索这章中两种简单的方法漏掉,那就稍微简单介绍下吧。
注意:本博文介绍的搜索都是不含重复元素的搜索,至于重复下的搜索,只需用到另外一个数据结构用来存放这多个重复元素的下标就行了,就不多作介绍。
其实可以看到就是一个简单的for循环,但是就是这么简单的算法,也有优化的地方,这也许就是算法的魅力所在。
其优化的方面在于判断次数的优化,这里我们可以看到,for循环中每次变量i变化时,要进行两次的比较,首先是i与数组边界n的比较和A[i]和key的比较。
我们优化的方法就是设置一个标记,一个有个特殊值的元素,借助这种编程技巧,我们能达到简化循环控制等诸多目的。在线性搜索中,我们吧标记放在数组的末尾,其具体的实现方法如下:
key为要搜索的值,将key插入末尾,这样在下标从0~n的元素中,可能有两个位置的元素等于key,(要注意的是,0~n-1菜蔬数组的有效范围,A
是标记)这样从头开始遍历比较,不等则i++比较下一个,因为最终A
=key,所以能保证的是while肯定是会结束的,但是重点就是while循环是在哪里结束退出循环的,如果在i=n退出时,那说明之前的0~n-1并没有元素只等于key,那么说明原来的数组的有效范围内找不到该值。反之,当退出循环时,i不等于n,则说明在有效范围找到了该值。这样的话,每次for循环中i变化时,只需要进行一次A[i]与key的比较就行了,最后再加一次i与n的比较就行。(这里是我平时没有注意到的,也是算法深深吸引我的地方,优中求优)
线性搜索的时间复杂度为O(n),但是在引用了标记后效率可以提升常数倍,在处理大规模数据时会有比较明显的效果。
2.二分搜索
二分搜索又叫二分查找,其看名字就可以想到该算法的实现步骤,就是每次将有效的查找范围分为两半,并且每次将范围减少一半,其中每次通过将要查找的值key与有效范围中间的值比较来判断是否已经找到该值,或者需要在剩下的哪一半中继续查找。其基本的源代码如下:
但是要注意的一点是,在进行二分查找之前,必须保证元素是有序排列的,这样才能根据要查找的值key与中间值的比较结果来判断需要在哪一半继续查找或者查找结束。
举个例子,比如对于已知的数组1 2 3 4 5 6 7 8 ,想要查找7的位置,那么一开始start=0,end=8,第一次查找mid=(start+end)/2=4,找到A[4]=5,这时在元素已经升序排列的情况下,那么肯定可以得到7的位置在当前中间位置4之后,所以将start置为4+1=5,这时有效范围为下标从5到8,然后继续去中间位置A[(5+8)/2]=A[6]=7,这时找到该值,返回位置6.至于不存在该值时,由于不存在,那么永远不会有A[mid]==key,那么就不会返回return mid,这样的户,while不断循环,必然导致start不断变大或者end不断变小,当start>=end时,就退出循环,这时便说明找到不到该值。
其实二分查找有很多细节方面的注意点,比如上面的一种二分查找就是将end初始化为数组元素的最后一个位置的后一个位置,当然也可以将end=n-1,那么就有了以下的源代码:
当然还有递归形式下的二分法,就不介绍了,总之知道二分原理就行,而且在实际比赛和开发中我们也并不需要自己从头写二分查找,STL中有很多方法,具体可以参考:STL中与二分查找有关的四个函数
PS:从写上一篇博文的大年初三后忙着走亲戚,聚会啥,耽误了学习和博客,更新慢了~虽然目前也没人看我的这个系列博客,但是我还是要自己监督自己~
注意:本博文介绍的搜索都是不含重复元素的搜索,至于重复下的搜索,只需用到另外一个数据结构用来存放这多个重复元素的下标就行了,就不多作介绍。
1.线性搜索
线性搜索看名字就看出来了,是最简单的搜索方式,顾名思义,就是从头到尾一个个查找搜索,其基本的算法模式如下:LinearSearch() for(i从0到n-1) if(A[i]与key相等) return i; return Not_Found;
其实可以看到就是一个简单的for循环,但是就是这么简单的算法,也有优化的地方,这也许就是算法的魅力所在。
其优化的方面在于判断次数的优化,这里我们可以看到,for循环中每次变量i变化时,要进行两次的比较,首先是i与数组边界n的比较和A[i]和key的比较。
我们优化的方法就是设置一个标记,一个有个特殊值的元素,借助这种编程技巧,我们能达到简化循环控制等诸多目的。在线性搜索中,我们吧标记放在数组的末尾,其具体的实现方法如下:
LinearSearch() i=0; A =key; while(A[i]与key不相等) i++; f(i达到了n) return Not_Found; return i;
key为要搜索的值,将key插入末尾,这样在下标从0~n的元素中,可能有两个位置的元素等于key,(要注意的是,0~n-1菜蔬数组的有效范围,A
是标记)这样从头开始遍历比较,不等则i++比较下一个,因为最终A
=key,所以能保证的是while肯定是会结束的,但是重点就是while循环是在哪里结束退出循环的,如果在i=n退出时,那说明之前的0~n-1并没有元素只等于key,那么说明原来的数组的有效范围内找不到该值。反之,当退出循环时,i不等于n,则说明在有效范围找到了该值。这样的话,每次for循环中i变化时,只需要进行一次A[i]与key的比较就行了,最后再加一次i与n的比较就行。(这里是我平时没有注意到的,也是算法深深吸引我的地方,优中求优)
线性搜索的时间复杂度为O(n),但是在引用了标记后效率可以提升常数倍,在处理大规模数据时会有比较明显的效果。
2.二分搜索
二分搜索又叫二分查找,其看名字就可以想到该算法的实现步骤,就是每次将有效的查找范围分为两半,并且每次将范围减少一半,其中每次通过将要查找的值key与有效范围中间的值比较来判断是否已经找到该值,或者需要在剩下的哪一半中继续查找。其基本的源代码如下:int Binary_search(int a[],int n,int key) { int start=0,end=n,mid; //end指向搜索范围中最后一个元素的后一个位置 while(start<end) { mid=(start+end)/2; if(a[mid]==key) return mid; if(key>a[mid]) start=mid+1; else end=mid; //注意::在key<a[mid],有效范围为start~mid-1,所以这里en置为mid, } return -1; }
但是要注意的一点是,在进行二分查找之前,必须保证元素是有序排列的,这样才能根据要查找的值key与中间值的比较结果来判断需要在哪一半继续查找或者查找结束。
举个例子,比如对于已知的数组1 2 3 4 5 6 7 8 ,想要查找7的位置,那么一开始start=0,end=8,第一次查找mid=(start+end)/2=4,找到A[4]=5,这时在元素已经升序排列的情况下,那么肯定可以得到7的位置在当前中间位置4之后,所以将start置为4+1=5,这时有效范围为下标从5到8,然后继续去中间位置A[(5+8)/2]=A[6]=7,这时找到该值,返回位置6.至于不存在该值时,由于不存在,那么永远不会有A[mid]==key,那么就不会返回return mid,这样的户,while不断循环,必然导致start不断变大或者end不断变小,当start>=end时,就退出循环,这时便说明找到不到该值。
其实二分查找有很多细节方面的注意点,比如上面的一种二分查找就是将end初始化为数组元素的最后一个位置的后一个位置,当然也可以将end=n-1,那么就有了以下的源代码:
int start=0,end=n-1; //end指向搜索范围中最后一个元素的位置 int mid=(start+end)/2; while(end>=start && a[mid]!=key) { cout<<"start="<<start<<" mid="<<mid<<" end="<<end<<endl; if(a[mid]>key) end=mid-1; else start=mid+1; mid=(start+end)/2; } if(end>=start) return mid; else return -1;
当然还有递归形式下的二分法,就不介绍了,总之知道二分原理就行,而且在实际比赛和开发中我们也并不需要自己从头写二分查找,STL中有很多方法,具体可以参考:STL中与二分查找有关的四个函数
PS:从写上一篇博文的大年初三后忙着走亲戚,聚会啥,耽误了学习和博客,更新慢了~虽然目前也没人看我的这个系列博客,但是我还是要自己监督自己~
相关文章推荐
- (1)线性查找和二分搜索
- 搜索算法--线性搜索、二分搜索、内插搜索、剪枝搜索
- 算法设计技巧与分析(1)二分搜索的前提——线性搜索
- 最大化平均值---二分搜索
- 二分搜索--控制精度--hdu2199 Can you solve this equation
- 一步一步学习java数组学习(二分搜索)
- 二分搜索与一般搜索
- POJ - 2976 Dropping tests(二分搜索:最大化平均值)
- HDOJ Can you find it? 2141(二分搜索)
- hiho字体大小设置(二分搜索)
- 使用迭代器进行二分搜索
- POJ 3273 Monthly Expense (二分搜索)
- 【leetcode】34Search for a Range(二分搜索上下界)
- Jan's light oj 01--二分搜索篇
- 冒泡排序 二分查找 快速排序 线性查找
- 二分搜索求利率近似解
- js实现二分搜索的两种方法
- 实验一 分治与递归―二分搜索 java实现
- poj 2112 Optimal Milking(最大费用流+dinic算法+二分搜索)
- poj 1759 Garland (二分搜索之其他)