表查找
解决文本替换问题,采用哈希散列查找方法。
1.先声明一个链表节点
该节点有三个元素,(a)指向下一个节点指针
(b)指向名字的指针(c)指向替换文本的指针
struct nlist
{
struct nlist *next;
char *name;
char *defn;
};
2.定义一个指针数组
数值长度为101,数组元素为指向链表节点的指针,
#define HASHSIZE 101
static struct nlist *hashtab[HASHSIZE];
3.为了将文本散列到哈希表中,通过变换,
经过一个for循环进行计算,每次循环中,将上次的计算结果值通过(hashval=s+31hashval)(可以对比一个计算表示十进制的字符串(sum=n+sum*10),如果乘以31相当于将该数二进制表示向左移动五位,在外减去该数)。返回值为结果数与哈希长度取余,作为指针数组的下标。
unsigned hash(char *s)
{
unsigned hashval;
for(hashval=0;*s!='\0';s++)
{
hashval=*s+31*hashval;
}
return hashval%HASHSIZE;
}
散列过程生成了在数组hashtab中执行查找的起始下标。如果该字符串可以被查找到,则一定位于该起始下标指向的链表某个块中。函数的返回值为指向查找到节点的指针,函数的参数为指针数组以及需要查找的字符串,方法为,先对字符串进行hash变换,以此为指针数组的下标,在该指针指向的链表中查找,因为指针数组声明为静态外部变量,所以函数参数可以不声明该值,具体代码如下:
struct nlist *lookup(char *name)
{
unsigned hashval;
struct nlist *np;
hashval=hash(name);
for(np=hashtab[hashval];np!=NULL;np=np->next)
{
if(strcmp(np->name,name)==0)
{
return np;
}
}
return NULL;
}
下面给出插入函数,插入函数利用loopup函数判定查找的字符串是否在表中。
函数的返回值为指向文本节点的指针,参数为查找的字符串,替换的文本。
struct nlink *install(char *name,char *defn)
{
unsigned hashval;
struct nlist *np;
hashval=hash(name);
if((np=lookup(name))==NULL)
{
np=(struct nlist *)malloc(sizeof(struct nlist));
if(np==NULL||(np->name=strdup(name))==NULL)
{
return NULL;
}
np->next=hashtab[hashval];
hashtab[hashval]=np;
}
else
{
free((void *)np->defn);'
}
if((np->defn=strdup(defn))==NULL)
{
return NULL;
}
return np;
}