搜索之线性搜索和二分搜索
今天介绍下搜索的方法,其实对于今天介绍的两种搜索方式是很简单的,尤其是线性搜索,但是本着完整性的心态,还是不想把搜索这章中两种简单的方法漏掉,那就稍微简单介绍下吧。
注意:本博文介绍的搜索都是不含重复元素的搜索,至于重复下的搜索,只需用到另外一个数据结构用来存放这多个重复元素的下标就行了,就不多作介绍。
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[n]=key;
while(A[i]与key不相等)i++;f(i达到了n)return Not_Found;
return i;
key为要搜索的值,将key插入末尾,这样在下标从0~n的元素中,可能有两个位置的元素等于key,(要注意的是,0~n-1菜蔬数组的有效范围,A[n]是标记)这样从头开始遍历比较,不等则i++比较下一个,因为最终A[n]=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;elsereturn -1;
当然还有递归形式下的二分法,就不介绍了,总之知道二分原理就行,而且在实际比赛和开发中我们也并不需要自己从头写二分查找,STL中有很多方法,具体可以参考:STL中与二分查找有关的四个函数
PS:从写上一篇博文的大年初三后忙着走亲戚,聚会啥,耽误了学习和博客,更新慢了~虽然目前也没人看我的这个系列博客,但是我还是要自己监督自己~
搜索之线性搜索和二分搜索相关推荐
- 《程序设计与数据结构》第八周学习总结
学号 20172326 <程序设计与数据结构>第八周学习总结 教材学习内容总结 后绑定在程序执行时执行 多态性可由继承与接口实现 排序有选择法排序与插入法排序 搜索分为线性搜索与二分搜索 ...
- java 线性回归算法_线性搜索或顺序搜索算法在Java中如何工作? 示例教程
java 线性回归算法 大家好,之前,我讨论了二进制搜索算法的工作原理,并分享了在Java中实现二进制搜索的代码. 在那篇文章中,有人问我是否还有其他搜索算法? 如果数组中的元素未排序,又该如何使用它 ...
- 线性搜索或顺序搜索算法在Java中如何工作? 示例教程
大家好,我之前谈到了二进制搜索算法的工作原理,并分享了在Java中实现二进制搜索的代码. 在那篇文章中,有人问我是否还存在其他搜索算法? 如果数组中的元素未排序,又如何使用二进制搜索算法,该如何搜索呢 ...
- 我写了一个套路,助你随心所欲运用二分搜索
后台回复进群一起刷力扣 点击卡片可搜索关键词???? 读完本文,可以去力扣解决如下题目: 875.爱吃香蕉的珂珂(Medium) 1011.在D天内送达包裹的能力(Medium) 我们前文 我作了首诗 ...
- 20172310 2017-2018-2 《程序设计与数据结构》第八周学习总结
20172310 2017-2018-2 <程序设计与数据结构>第八周学习总结 教材学习内容总结 我的总结主要是按照课本的顺序,对一些重要的知识点做出的总结和记录,方便后期的查看,当然其中 ...
- js 冒泡排序_JS 里的简易算法和数据结构之复杂度
原文:https://www.freecodecamp.org/news/the-complexity-of-simple-algorithms-and-data-structures-in-java ...
- 20172329 2017-2018-2《程序设计与数据结构》课程总结
作者:lalalouye(20172329王文彬) 2017-2018年大一Java程序设计课程总目录:第一周 第二周 第三周 第四周 第五周 第六周 第七周 第八周 第九周 第十周 第十一周 实验一 ...
- Algorithms and Data Structures I
Vintage 80s office by Mohamed Chahin 更好的阅读体验请访问 Algorithms and Data Structures I Acquire fundamental ...
- Python基本手册
Python基本手册 关键词: Python Python基本手册 常见内置函数 标准库 爬虫 1 GET 2 POST 3 Headers 字符串 模块 1 定义模块 2 常用的字符串方法 列表li ...
最新文章
- Ubuntu 安装flash
- Cisco 2950 系列交换机实例配置
- 娱美德投入千万研发 揭秘韩国第一游戏引擎
- python源码文件_从源代码生成Python文件
- MySQL 调用存储过程
- 华为手机打字声音怎么开启_华为手机这5个超实用小功能,记得要开启,谁用都说好...
- 意外收获字节跳动内部资料,一篇文章帮你解答
- iOS-关于iOS开发架构的搭建
- 孙鑫VC学习笔记:第二讲 掌握C++
- 关于BetterScroll 2.0版本出现BScroll is not defined 的解决方案
- 计算机软件考试高级工程师,软考高级工程师容易考吗
- 光纤跳线的类型和区别?
- Intel核芯显卡微架构浅析
- matlab读多个excel,读取excel 多个表格文件数据-怎样利用matlab去读取一个excel表中多个sheet的数......
- FPGA VIVADO仿真详解 TEST BENCH
- RTFM(Read The Fucking Manual)的意思
- 内网穿透-Frp(1)使用樱花Frp(Sakura Frp)进行免费的内网穿透操作步骤
- Spark各版本及相关软件下载
- 基于区域协方差的结构保持图像平滑
- 韩国电信在物联网领域的多重探索经验