为了实现高效访问一个集合中的元素,Mpr中实现了Hash Table,其结构如下图所示
类的简单描述: MprHashTable是存储和管理Hash内容的类,MprHashEntry是HashTable的一项,有三个派生类MprStringHashEntry、MprStaticHashEntry和MprObjectHashEntry
个各类的详细描述: MprHashTable类 如下图所示,MprHashTable类使用链表来存储存在冲突的元素集,但是这只是MprHashTable类的简单结构 成员变量 MprList *buckets; 正如我在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; if ((ep = lookupInner(value->key, &bp)) != 0) {
删除操作1:int MprHashTable::remove(char *key) MprList *bp; if ((ep = lookupInner(key, &bp)) == 0) {
删除操作2:int MprHashTable::remove(MprHashEntry *ep) ep->bucket->remove(ep);
删除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; mprAssert(key); index = hashIndex(key); while (ep) { 得到第一个元素:MprHashEntry *MprHashTable::getFirst() 从buckets[0]由左向右,由上向下查找,如果找到有一个链表中的元素不为NULL,则返回
hash映射: int MprHashTable::hashIndex(char *key) sum = 0; return sum % size; 这个函数的选取特别重要,因为一个好的hash函数可以减少冲突,使各个bucket内的内容比较均匀。
MprHashEntry、MprStringHashEntry、MprStaticHashEntry和MprObjectHashEntry这四个类都比较简单,这里就不描述了,后两个类是从MprHashEntry继承,他们和MprHashEntry的不同时由于他们除了有key值还有对应的value值。其中MprStringHashEntry和MprStaticHashEntry的区别是MprStringHashEntry中的value是一个可以修改的MprStr类型,而MprStaticHashEntry中的value是char*类型,我们知道该类型指向的指针式不能够被修改的。而MprObjectHashEntry是定义在编译宏PERHAPS下面的,其定义和MprStaticHashEntry是完全一样。 |