通過表查找(HASH表)分析結構

通過一個表查找的程序,深入討論結構。

當遇到如宏定義 #define IN   1時,宏處理器和編譯器如何處理呢。需要把名字IN和替換文本1存入某個表中,當出現IN時如“statet = IN;

就必須用1來替換IN。

1處理名字 需要將名字和替換文本存入表中.用函數install(s,t)來實現。遇到之後就用lookup(s)函數在表中查找,若找到,返回指向該處到指針;若沒找到,返回NULL。

算法:採用散列查找方法(將輸入的名字轉換爲一個小的非負整數,該整數隨後作爲一個指針數組的下標。每個數組每個元素指向某個鏈表的表頭,鏈表中的各個塊用於描述具有

該散列值的名字。如果沒有名字散列到該值,則數組元素的值爲NULL。

鏈表中每個塊都是一個結構,包含一個指向名字的指針,一個指向替換文本的指針,還要有指向鏈表後繼塊的指針,如果後繼塊爲空,即鏈表到頭結束。

塊結構如下

struct nlist{                           /* table entry: */

                struct  nlist *next;   /*next entry in chain */

                char *name;       /*defined name */

               char *defn;            /* replacement text */

};

指針數組定義如下:

#define HASHSIZE 101

static struct nlist  *hashtab[HASHSIZE];    /*pointer table*/

lookup和Install函數都使用hash,通過一個for循環進行計算,每次循環,將上一次循環計算得到到結果經過變換(乘以31)後得到新的值同字符串當前字符的值相加(*s  + 31 *

hashval),然後將該結果值同數組長度執行去模操作(即取餘),其結果是該函數的返回值。這種散列函數不是最優,但簡短有效。

/*hash: from hash value for string s* /

unsigned hash(char *s)

{

    unsigned hashval;

    for(hashval = 0;  *s != '\0'; s++)

           hashval = *s  + 31 *  hashval;

    return hashval % HASHSIZE;

}

散列過程生產了在數組hastab中執行查找的起始下標.如果字符串可以被找到,就一定位於該起始下標指向的鏈表的某個塊.查找過程由lookup函數實現,如果找到

返回該表項的指針,否則返回空NULL.

/*lookup:look for s in hashtab*/

struct nlist *lookup(char *s)

{

struct  nlist *np;

        for (np = hashtab[hash(s)]; np != NULL;  np  =  np->next)

if (strcmp(s, np->name) == 0)

return np;   /*找到*/

return NULL;    /*沒找到*/

}

for( ptr = head;ptr != NULL; ptr = ptr -> next)是遍歷一個鏈表的標準方法.

install函數借助lookup函數判斷待加入的名字是否存在,同上,存在就用新的的定義替換,沒有就創建一個新的表項,如果空間不足,返回NULL.

struct nlist  *lookup(char *);

char *strdup(char *);

/*install :put(name, defn) in hashtab *.

struct nlist *install(char *name,char *defn)

{

struct nlist *np;

unsigned hashval;

if ((np =lookup(name)) == NULL){  /*沒有找到*/

np = (struct nlist *) malloc( size(* np));

if (np == NULL || (np->name = strdup(name)) == NULL)

return NULL;

hashval = hash(name);

np->next = hashtab[hashval];

hashtab[hashval] = np;

} else

free((void *) np->defn); 

if((np->defn = strdup(defn)) == NULL;

return NULL;

return np;

}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章