当前位置: 首页 > news >正文

微信小程序制作软件下载/宁波seo推广外包公司

微信小程序制作软件下载,宁波seo推广外包公司,外国网站 游戏设定图,ps简单网页设计模板图片引言: 作为资深老鸟,有事没事,出去面试;找准差距、定位价值。 面试必谈哈希, Q1:什么是哈希? Q2:哈希为什么快? Q3:你是怎么理解哈希算法利用空间换取时间的? Q4&#…

 引言:

作为资深老鸟,有事没事,出去面试;找准差距、定位价值。

面试必谈哈希,

Q1:什么是哈希?

Q2:哈希为什么快?

Q3:你是怎么理解哈希算法利用空间换取时间的?

Q4:你是怎么解决哈希冲突的?

Q5:你有实际用写过哈希算法吗?

1. 知识储备

  哈希(也叫散列)是一种查找算法(可用于插入),哈希算法希望能做到不经过任何比较(发生冲突,还是需要少许比较),通过一次存取就能得到查找的数据。

因此哈希的关键在key和数据元素的存储位置之间建立一个确定的对应关系,每个key在哈希表中都有唯一的地址相对应(形成有限、连续的地址空间),查找时根据对应关系经过一步计算得到key在散列表的位置。

在数学上, 原Key叫做原像,由映射函数h(key)映射的存储位置叫做像;在IT领域,以上存储位置叫哈希地址(散列地址),这个映射过程叫做哈希/散列。

故我们可以预见:

  ① 不同的key值,由哈希函数h(x) 作用后可能映射到同一个哈希地址, 这就是哈希冲突,冲突发生的概率取决于 定义的哈希函数

  ② 由哈希表作用后的哈希地址需要空间存储,这一系列连续相邻的地址空间叫哈希表、 散列表。 

  

  处理哈希冲突可分为两大类:

  (1)开散列法发生冲突的元素存储于数组空间之外。可以把“开”字理解为需要另外“开辟”空间存储发生冲突的元素, 又称【链地址法】

  (2)闭散列法发生冲突的元素存储于数组空间之内。可以把“闭”字理解为所有元素,不管是否有冲突,都“关闭”于数组之中,闭散列法又称【开放定址法】,意指数组空间对所有元素,不管是否冲突都是开放的

哈希表是用数组实现的一片连续的地址空间,两种冲突解决方案的区别在于发生冲突的元素是存储在这片数组的空间之外还是空间之内

2. 看图说话

----------------------------以下是开散列法(链地址法)解决冲突的示意图---------------------------

  从图上看实现【哈希】过程分两部分:

① 哈希函数

  收敛函数,不可避免会冲突,需要思考设定一个均衡的哈希函数,使哈希地址尽可能均匀地分布在哈希地址空间

②  构造哈希表 + 冲突链表

  装填因子loadfactor :所谓装填因子是指哈希表中已存入的记录数n与哈希地址空间大小m的比值,即 α=n / m ,α越小,冲突发生的可能性就越小;α越大(最大可取1),冲突发生的可能性就越大。

  另一方面,α越小,存储窨的利用率就越低;反之,存储窨的利用率就越高。为了既兼顾减少冲突的发生,又兼顾提高存储空间的利用率,通常把α控制在0.6~0.9的范围之内

 

哈希在.Net中的应用

  Object基类中有GetHashCode方法,HashCode是一个数字值,用于在【基于哈希特性的集合】中插入和查找某对象;GetHashCode方法为需要快速检查对象相等性的算法提供此哈希代码;

  Do not test for equality of hash codes to determine whether two objects are equal. (Unequal objects can have identical hash codes.) To test for equality, call the ReferenceEquals or Equals method.  (重要的话要读3遍)

  • 值类型hashcode 的默认实现

  • 引用类型hashcode的默认实现

单纯判断【逻辑相等】时,本无所谓重写 GetHashCode方法;但若在基于hash的集合中快速查找/插入某元素,则一定要重写GetHashCode方法。

? 我们看一个实锤:

  统计参加Footabll,Basketball 两个球队的所有成员,自然会想到对 footabllTeam, basketballTeam 成员使用Union方法求并集 (A∪B)

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Http;
using System.Collections.Generic;
using System.Linq;
using System.Collections;namespace Test
{public class Person{public string Name { get; set; }public int Age { get; set; }// 单纯判断逻辑相等,只需重写Equals方法public override bool Equals(object obj){return Name == (obj as Person).Name;}public override int GetHashCode(){return Name.GetHashCode();}}/// <summary>/// 体育小组成员/// </summary>public class TeamMember{public Person Member { get; set; }public string Sport { get; set; } = "footabll";}public class Program{static void Main(){var Beckham = new Person { Name = "Beckham", Age = 21 };var Kobe = new Person { Name = "Kobe", Age = 21 };var footabllTeam = new List<TeamMember>{new TeamMember { Member = new Person { Name = "nash", Age=21 } },new TeamMember { Member = Beckham }};var basketballTeam = new List<TeamMember>{new TeamMember { Member = new Person {  Name = "nash", Age=21 },Sport="basketball" },new TeamMember { Member = Kobe,Sport = "basketball" }};// “==”操作符:判断引用相等Console.WriteLine($"足球队[0]和篮球队[0]是不同引用对象,footabllTeam[0].Member == basketballTeam[0].Member输出:{footabllTeam[0].Member == basketballTeam[0].Member}");// 对两个内存对象,判断逻辑相等Console.WriteLine($"足球队[0]和篮球队[0]逻辑上是一个人,footabllTeam[0].Member.Equals(basketballTeam[0].Member输出:{footabllTeam[0].Member.Equals(basketballTeam[0].Member )}");// 统计两个球队中所有队员, hash-base查找/插入,务必重写GetHashCode方法var members = footabllTeam.Select(x=>x.Member).Union(basketballTeam.Select(x=>x.Member));Console.WriteLine($"总成员人数:{members.Count()} ");Console.Read();}}
}
------------------------output----------------------------------------
 
足球队[0]和篮球队[0]是不同引用对象,footabllTeam[0].Member == basketballTeam[0].Member输出:False
 
足球队[0]和篮球队[0]逻辑上是一个人,footabllTeam[0].Member.Equals(basketballTeam[0].Member输出:True
 
总成员人数:3
 
  观察Union源码计算A,B并集的实现,内部会构造哈希表Set<TElement> 快速查找和插入并集元素,故我们需要给元素编写合适的哈希函数。
public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{if (first == null) throw Error.ArgumentNull("first");if (second == null) throw Error.ArgumentNull("second");return UnionIterator<TSource>(first, second, comparer);
}static IEnumerable<TSource> UnionIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{Set<TSource> set = new Set<TSource>(comparer);foreach (TSource element in first)if (set.Add(element)) yield return element;      //  Set 便是Union方法内部构造的哈希表foreach (TSource element in second)if (set.Add(element)) yield return element;
}
Union方法入口

 

高潮来了,不是总说没处理过哈希冲突吗? 结【知识储备】围观链地址法处理哈希冲突
internal class Set<TElement>{int[] buckets;            //  连续相邻的地址空间,盛放不同冲突链表的容器,俗称哈希桶Slot[] slots;             //  用于解决冲突的链表int count;int freeList;IEqualityComparer<TElement> comparer;public Set() : this(null) { }public Set(IEqualityComparer<TElement> comparer) {if (comparer == null) comparer = EqualityComparer<TElement>.Default;this.comparer = comparer;buckets = new int[7];   // 初始哈希桶和冲突链表长度 都是7slots = new Slot[7];freeList = -1;}// If value is not in set, add it and return true; otherwise return falsepublic bool Add(TElement value) {return !Find(value, true);}// Check whether value is in setpublic bool Contains(TElement value) {return Find(value, false);}// If value is in set, remove it and return true; otherwise return falsepublic bool Remove(TElement value) {int hashCode = InternalGetHashCode(value);int bucket = hashCode % buckets.Length;int last = -1;for (int i = buckets[bucket] - 1; i >= 0; last = i, i = slots[i].next) {if (slots[i].hashCode == hashCode && comparer.Equals(slots[i].value, value)) {if (last < 0) {buckets[bucket] = slots[i].next + 1;}else {slots[last].next = slots[i].next;}slots[i].hashCode = -1;slots[i].value = default(TElement);slots[i].next = freeList;freeList = i;return true;}}return false;}bool Find(TElement value, bool add) {int hashCode = InternalGetHashCode(value);for (int i = buckets[hashCode % buckets.Length] - 1; i >= 0; i = slots[i].next) {if (slots[i].hashCode == hashCode && comparer.Equals(slots[i].value, value)) return true;}if (add) {int index;if (freeList >= 0) {index = freeList;freeList = slots[index].next;}else {if (count == slots.Length) Resize();index = count;count++;}int bucket = hashCode % buckets.Length;slots[index].hashCode = hashCode;slots[index].value = value;slots[index].next = buckets[bucket] - 1;buckets[bucket] = index + 1;}return false;}void Resize() {int newSize = checked(count * 2 + 1);    // 尝试扩容int[] newBuckets = new int[newSize];Slot[] newSlots = new Slot[newSize];Array.Copy(slots, 0, newSlots, 0, count);for (int i = 0; i < count; i++) {int bucket = newSlots[i].hashCode % newSize;newSlots[i].next = newBuckets[bucket] - 1;newBuckets[bucket] = i + 1;}buckets = newBuckets;slots = newSlots;}internal int InternalGetHashCode(TElement value){//Microsoft DevDivBugs 171937. work around comparer implementations that throw when passed nullreturn (value == null) ? 0 : comparer.GetHashCode(value) & 0x7FFFFFFF;}internal struct Slot{internal int hashCode;internal TElement value;internal int next;}}

因此有最佳实践: 当两对象重写Equal方法返回true时, 请务必重写GetHashCode方法为对象返回相同的hashcode。

话虽如此,写一个合适、均衡的哈希函数还是比较考验算法的。

在一般场景中,经验会帮助你编写哈希函数, 比如以上Person类中,字符串类型Name的HashCode总是相等的。

That‘all   看完了通篇文章的同栈猿,应该就可以回答文章引言 5大提问。

作者:JulianHuang
作者:JulianHuang

码甲拙见,如有问题请下方留言大胆斧正;码字+Visio制图,均为原创,看官请不吝好评+关注,  ~。。~

本文欢迎转载,请转载页面明显位置注明原作者及原文链接

转载于:https://www.cnblogs.com/JulianHuang/p/11275611.html

http://www.lbrq.cn/news/1351027.html

相关文章:

  • 网页设计与网站建设试题/培训心得体会范文500字
  • 自己做的网站微信pc端显示乱码/重庆高端网站seo
  • 网站建设怎么弄/网络平台推广方案
  • 自己可以接单做网站吗/企业网络营销策略分析案例
  • 网站建设过程中的通用原则/网站设计是做什么的
  • 起点数据网是谁做的网站/搜索引擎推广的方法有哪些
  • 网站怎么做可以增加点击率/电商推广平台
  • 高埗网站建设/自动推广引流app
  • 网站建设ps模板下载/ios aso优化工具
  • 外贸公司网站建设/公司网络推广
  • 百度云做网站/搜狐三季度营收多少
  • 乐思网站建设/简述网络营销的方法
  • 网站建设完整/美国新冠疫情最新消息
  • 网站开发人员/湘潭网站设计
  • 企业网站发展趋势/网络营销理论包括哪些
  • 企业推广普通话/网站搜索排名优化软件
  • 怎样做付费下载的网站/西安百度推广开户运营
  • 建一个个人网站一年多少钱/泰安优化关键词排名哪家合适
  • 做运营的具体做什么/天津放心站内优化seo
  • seo+网站排名/宁波seo
  • 博客用来做微网站/百度收录提交
  • 东莞市建设网网上办事平台/商丘seo排名
  • 对招聘网站页面设计做建议/百度投诉电话24小时
  • 京东商城网站建设目的/seo快速工具
  • 我想花钱做网站/搜索竞价排名
  • 视频网站策划/网站关键字优化价格
  • 东莞视频网站制作/seo搜索优化工程师招聘
  • 广东网站建设有限公司/网络营销的职能有哪些
  • 广东省白云区属于哪个市/网站推广优化是什么意思
  • 做全国性的app网站推广多少/seo搜索引擎优化实训
  • 初识神经网络01——认识PyTorch
  • 基于Hadoop的股票大数据分析可视化及多模型的股票预测研究与实现
  • 2.4 组件通信
  • 自由学习记录(77)
  • Docker-07.Docker基础-数据卷挂载
  • 福彩双色球第2025089期篮球号码分析