HashTable的实现
来源:互联网 发布:软件配置管理流程 编辑:程序博客网 时间:2024/05/21 10:50
类的简单描述:
MprHashTable是存储和管理Hash内容的类,MprHashEntry是HashTable的一项,有三个派生类MprStringHashEntry、MprStaticHashEntry和MprObjectHashEntry
个各类的详细描述:
MprHashTable类
如下图所示,MprHashTable类使用链表来存储存在冲突的元素集,但是这只是MprHashTable类的简单结构
成员变量
MprList *buckets;
int size;
int count;
正如我在MprList实现那章所描述的一样,类MprList在这里的目的是用于存储MprLink(或其子类但不包括MprList)类型的指针,在这里是MprHashEntry或其子类MprStringHashEntry、MprStaticHashEntry和MprObjectHashEntry
成员函数
插入操作:int MprHashTable::insert(MprHashEntry *value)
实例:MprHashTable hashTable, MprHashEntry* entryPtr1, MprHashEntry* entryPtr2,entryPtr1和entryPtr2指向两个MprHashEntry的实例
1.在执行插入操作之前
2.entryPtr1 = new MprHashEntry(“item1”);
hashTable.insert(entryPtr1);
在这步操作之后,hashTable所做的事情是通过调用lookupInner查看entryPtr1是否在hashTable中,并返回buckets[i]的地址给bp和"item1"在bp指向的链表中的位置给ep,如果ep不等于NUll,则将entryPtr1插入到ep之后,然后删除ep。否则将entryPtr1插入到对应项。假设"item1"对应的hash值为0,即i = 0。
3.entryPtr2 = new MprHashEntry(“item2”);
hashTable.insert(entryPtr2);
3.1如果"item2"的hash值和"item1"的hash值不同,假设这时候的hash值为2,即i = 2
3.2如果"item2"的hash值和"item1"的hash值相同
3.3 再一次执行如下操作
entryPtr3 = new MprHashEntry(“item2”);
hashTable.insert(entryPtr3);
在插入entryPtr3之前,首先通过通过hash函数计算出"Item2"对应的hash值,然后将entryPtr3插入到entryPtr2的后面,最后删除entryPtr2
MprList *bp;
MprHashEntry *ep;
if ((ep = lookupInner(value->key, &bp)) != 0) {
//
// Already exists. Delete the old and insert the new. Insert
// first to make sure we get the right position
//
ep->insertAfter(value);
value->bucket = bp;
bp->remove(ep);
delete ep;
return 0;
}
//
// New entry
//
bp->insert(value);
value->bucket = bp;
count++;
return 0;
删除操作1:int MprHashTable::remove(char *key)
通过lookupInner函数查找key对应的bucket[i]和该链表上的对应item
MprList *bp;
MprHashEntry *ep;
if ((ep = lookupInner(key, &bp)) == 0) {
return MPR_ERR_NOT_FOUND;
}
bp->remove(ep);
count--;
return 0;
删除操作2:int MprHashTable::remove(MprHashEntry *ep)
ep->bucket->remove(ep);
count--;
return 0;
删除hashTable中的所有元素:int MprHashTable::removeAll()
依次遍历所有的bucket[i],删除该队列中所有的元素
查找:MprHashEntry *MprHashTable::lookup(char *key)
MprHashEntry *MprHashTable::lookupInner(char *key, MprList **bucket)
在这里我们只讲第二个函数,该函数的操作过程是:首先通过通过hash函数将key值映射到i上,通过buckets[i]查找到对应的MprList的入口点,再依次查找MprList,将其元素的key值和目标元素的key值进行比较,直到找到对应的item,则返回该item;否则返回NULL。
MprList *bp;
MprHashEntry *ep;
int index, rc;
mprAssert(key);
index = hashIndex(key);
bp = &buckets[index];
ep = (MprHashEntry*) bp->getFirst();
if (bucket) {
*bucket = bp;
}
while (ep) {
rc = strcmp(ep->key, key);
if (rc == 0) {
return ep;
}
ep = (MprHashEntry*) bp->getNext(ep);
}
return 0;
得到第一个元素:MprHashEntry *MprHashTable::getFirst()
从buckets[0]由左向右,由上向下查找,如果找到有一个链表中的元素不为NULL,则返回
得到下一个元素:MprHashEntry *MprHashTable::getNext(MprHashEntry *ep)
从ep开始由左向右,由上向下查找,如果找到有一个链表中的元素不为NULL,则返回
hash映射:
int MprHashTable::hashIndex(char *key)
{
uint sum;
sum = 0;
while (*key) {
sum += (sum * 33) + *key++;
}
return sum % size;
}
这个函数的选取特别重要,因为一个好的hash函数可以减少冲突,使各个bucket内的内容比较均匀。
MprHashEntry、MprStringHashEntry、MprStaticHashEntry和MprObjectHashEntry这四个类都比较简单,这里就不描述了,后两个类是从MprHashEntry继承,他们和MprHashEntry的不同时由于他们除了有key值还有对应的value值。其中MprStringHashEntry和MprStaticHashEntry的区别是MprStringHashEntry中的value是一个可以修改的MprStr类型,而MprStaticHashEntry中的value是char*类型,我们知道该类型指向的指针式不能够被修改的。而MprObjectHashEntry是定义在编译宏PERHAPS下面的,其定义和MprStaticHashEntry是完全一样。
- HashTable的实现
- HASHTABLE的内部实现
- Java的Hashtable实现
- Hashtable 的实现原理
- HashTable的实现测试
- HashTable的C++实现
- hashtable的C++实现
- HashTable 的内部实现
- Hashtable的实现原理
- Hashtable 的实现原理
- Java Hashtable的实现
- javascript的hashtable实现
- Hashtable的实现原理
- hashtable的C++实现
- Hashtable的实现原理
- HashTable的实现原理
- Hashtable的实现原理
- HashTable的实现原理
- VS2005/2008中清除最近打开项目的方法
- windows7下设置IIS
- 自定义MembershipProvider,asp.net2.0 Forms验证-代码及分析
- 双向循环链表的实现
- List【怪异】的初始化方式
- HashTable的实现
- 关于ftp只能自己访问的问题
- Java有用知识
- 导入Custom的Master page(含自定义的CSS) 到Moss 2007
- GCC MakeFile Asrc 的设置-GCC ASM混合编译
- 【顽症】客户端调用DLL类库项目时,config文件中自定义Section的顺序
- PHP PCRE 整理
- 大学毕业前一定要看的9本书
- 【软件】Dreamweaver cs4 破解安装方法