哈希表的实现
来源:互联网 发布:腾讯软件大全 编辑:程序博客网 时间:2024/05/18 18:04
using System;2 public class Hashtable3 {4 private struct bucket5 {6 public Object key; //键7 public Object val; //值8 public int hash_coll; //哈希码9 }10 private bucket[] buckets; //存储哈希表数据的数组(数据桶)11 private int count; //元素个数12 private int loadsize; //当前允许存储的元素个数13 private float loadFactor; //填充因子14 //默认构造方法15 public Hashtable() : this(0, 1.0f) { }16 //指定容量的构造方法17 public Hashtable(int capacity, float loadFactor)18 {19 if (!(loadFactor >= 0.1f && loadFactor <= 1.0f))20 throw new ArgumentOutOfRangeException(21 "填充因子必须在0.1~1之间");22 this.loadFactor = loadFactor > 0.72f ? 0.72f : loadFactor;23 //根据容量计算表长24 double rawsize = capacity / this.loadFactor;25 int hashsize = (rawsize > 11) ? //表长为大于11的素数26 HashHelpers.GetPrime((int)rawsize) : 11;27 buckets = new bucket[hashsize]; //初始化容器28 loadsize = (int)(this.loadFactor * hashsize);29 }30 public virtual void Add(Object key, Object value) //添加31 { 32 Insert(key, value, true);33 }34 //哈希码初始化35 private uint InitHash(Object key,int hashsize,36 out uint seed,out uint incr)37 {38 uint hashcode = (uint)GetHash(key) & 0x7FFFFFFF; //取绝对值39 seed = (uint)hashcode; //h140 incr = (uint)(1 + (((seed >> 5)+1) % ((uint)hashsize-1)));//h241 return hashcode; //返回哈希码42 }43 public virtual Object this[Object key] //索引器44 {45 get46 {47 uint seed; //h148 uint incr; //h249 uint hashcode = InitHash(key, buckets.Length, 50 out seed, out incr);51 int ntry = 0; //用于表示h(key,i)中的i值52 bucket b;53 int bn = (int)(seed % (uint)buckets.Length); //h(key,0)54 do55 {56 b = buckets[bn]; 57 if (b.key == null) //b为无冲突空位时58 { //找不到相应的键,返回空59 return null;60 }61 if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&62 KeyEquals(b.key, key))63 { //查找成功64 return b.val;65 }66 bn = (int)(((long)bn + incr) % 67 (uint)buckets.Length); //h(key+i)68 } while (b.hash_coll < 0 && ++ntry < buckets.Length);69 return null;70 }71 set72 {73 Insert(key, value, false);74 }75 }76 private void expand() //扩容77 { //使新的容量为旧容量的近似两倍78 int rawsize = HashHelpers.GetPrime(buckets.Length * 2); 79 rehash(rawsize);80 }81 private void rehash(int newsize) //按新容量扩容82 {83 bucket[] newBuckets = new bucket[newsize];84 for (int nb = 0; nb < buckets.Length; nb++)85 {86 bucket oldb = buckets[nb];87 if ((oldb.key != null) && (oldb.key != buckets))88 {89 putEntry(newBuckets, oldb.key, oldb.val, 90 oldb.hash_coll & 0x7FFFFFFF);91 }92 }93 buckets = newBuckets;94 loadsize = (int)(loadFactor * newsize);95 return;96 }97 //在新数组内添加旧数组的一个元素98 private void putEntry(bucket[] newBuckets, Object key, 99 Object nvalue, int hashcode)100 {101 uint seed = (uint)hashcode; //h1102 uint incr = (uint)(1 + (((seed >> 5) + 1) % 103 ((uint)newBuckets.Length - 1))); //h2104 int bn = (int)(seed % (uint)newBuckets.Length);//哈希地址105 do106 { //当前位置为有冲突空位或无冲突空位时都可添加新元素107 if ((newBuckets[bn].key == null) || 108 (newBuckets[bn].key == buckets))109 { //赋值110 newBuckets[bn].val = nvalue;111 newBuckets[bn].key = key;112 newBuckets[bn].hash_coll |= hashcode;113 return;114 }115 //当前位置已存在其他元素时116 if (newBuckets[bn].hash_coll >= 0)117 { //置hash_coll的高位为1118 newBuckets[bn].hash_coll |= 119 unchecked((int)0x80000000);120 }121 //二度哈希h1(key)+h2(key)122 bn = (int)(((long)bn + incr) % (uint)newBuckets.Length);123 } while (true);124 }125 protected virtual int GetHash(Object key)126 { //获取哈希码127 return key.GetHashCode();128 }129 protected virtual bool KeyEquals(Object item, Object key)130 { //用于判断两key是否相等131 return item == null ? false : item.Equals(key);132 }133 //当add为true时用作添加元素,当add为false时用作修改元素值134 private void Insert(Object key, Object nvalue, bool add)135 { //如果超过允许存放元素个数的上限则扩容136 if (count >= loadsize)137 { 138 expand();139 }140 uint seed; //h1141 uint incr; //h2142 uint hashcode = InitHash(key, buckets.Length,out seed, out incr);143 int ntry = 0; //用于表示h(key,i)中的i值144 int emptySlotNumber = -1; //用于记录空位145 int bn = (int)(seed % (uint)buckets.Length); //索引号146 do147 { //如果是有冲突空位,需继续向后查找以确定是否存在相同的键148 if (emptySlotNumber == -1 && (buckets[bn].key == buckets) &&149 (buckets[bn].hash_coll < 0))150 {151 emptySlotNumber = bn;152 }153 if (buckets[bn].key == null) //确定没有重复键才添加154 {155 if (emptySlotNumber != -1) //使用之前的空位156 bn = emptySlotNumber;157 buckets[bn].val = nvalue;158 buckets[bn].key = key;159 buckets[bn].hash_coll |= (int)hashcode;160 count++;161 return;162 }163 //找到重复键164 if (((buckets[bn].hash_coll & 0x7FFFFFFF)==hashcode) &&165 KeyEquals(buckets[bn].key, key))166 { //如果处于添加元素状态,则由于出现重复键而报错167 if (add)168 {169 throw new ArgumentException("添加了重复的键值!");170 }171 buckets[bn].val = nvalue; //修改批定键的元素172 return;173 }174 //存在冲突则置hash_coll的最高位为1175 if (emptySlotNumber == -1)176 {177 if (buckets[bn].hash_coll >= 0)178 {179 buckets[bn].hash_coll |= unchecked((int)0x80000000);180 }181 }182 bn = (int)(((long)bn + incr) % (uint)buckets.Length);//二度哈希183 } while (++ntry < buckets.Length);184 throw new InvalidOperationException("添加失败!");185 }186 public virtual void Remove(Object key) //移除一个元素187 {188 uint seed; //h1189 uint incr; //h2190 uint hashcode = InitHash(key, buckets.Length,out seed, out incr);191 int ntry = 0; //h(key,i)中的i192 bucket b;193 int bn = (int)(seed % (uint)buckets.Length); //哈希地址194 do195 {196 b = buckets[bn];197 if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&198 KeyEquals(b.key, key)) //如果找到相应的键值199 { //保留最高位,其余清0200 buckets[bn].hash_coll &= unchecked((int)0x80000000);201 if (buckets[bn].hash_coll != 0) //如果原来存在冲突202 { //使key指向buckets203 buckets[bn].key = buckets;204 }205 else //原来不存在冲突206 { //置key为空207 buckets[bn].key = null;208 }209 buckets[bn].val = null; //释放相应的“值”。210 count--;211 return;212 } //二度哈希213 bn = (int)(((long)bn + incr) % (uint)buckets.Length);214 } while (b.hash_coll < 0 && ++ntry < buckets.Length);215 }216 public override string ToString()217 {218 string s = string.Empty;219 for (int i = 0; i < buckets.Length; i++)220 {221 if (buckets[i].key != null && buckets[i].key != buckets)222 { //不为空位时打印索引、键、值、hash_coll223 s += string.Format("{0,-5}{1,-8}{2,-8}{3,-8}\r\n",224 i.ToString(), buckets[i].key.ToString(),225 buckets[i].val.ToString(), 226 buckets[i].hash_coll.ToString());227 }228 else229 { //是空位时则打印索引和hash_coll230 s += string.Format("{0,-21}{1,-8}\r\n", i.ToString(),231 buckets[i].hash_coll.ToString());232 }233 }234 return s;235 }236 public virtual int Count //属性237 { //获取元素个数238 get { return count; }239 }240 }
- 哈希表的实现
- 哈希表的实现
- 哈希表的C实现
- 一个哈希表的实现
- 哈希表的实现
- 哈希表的C实现
- 哈希表的实现
- VB哈希表的实现
- 哈希表的实现
- c++ 哈希表的实现
- 简单的哈希表实现
- 哈希表的简单实现
- PHP的哈希表实现
- 哈希表的C++实现
- 哈希表的C++实现
- hash哈希表的实现
- 哈希表的实现
- 哈希表的C++实现
- Qt中向导类 QWizard 修改 next finish 按钮事件方法
- S3C2440对Nand Flash操作和电路原理(基于K9F2G08U0A)
- BCLOJ-1334:元素插入
- Android:数据存储方式的比较
- 应该知道的Linux技巧
- 哈希表的实现
- mangos登录服务器-2-main注释
- 一种C#读写二进制文件的通用方法<转>
- 线性同余式
- GLIB 安装手记
- public boolean isAdmin(String adminId,String adminPwd)
- 暗黑破坏神2 换装系统
- NAND FLASH读写原理
- linux 安装chrome