通过表查找(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;

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值