引言

  在开始之前首先可以先思考一下假如没有查找算法会是什么情况?所有数据结构都需要全部遍历一遍,每次都一遍又一遍的查,从本质而言查找算法就是为了提高效率。

  经过前人一代又一代的努力,目前的查找算法大致可以分为静态查找和动态查找。从名字上就很容易理解,静态查找通俗而言就是查找的时候数据不变,而动态查找也可以理解为查找的时候数据发生了改变。

  所以这就衍生了个推论,即静态查找和动态查找算法不能通用,或者说在静态算法中使用动态算法不划算。

  还可以从顺序的维度来划分,可以划分为无序查找和有序查找。当然其中的顺序是相对的,也就是说是依据某个参照物来比是有序或者无序。

  平时大多数开发人员所编写的代码基本都是顺序查找,也就是说O(n)操作。

  接下去就让我们站在前人的肩膀上,改进一下我们的思路吧。

二分查找

  二分查找,平时在工作中应该或多或少都有听说过,这也算是除了顺序查找以外,最容易想到的查找算法了。

  核心思路就是不断的除2,直到找到为止,就类似于以前电视节目里面的猜价格,每次猜中间的值。

  但是这个算法前提就是给定的数据必须是有序的,如果无序的话,就没有办法决定是选上半截的中间值或是选下半截的中间值了。

  在这里贴上一张与顺序查找的对比图:

  

  代码实现:

  

  public class BinarySearch
{
public static int Demo(List<int> data, int key)
{
int low = , mid = ;
int high = data.Count - ;
while (low <= high)
{
mid = (low + high) / ;
if (data[mid] == key)
{
return mid;
}
else if (data[mid] > key)
{
high = mid - ;
}
else if (data[mid] < key)
{
low = mid + ;
}
}
return -;
}
}

BinarySearch

  使用场景:

  .net已经提供的二分实现:BinarySearch

  二分法适用于数据较为连续较为均匀的,如内存地址,索引等

  算法复杂度 O(logn)

斐波那契查找

  提到斐波那契,具有大学经历的小伙伴一定不会陌生,第一反应肯定就是斐波那契数列,而斐波那契查找可能有些小伙伴就没有听过了。

  其实这个查找就是利用了斐波那契的黄金比例来减少分的次数。可以理解为是二分法的一个优化。

  ps:没有找到gif,来个png先顶上(捂脸)

  

  从图中可以看到斐波那契查找改变的是如何切分数据的问题。

  代码如下:

  public class FibonacciSearch
{
public static int Demo(List<int> data, int key)
{
int low = ;
int high = data.Count - ; var myFibonacciSearch = new List<int>(new int[]);
myFibonacciSearch[] = ;
myFibonacciSearch[] = ;
for (int i = ; i < myFibonacciSearch.Count; ++i)
{
myFibonacciSearch[i] = myFibonacciSearch[i - ] + myFibonacciSearch[i - ];
} int relativePosition = ;
while (data.Count > myFibonacciSearch[relativePosition] - )
{
++relativePosition;
}
int[] temp = new int[myFibonacciSearch[relativePosition] - ];
data.CopyTo(temp); for (int i = data.Count; i < myFibonacciSearch[relativePosition] - ; ++i)
{
temp[i] = data[data.Count - ];
} while (low <= high)
{
int mid = low + myFibonacciSearch[relativePosition - ] - ;
if (key < temp[mid])
{
high = mid - ;
relativePosition -= ;
}
else if (key > temp[mid])
{
low = mid + ;
relativePosition -= ;
}
else
{
if (mid < data.Count)
{
return mid;
}
else
{
return data.Count - ;
}
}
}
return -;
}
}

FibonacciSearch

  算法复杂度 O(logn)

插值查找

  这个可能一般的小伙伴没有听过这个查找算法,其实这个算法也是定义了如何去找。

  可以类比为查找字典的时候我们找X开头的单词总是会从后面开始找而找B开头的则会从头开始找。

  插值查找就是定义了这么一个规则,通过公式    搜索键值 = left + parseInt( ( key - data[left] ) / ( data[right] - data[left] ) )*( right - left ) )

  然后不停的切分,直到找到所需要的内容。

  下面附上维基百科里提供的JS程序段,感兴趣的可以翻译为自己常用的语言。

  

 var interpolationSearch = function(data, key){
var left = ;
var right = data.length - ;
var m = ;
while(left <= right){
var m = parseInt((right - left)*(key - data[left])/(data[right] - data[left])) + left;
if( m < left || m > right)
break;
if(key < data[m])
right = m - ;
else if(key > data[m])
left = m + ;
else
return m;
}
return -;
}; //執行
var data = getRandomData();
quickSort(data, , data.length-);
interpolationSearch(data, ); // (data, key)

interpolationSearch

分块查找

  顺序查找的增强版,有点桶排序的味道。

  分开查找的要求就是分成N块每块内部可以无序但是块与块之间必须有序。

  这个就可以利用cpu的并行并发进行查找加速。

  如下图所示:

  

  

哈希查找

  哈希对于各位开发小伙伴一定不陌生,哈希查找目的也很简单就是用空间来换时间。

  1)       用给定的哈希函数构造哈希表;

  2)       根据选择的冲突处理方法解决地址冲突;

  3)       在哈希表的基础上执行哈希查找。

  实用场景也很多:

  1.文件查找

    比如百度网盘秒传功能,适用诸如sha256等哈希算法就可以快速的找到文件是否存在(md5冲突率相对较高,不适合用做文件判重)

  2.网络通信(微信消息算法)

    数据中组装一个随机的int值然后再组装所需要的参数如id 组装成long,即后半截有序前半截随机,再使用基数对比法,只对比后部分。最终实现数据不重复的情况下查找id

    用图解释就是

    

    有点类似于雪花算法的感觉。

树查找

  .net提供了教科书式的用法 感兴趣可以自行查看core源码中的SortedDictionary

  二叉树的查询性能还行,平均查询是O(Logn),但是最坏的情况会退化为O(n),在二叉树的基础上,

  又出来什么AVL,2-3-4,2-3(就是红黑,准确说 红黑树是2-3树的简单高效的实现)等等.

  而B/B+平衡树其实是2-3查找树的扩展,在文件系统中好用. 所以树而言,只管用,你自己的实现根本跟不上大佬们的性能.

  

【摩天大楼平地起】基础篇 09 简述N种查找算法的更多相关文章

  1. iOS系列 基础篇 09 开关、滑块和分段控件

    iOS系列 基础篇 09 开关.滑块和分段控件 目录: 案例说明 开关控件Switch 滑块控件Slider 分段控件Segmented Control 1. 案例说明 开关控件(Switch).滑块 ...

  2. Java多线程系列--“基础篇”09之 interrupt()和线程终止方式

    概要 本章,会对线程的interrupt()中断和终止方式进行介绍.涉及到的内容包括:1. interrupt()说明2. 终止线程的方式2.1 终止处于“阻塞状态”的线程2.2 终止处于“运行状态” ...

  3. Java多线程系列 基础篇09 Object.wait/notifyJVM源码实现

    转载 https://www.jianshu.com/p/f4454164c017 作者 占小狼 最简单的东西,往往包含了最复杂的实现,因为需要为上层的存在提供一个稳定的基础,Object作为java ...

  4. python 基础篇 09 函数初识

    <<<<<<<<<<<<<<<------------------------------函         ...

  5. Python学习笔记——基础篇【第五周】——算法(4*4的2维数组和冒泡排序)、时间复杂度

    目录 1.算法基础 2.冒泡排序 3.时间复杂度 (1)时间频度 (2)时间复杂度 4.指数时间 5.常数时间 6.对数时间 7.线性时间 1.算法基础  要求:生成一个4*4的2维数组并将其顺时针旋 ...

  6. 简述N种排序算法

    排序算法概述 排序算法是程序员日常很常见的算法,基本上每天都会使用排序,在这里将进行一下总结. 排序算法大致可分为比较类排序和非比较类排序二种,其核心区别可以简单的理解为非比较类排序是对比较类排序之前 ...

  7. Java多线程系列--“基础篇”11之 生产消费者问题

    概要 本章,会对“生产/消费者问题”进行讨论.涉及到的内容包括:1. 生产/消费者模型2. 生产/消费者实现 转载请注明出处:http://www.cnblogs.com/skywang12345/p ...

  8. Java多线程系列--“基础篇”10之 线程优先级和守护线程

    概要 本章,会对守护线程和线程优先级进行介绍.涉及到的内容包括:1. 线程优先级的介绍2. 线程优先级的示例3. 守护线程的示例 转载请注明出处:http://www.cnblogs.com/skyw ...

  9. Python学习笔记基础篇——总览

    Python初识与简介[开篇] Python学习笔记——基础篇[第一周]——变量与赋值.用户交互.条件判断.循环控制.数据类型.文本操作 Python学习笔记——基础篇[第二周]——解释器.字符串.列 ...

随机推荐

  1. 在CMD中操作mysql数据库出现中文乱码解决方案

    百度了一下..有说将cmd字符编码用chcp命令改为65001(utf8字符编码),可这样之后根本无法输入中文,查询出的中问结果依旧乱码 其实,只要保证cmd客户端和MySQL两者编码一致即可. 但现 ...

  2. cs231n spring 2017 lecture7 Training Neural Networks II

    1. 优化: 1.1 随机梯度下降法(Stochasitc Gradient Decent, SGD)的问题: 1)对于condition number(Hessian矩阵最大和最小的奇异值的比值)很 ...

  3. 接口测试时返回的响应报json错误

    问题: 测试接口时,传入错误数据,最开始对于错误数据也返回了json数据的响应:后来传入错误数据,接口突然就没有返回json数据,通过在出错的代码之前进行打印,发现接口报500了 检查错误的方法1:在 ...

  4. OpenCV 霍夫线变换

    #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #i ...

  5. mysql表关联问题(第二卷:外键1对多之2)

    接着上一卷内容我们继续: 上卷我用的查询语句我们可以看到全部数据,很明显这样的方式查找的数据并不详细: SELECT * FROM usr LEFT JOIN fzu ON usr.fzu = fzu ...

  6. 吴裕雄--天生自然python学习笔记:Python3 函数

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创建函数,这 ...

  7. 一次面试留下的实际应用问题。关于HttpModule,IIS集成模式。

    资料来自<IIS7开发与管理完全手册> 周五面试时有点紧张,没能静下心思考,当时隐约想到这个解决方案,但因面试环境和心态确未能明确的表述. 回家的地铁上已经找到解决办法. 要点:1基于IH ...

  8. 两种方法使用js读写cookie实现一个底部广告浮层效果

    下面一个案例实现了js实现一个页面浮层并且使用两种方法使用js读写cookie:来实现用户关闭广告的显示状态: 读者可以将下面代码复制到一个html文件试试效果:html的pre标签未两种js实现的方 ...

  9. 吴裕雄--天生自然 R语言数据分析:火箭发射的地点、日期/时间和结果分析

    dfS = read.csv("F:\\kaggleDataSet\\spacex-missions\\database.csv") library(dplyr) library( ...

  10. mac下配置开发环境

    常用命令 显示隐藏文件 1 defaults write com.apple.finder AppleShowAllFiles -boolean true ; killall Finder 关闭隐藏文 ...