爲了實現高效訪問一個集合中的元素,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是完全一樣。 |