面试准备 - HashTable 的C#实现 开放地址法
Hashtable是很经常在面试中遇到的数据结构,因为他的O(1)操作时间和O(n)空间
之所以自己写一份是因为:
- 加深对于hashtable的理解
- 某些公司面试的时候需要coding.......
开放地址法 Xn=(Xn-1 +b ) % size
理论上b要和size是要精心选择的,不过我这边没有做特别的处理,101的默认size是从c#源代码中抄袭的。。。。
代码尽量简单一点是为了理解方便
hashtable快满的时候扩展一倍空间,数据和标志位还有key 这三个数组都要扩展
删除的时候不能直接删除元素,只能打一个标志(因为用了开放地方方法)
目前只支持string和int类型的key(按位131进制)
非线程安全- 因为这是范例代码
支持泛型
- public class Hashtable<T>
- {
- public Hashtable()
- {
- this.dataArray = new T[this.m];
- this.avaiableCapacity = this.m;
- this.keyArray = new int[this.m];
- for (int i = ; i < this.keyArray.Length; i++)
- {
- this.keyArray[i] = -;
- }
- this.flagArray = new bool[this.m];
- }
- private int m = ;
- private int l = ;
- private int avaiableCapacity;
- private double factor = 0.35;
- private T[] dataArray;
- private int[] keyArray;
- private bool[] flagArray;
- public void Add(string s, T item)
- {
- if (string.IsNullOrEmpty(s))
- {
- throw new ArgumentNullException("s");
- }
- if ((double)this.avaiableCapacity / this.m < this.factor)
- {
- this.ExtendCapacity();
- }
- var code = HashtableHelper.GetStringHash(s);
- this.AddItem(code, item, this.dataArray, code, this.keyArray, this.flagArray);
- }
- public T Get(string s)
- {
- if (string.IsNullOrEmpty(s))
- {
- throw new ArgumentNullException("s");
- }
- var code = HashtableHelper.GetStringHash(s);
- return this.GetItem(code, this.dataArray, code, this.keyArray, this.flagArray);
- }
- private void ExtendCapacity()
- {
- this.m *= ;
- this.avaiableCapacity += this.m;
- T[] newItems = new T[this.m];
- int[] newKeys = new int[this.m];
- bool[] newFlags = new bool[this.m];
- for (int i = ; i < newKeys.Length; i++)
- {
- newKeys[i] = -;
- }
- for (int i = ; i < this.dataArray.Length; i++)
- {
- if (this.keyArray[i] >= && !this.flagArray[i])
- {
- //var code = HashtableHelper.GetStringHash(s);
- this.AddItem(
- this.keyArray[i],
- this.dataArray[i],
- newItems,
- this.keyArray[i],
- newKeys,
- this.flagArray);
- }
- }
- this.dataArray = newItems;
- this.keyArray = newKeys;
- this.flagArray = newFlags;
- // throw new NotImplementedException();
- }
- private int AddItem(int code, T item, T[] data, int hashCode, int[] keys, bool[] flags)
- {
- int address = code % this.m;
- if (keys[address] < )
- {
- data[address] = item;
- keys[address] = hashCode;
- this.avaiableCapacity--;
- return address;
- }
- else if (keys[address] == hashCode)
- {
- if (flags[address])
- {
- flags[address] = false;
- data[address] = item;
- return address;
- }
- throw new ArgumentException("duplicated key");
- }
- else
- {
- int nextAddress = address + this.l; //open addressing Xn=Xn-1 + b
- return this.AddItem(nextAddress, item, data, hashCode, keys, flags);
- }
- }
- private T GetItem(int code, T[] data, int hashCode, int[] keys, bool[] flags)
- {
- int address = code % this.m;
- if (keys[address] < )
- {
- return default(T);
- }
- else if (keys[address] == hashCode)
- {
- if (flags[address])
- {
- return default(T);
- }
- return data[address];
- }
- else
- {
- int nextAddress = address + this.l; //open addressing Xn=Xn-1 + b
- return this.GetItem(nextAddress, data, hashCode, keys, flags);
- }
- }
- public void Delete(string s)
- {
- if (string.IsNullOrEmpty(s))
- {
- throw new ArgumentNullException("s");
- }
- var code = HashtableHelper.GetStringHash(s);
- this.DeleteItem(code, this.dataArray, code, this.keyArray, this.flagArray);
- }
- private void DeleteItem(int code, T[] data, int hashCode, int[] keys, bool[] flags)
- {
- int address = code % this.m;
- if (keys[address] < )
- {
- return;
- //not exist
- }
- else if (keys[address] == hashCode)
- {
- if (!this.flagArray[address])
- {
- flags[address] = true;
- this.avaiableCapacity++;
- }
- }
- else
- {
- int nextAddress = address + this.l; //open addressing Xn=Xn-1 + b
- this.DeleteItem(nextAddress, data, hashCode, keys, flags);
- }
- }
- }
- public class HashtableHelper
- {
- public static int GetStringHash(string s)
- {
- if (string.IsNullOrEmpty(s))
- {
- throw new ArgumentNullException("s");
- }
- var bytes = Encoding.ASCII.GetBytes(s);
- int checksum = GetBytesHash(bytes, , bytes.Length);
- return checksum;
- }
- public static int GetBytesHash(byte[] array, int ibStart, int cbSize)
- {
- if (array == null || array.Length == )
- {
- throw new ArgumentNullException("array");
- }
- int checksum = ;
- for (int i = ibStart; i < (ibStart + cbSize); i++)
- {
- checksum = (checksum * ) + array[i];
- }
- return checksum;
- }
- public static int GetBytesHash(char[] array, int ibStart, int cbSize)
- {
- if (array == null || array.Length == )
- {
- throw new ArgumentNullException("array");
- }
- int checksum = ;
- for (int i = ibStart; i < (ibStart + cbSize); i++)
- {
- checksum = (checksum * ) + array[i];
- }
- return checksum;
- }
- }
面试准备 - HashTable 的C#实现 开放地址法的更多相关文章
- Hash冲突的线性探测开放地址法
在实际应用中,无论如何构造哈希函数,冲突是无法完全避免的. 开放地址法 这个方法的基本思想是:当发生地址冲突时,按照某种方法继续探测哈希表中的其他存储单元,直到找到空位置为止.这个过程可用下式描述: ...
- Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区
最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不 ...
- 开放地址法实现HashTable
前注:本文不是讲解Java类库的Hashtable实现原理,而是根据计算机哈希表原理自己实现的一个Hashtable. HashTable内部是用数组存放一个(Key-Value pair)键值对的引 ...
- 开放地址法散列表ADT
数据结构定义如下: typedef unsigned int Index; typedef Index Position; struct HashTbl; typedef struct HashTbl ...
- 链地址法实现HashMap
前注:本文介绍的HashMap并非Java类库的实现.而是根据哈希表知识的一个实现. 上文介绍了开放地址法实现HashTable,它的缺点是对hashCode映射为地址后如果出现重复地址,则会占用其他 ...
- C# Dictionary源码剖析---哈希处理冲突的方法有:开放定址法、再哈希法、链地址法、建立一个公共溢出区等
C# Dictionary源码剖析 参考:https://blog.csdn.net/exiaojiu/article/details/51252515 http://www.cnblogs.com/ ...
- java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区
java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测).链地址法.再哈希.建立公共溢出区 标签: hashmaphashmap冲突解决冲突的方法冲突 2016-0 ...
- 面试之Hashtable和ConcurrentHashMap
那么要如何保证HashMap的线程安全呢? 方法有很多,比如使用Hashtable或者Collections.synchronizedMap,但是这两位选手都有一个共同的问题:性能.因为不管是读还是写 ...
- java8中哪个类用到了开放地址解决冲突
hreadlocalmap使用开放定址法解决haah冲突,hashmap使用链地址法解决hash冲突
随机推荐
- 20145301&20145321&20145335实验五
20145301&20145321&20145335实验五 这次实验我的组员为:20145301赵嘉鑫.20145321曾子誉.20145335郝昊 实验内容详见:实验五
- Revert R12.1.3 Homepage Layout to Link Style as in R12.1.1 or 11i
https://blogs.oracle.com/ptian/entry/revert_r12_1_3_homepage Oracle EBS 12.1.3主页的展示方式不太习惯,12.1.3为了展示 ...
- 转:python获取linux系统及性能信息
原文:http://amitsaha.github.io/site/notes/articles/python_linux/article.html In this article, we will ...
- Android 高仿微信支付密码输入控件
像微信支付密码控件,在app中是一个多么司空见惯的功能.最近,项目需要这个功能,于是乎就实现这个功能. 老样子,投篮需要找准角度,变成需要理清思路.对于这个"小而美"的控件,我们思 ...
- [Asp.net 开发系列之SignalR篇]专题五:SignalR支持的平台
SignalR支持多种服务器和客户端配置.此外,每种传输方式都有自身的要求限制:如果某种传输方式不被系统支持,SignalR能够优雅地将故障转移到其他类型的传输方式.关于SignalR所支持的传输方式 ...
- 作业三:代码规范、代码复审、PSP
一.代码规范 我认为我们编写的代码都需要进行规范的操作,因为如果为了图省事情或者为了减少时间去完成这个编程.在最后检验的时候就会出现一些警告,导致你这次编程的代码出现问题,当出现问题的时候你在回头去检 ...
- 今天心情好,给各位免费呈上200兆SVN代码服务器一枚,不谢!
开篇先给大家讲个我自己的故事,几个月前在网上接了个小软件开发的私活,平日上班时间也比较忙,就中午一会儿休息时间能抽出来倒腾着去做点.每天下班复制一份到U盘带回去继续摸索,没多久U盘里躺着的文件列表那叫 ...
- js模版引擎handlebars.js实用教程——each-基本循环使用方法
返回目录 <!DOCTYPE html> <html> <head> <META http-equiv=Content-Type content=" ...
- 关于node.js的误会
昨天写了篇博客,介绍了一下我对node.js的第一次亲密接触后的感受,以为node.js很小众,出乎我意料很多人感兴趣,并且对博客中的细节问题做了评论,最多的是围绕node.js的异步与单线程展开的, ...
- React Native01-开始 Windows环境安装配置篇
转载本文章的童鞋请注明原链接. 查阅文档之类的资料,建议到 http://reactnative.cn/ 本人使用环境Win10. 在阅读本文之前,请了解我们安装React Native之前,要安装P ...