大家可否知道,其实查找中有一种O(1)的查找,即所谓的秒杀。

哈希查找:

对的,他就是哈希查找,说到哈希,大家肯定要提到哈希函数,呵呵,这东西已经在我们脑子里面形成

固有思维了。大家一定要知道“哈希“中的对应关系。

比如说: ”5“是一个要保存的数,然后我丢给哈希函数,哈希函数给我返回一个”2",那么此时的”5“

和“2”就建立一种对应关系,这种关系就是所谓的“哈希关系”,在实际应用中也就形成了”2“是key,”5“是value。

那么有的朋友就会问如何做哈希,首先做哈希必须要遵守两点原则:

①:  key尽可能的分散,也就是我丢一个“6”和“5”给你,你都返回一个“2”,那么这样的哈希函数不尽完美。

②: 哈希函数尽可能的简单,也就是说丢一个“6”给你,你哈希函数要搞1小时才能给我,这样也是不好的。

其实常用的做哈希的手法有“五种”:

第一种:”直接定址法“。

很容易理解,key=Value+C; 这个“C"是常量。Value+C其实就是一个简单的哈希函数。

第二种:“除法取余法”。

很容易理解, key=value%C;解释同上。

第三种:“数字分析法”。

这种蛮有意思,比如有一组value1=112233,value2=112633,value3=119033,

针对这样的数我们分析数中间两个数比较波动,其他数不变。那么我们取key的值就可以是

key1=22,key2=26,key3=90。

第四种:“平方取中法”。此处忽略,见名识意。

第五种:“折叠法”。

这种蛮有意思,比如value=135790,要求key是2位数的散列值。那么我们将value变为13+57+90=160,

然后去掉高位“1”,此时key=60,哈哈,这就是他们的哈希关系,这样做的目的就是key与每一位value都相

关,来做到“散列地址”尽可能分散的目地。

正所谓常在河边走,哪有不湿鞋。哈希也一样,你哈希函数设计的再好,搞不好哪一次就撞楼了,那么抛给我们的问题

就是如果来解决“散列地址“的冲突。

其实解决冲突常用的手法也就2种:

第一种: “开放地址法“。

所谓”开放地址“,其实就是数组中未使用的地址。也就是说,在发生冲突的地方,后到的那个元素(可采用两种方式

:①线性探测,②函数探测)向数组后寻找"开放地址“然后把自己插进入。

第二种:”链接法“。

这个大家暂时不懂也没关系,我就先介绍一下原理,就是在每个元素上放一个”指针域“,在发生冲突的地方,后到的那

个元素将自己的数据域抛给冲突中的元素,此时冲突的地方就形成了一个链表。

上面啰嗦了那么多,也就是想让大家在”设计哈希“和”解决冲突“这两个方面提一点参考和手段。

那么下面就上代码了,

设计函数采用:”除法取余法“。

冲突方面采用:”开放地址线性探测法"。

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5  6 namespace HashSearch 7 { 8     class Program 9     {10         //“除法取余法”11         static int hashLength = 13;12 13         //原数据14         static List<int> list = new List<int>() { 13, 29, 27, 28, 26, 30, 38 };15 16         //哈希表长度17         static int[] hash = new int[hashLength];18 19         static void Main(string[] args)20         {21             //创建hash22             for (int i = 0; i < list.Count; i++)23             {24                 InsertHash(hash, hashLength, list[i]);25             }26 27             Console.WriteLine("Hash数据:" + string.Join(",", hash));28 29             while (true)30             {31                 Console.WriteLine("\n请输入要查找数字:");32                 int result = int.Parse(Console.ReadLine());33                 var index = SearchHash(hash, hashLength, result);34 35                 if (index != -1)36                     Console.WriteLine("数字" + result + "在索引的位置是:" + index);37                 else38                     Console.WriteLine("呜呜," + result + " 在hash中没有找到!");39 40             }41         }42 43         ///<summary>44 /// Hash表检索数据45 ///</summary>46 ///<param name="dic"></param>47 ///<param name="hashLength"></param>48 ///<param name="key"></param>49 ///<returns></returns>50         static int SearchHash(int[] hash, int hashLength, int key)51         {52             //哈希函数53             int hashAddress = key % hashLength;54 55             //指定hashAdrress对应值存在但不是关键值,则用开放寻址法解决56             while (hash[hashAddress] != 0 && hash[hashAddress] != key)57             {58                 hashAddress = (++hashAddress) % hashLength;59             }60 61             //查找到了开放单元,表示查找失败62             if (hash[hashAddress] == 0)63                 return -1;64             return hashAddress;65 66         }67 68         ///<summary>69 ///数据插入Hash表70 ///</summary>71 ///<param name="dic">哈希表</param>72 ///<param name="hashLength"></param>73 ///<param name="data"></param>74         static void InsertHash(int[] hash, int hashLength, int data)75         {76             //哈希函数77             int hashAddress = data % 13;78 79             //如果key存在,则说明已经被别人占用,此时必须解决冲突80             while (hash[hashAddress] != 0)81             {82                 //用开放寻址法找到83                 hashAddress = (++hashAddress) % hashLength;84             }85 86             //将data存入字典中87             hash[hashAddress] = data;88         }89     }90 }

结果:

索引查找:

一提到“索引”,估计大家第一反应就是“数据库索引”,对的,其实主键建立“索引”,就是方便我们在海量数据中查找。

关于“索引”的知识,估计大家都比我清楚,我就简单介绍下。

我们自己写算法来实现索引查找时常使用的三个术语:

第一:主表,      这个很简单,要查找的对象。

第二:索引项,   一般我们会用函数将一个主表划分成几个子表,每个子表建立一个索引,这个索引叫做索引项。

第三:索引表,    索引项的集合也就是索引表。

一般“索引项”包含三种内容:index,start,length

第一: index,也就是索引指向主表的关键字。

第二:start, 也就是index在主表中的位置。

第三:length, 也就是子表的区间长度。

  1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5   6 namespace IndexSearchProgram  7 {  8     class Program  9     { 10         ///<summary> 11 /// 索引项实体 12 ///</summary> 13         class IndexItem 14         { 15             //对应主表的值 16             public int index; 17             //主表记录区间段的开始位置 18             public int start; 19             //主表记录区间段的长度 20             public int length; 21         } 22  23         static void Main(string[] args) 24         { 25             Console.WriteLine("原数据为:" + string.Join(",", students)); 26  27  28             int value = 205; 29  30             Console.WriteLine("\n插入数据" + value); 31  32             //将205插入集合中,过索引 33             var index = insert(value); 34  35             //如果插入成功,获取205元素所在的位置 36             if (index == 1) 37             { 38                 Console.WriteLine("\n插入后数据:" + string.Join(",", students)); 39                 Console.WriteLine("\n数据元素:205在数组中的位置为 " + indexSearch(205) + "位"); 40             } 41  42             Console.ReadLine(); 43         } 44  45         ///<summary> 46 /// 学生主表 47 ///</summary> 48         static int[] students = {  49                                    101,102,103,104,105,0,0,0,0,0, 50                                    201,202,203,204,0,0,0,0,0,0, 51                                    301,302,303,0,0,0,0,0,0,0 52                                 }; 53         ///<summary> 54 ///学生索引表 55 ///</summary> 56         static IndexItem[] indexItem = {  57                                   new IndexItem(){ index=1, start=0, length=5}, 58                                   new IndexItem(){ index=2, start=10, length=4}, 59                                   new IndexItem(){ index=3, start=20, length=3}, 60                                 }; 61  62         ///<summary> 63 /// 查找数据 64 ///</summary> 65 ///<param name="key"></param> 66 ///<returns></returns> 67         public static int indexSearch(int key) 68         { 69             IndexItem item = null; 70  71             // 建立索引规则 72             var index = key / 100; 73  74             //首先去索引找 75             for (int i = 0; i < indexItem.Count(); i++) 76             { 77                 if (indexItem[i].index == index) 78                 { 79                     item = new IndexItem() { start = indexItem[i].start, length = indexItem[i].length }; 80                     break; 81                 } 82             } 83  84             //如果item为null,则说明在索引中查找失败 85             if (item == null) 86                 return -1; 87  88             for (int i = item.start; i < item.start + item.length; i++) 89             { 90                 if (students[i] == key) 91                 { 92                     return i; 93                 } 94             } 95             return -1; 96         } 97  98         ///<summary> 99 /// 插入数据100 ///</summary>101 ///<param name="key"></param>102 ///<returns></returns>103         public static int insert(int key)104         {105             IndexItem item = null;106             //建立索引规则107             var index = key / 100;108             int i = 0;109             for (i = 0; i < indexItem.Count(); i++)110             {111                 //获取到了索引112                 if (indexItem[i].index == index)113                 {114                     item = new IndexItem()115                     {116                         start = indexItem[i].start,117                         length = indexItem[i].length118                     };119                     break;120                 }121             }122             if (item == null)123                 return -1;124             //更新主表125             students[item.start + item.length] = key;126             //更新索引表127             indexItem[i].length++;128             return 1;129         }130     }131 }

结果:

ps: 哈希查找时间复杂度O(1)。

索引查找时间复杂度:就拿上面的Demo来说是等于O(n/3)+O(length)

转载于:https://www.cnblogs.com/huangxincheng/archive/2011/11/24/2261074.html

算法系列15天速成——第五天 五大经典查找【中】相关推荐

  1. 算法系列15天速成——第四天 五大经典查找【上】

    在我们的生活中,无处不存在着查找,比如找一下班里哪个mm最pl,猜一猜mm的芳龄....... 对的这些都是查找. 在我们的算法中,有一种叫做线性查找. 分为:顺序查找. 折半查找. 查找有两种形态: ...

  2. 算法系列15天速成——第三天 七大经典排序【下】

    今天跟大家聊聊最后三种排序: 直接插入排序,希尔排序和归并排序. 直接插入排序: 这种排序其实蛮好理解的,很现实的例子就是俺们斗地主,当我们抓到一手乱牌时,我们就要按照大小梳理扑克,30秒后, 扑克梳 ...

  3. 基本算法系列15天速成

    算法系列15天速成--第一天 七大经典排序[上] 算法系列15天速成--第二天 七大经典排序[中] 算法系列15天速成--第三天 七大经典排序[下] 算法系列15天速成--第四天 五大经典查找[上] ...

  4. 算法系列15天速成——第十天 栈

    原文:算法系列15天速成--第十天 栈 今天跟大家聊聊栈,在程序设计中,栈的使用还是非常广泛的,比如有"括号匹配问题","html结构匹配问题". 所以说掌握了 ...

  5. 算法系列15天速成——第二天 七大经典排序【中】

    首先感谢朋友们对第一篇文章的鼎力支持,感动中.......  今天说的是选择排序,包括"直接选择排序"和"堆排序". 话说上次"冒泡排序"被 ...

  6. 算法系列15天速成——第十三天 树操作【下】

    今天说下最后一种树,大家可否知道,文件压缩程序里面的核心结构,核心算法是什么?或许你知道,他就运用了赫夫曼树. 听说赫夫曼胜过了他的导师,被认为"青出于蓝而胜于蓝",这句话也是我比 ...

  7. 【❤️算法系列之顺序二叉树的实现(前序遍历、中序遍历、后序遍历)❤️】

    1.何为顺序二叉树 2.顺序二叉树的特点 3.顺序二叉树的遍历 3.1.前序遍历 3.2.中序遍历 3.3.后序遍历 4.顺序二叉树的注意点 [❤️算法系列之二叉树的实现(包含前序.中序.后序遍历以及 ...

  8. 【算法系列之线索化二叉树,前序线索化、中序线索化、后序线索化以及遍历~】

    1.何谓线索化二叉树 2.线索化二叉树的本质 3.线索化二叉树的存储结构 4.构建线索化二叉树 4.1.先序线索化 4.2.中序线索化 4.3.后序线索化 5.遍历线索化二叉树 5.1.先序遍历 先序 ...

  9. 八十五、Python | Leetcode数据结构之图和动态规划算法系列

    @Author:Runsen @Date:2020/7/7 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...

  10. python算法系列资料集(一)-2022.03.15

    小学生学python(一) 小学生学python(一) - 超龄码农 - 博客园 小学生学python(二) 小学生学python(二) - 超龄码农 - 博客园 小学生学python(三) 小学生学 ...

最新文章

  1. 解决 echarts柱状图x轴数据隔一个显示
  2. 线程同步机制:互斥量、信号量、读写锁、条件变量
  3. Linux系统编程20:基础IO之从内核代码深刻理解Linux是如何管理文件及文件描述符的本质是什么
  4. 错误记录(12):No 'Access-Control-Allow-Origin' header is present on the requested resource.
  5. 站长seo经过的阶段
  6. CTO下午茶:张弛有度,动静自如
  7. opencv:VS无法导入源文件(环境配置不全解决100%有效)
  8. 信号与线性系统分析(吴大正,郭宝龙)(2-冲激函数)
  9. 大样本OLS模型假设及R实现
  10. 过采样 Oversampling
  11. 第一周:半导体器件基础(一)
  12. Spring Boot整合mybatis报错Invalid bound statement (not found)
  13. linux发行版_看一看2020年最漂亮的Linux发行版
  14. vue2.x使用Relation Graph 人物关系图谱
  15. 入职两个月的一些感受
  16. 统一社会信用代码正则表达式
  17. Python 爬虫 m3u8的下载及AES解密
  18. Java中Math函数的使用
  19. linux之shell语言
  20. 运行VUE项目时,出现npm ERR! A complete log of this run can be found in:...报错

热门文章

  1. python matplotlib 绘图操作
  2. 物体检测中常用的几个概念迁移学习、IOU、NMS理解
  3. CTF入门指南(Capture the flag)
  4. Caffe学习:pycaffe接口配置
  5. 如何使用XGBoost开发随机森林集成
  6. Python实现四种方法求解计算阶乘和(1!+2!+3!+...+n!)
  7. 机器学习之特征选择 (feature_selection)
  8. oracle里的or 短路么,Oracle CASE短路不能分组工作
  9. mac remix导入本地项目
  10. 软件工程 结对编程 设计结对 单元测试结对 评审结对 是什么