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#实现 开放地址法的更多相关文章

  1. Hash冲突的线性探测开放地址法

    在实际应用中,无论如何构造哈希函数,冲突是无法完全避免的. 开放地址法 这个方法的基本思想是:当发生地址冲突时,按照某种方法继续探测哈希表中的其他存储单元,直到找到空位置为止.这个过程可用下式描述:  ...

  2. Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

    最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不 ...

  3. 开放地址法实现HashTable

    前注:本文不是讲解Java类库的Hashtable实现原理,而是根据计算机哈希表原理自己实现的一个Hashtable. HashTable内部是用数组存放一个(Key-Value pair)键值对的引 ...

  4. 开放地址法散列表ADT

    数据结构定义如下: typedef unsigned int Index; typedef Index Position; struct HashTbl; typedef struct HashTbl ...

  5. 链地址法实现HashMap

    前注:本文介绍的HashMap并非Java类库的实现.而是根据哈希表知识的一个实现. 上文介绍了开放地址法实现HashTable,它的缺点是对hashCode映射为地址后如果出现重复地址,则会占用其他 ...

  6. C# Dictionary源码剖析---哈希处理冲突的方法有:开放定址法、再哈希法、链地址法、建立一个公共溢出区等

    C# Dictionary源码剖析 参考:https://blog.csdn.net/exiaojiu/article/details/51252515 http://www.cnblogs.com/ ...

  7. java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

    java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测).链地址法.再哈希.建立公共溢出区 标签: hashmaphashmap冲突解决冲突的方法冲突 2016-0 ...

  8. 面试之Hashtable和ConcurrentHashMap

    那么要如何保证HashMap的线程安全呢? 方法有很多,比如使用Hashtable或者Collections.synchronizedMap,但是这两位选手都有一个共同的问题:性能.因为不管是读还是写 ...

  9. java8中哪个类用到了开放地址解决冲突

    hreadlocalmap使用开放定址法解决haah冲突,hashmap使用链地址法解决hash冲突

随机推荐

  1. solr&lucene3.6.0源码解析(三)

    solr索引操作(包括新增 更新 删除 提交 合并等)相关UML图如下 从上面的类图我们可以发现,其中体现了工厂方法模式及责任链模式的运用 UpdateRequestProcessor相当于责任链模式 ...

  2. day10---multiprocess 多进程

    multiprocess Queue  \ Pipe 只是实现进程间数据的传递 Manager 实现了进程间数据的共享,即多个进程可以修改同一份数据   进程模块 multiprocessing #! ...

  3. android 连接蓝牙扫码枪,程序崩溃之onConfigurationChanged

    当android手机通过蓝牙连接扫码枪时,程序崩溃的原因之一是:键盘弹出或隐藏,触发程序走了onDestory->onCreate的生命周期,从而可能使得页面的某些初始化数据被清除了. 解决方法 ...

  4. C++ 非阻塞套接字的使用 (1)

    在维护代码的过程中,发现软件运行的CPU占用率居高不下,在4核的电脑上占用了25%的CPU.查阅资料的得知,这是可能是由于软件中出现了死循环. 经过对软件的一些测试,最终确定了死循环出现的位置——通讯 ...

  5. I/O优化篇

    转载:http://blog.csdn.net/gzh0222/article/details/9227393 很不错 1.系统学习 IO性能对于一个系统的影响是至关重要的.一个系统经过多项优化以后, ...

  6. 如何在Hdevelop加入自己的算子

    halcon中允许用户编写自定义函数,同时也可以将此函数保存在其他工程中调用.   以halcon12讲解   创建自定义函数     本地程序函数:创建后仅能在当前工程使用 hdevelop函数文件 ...

  7. DataTable汇总

    一.排序 1 获取DataTable的默认视图 2 对视图设置排序表达式 3 用排序后的视图导出的新DataTable替换就DataTable (Asc升序可省略,多列排序用"," ...

  8. 【Win10 UWP】微信SDK基本使用方法和基本原理

    上回讲到,作为一个长期散播温暖,散播希望的小清新无公害WP开发者,继QQ SDK之后,又把UWP微信SDK这茬了结了,仅供学习交流. 1.安装微信SDK for UWP 微信官方此前明确说明短时间内暂 ...

  9. Kali Linux渗透测试实战 1.2 环境安装及初始化

    1.2 环境安装及初始化 目录(?)[-] 环境安装及初始化 下载映像 安装虚拟机 安装Kali Linux 安装中文输入法 安装VirtualBox增强工具 配置共享目录和剪贴板 运行 Metasp ...

  10. VS2012编译的Windows服务启动后立即停止的解决方案

    ATL中的BUG,在没有COM的服务中,使用_ATL_NO_COM_SUPPORT. 并在服务中添加下面的代码 #if defined(_ATL_NO_COM_SUPPORT) HRESULT Pre ...