哈希表

对于C语言而言,实现哈希表加深指针的运用。哈希表是典型空间换时间的算法,解决冲突有多种,以下采用链条式。

以下是本人造的轮子,做一个记录。

hash.c

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 
  5 #define HASHSIZE 101
  6 struct nlist {
  7     struct nlist *next;
  8     char *name;
  9     char *defn;
 10 };
 11 
 12 static struct nlist *hashtab[HASHSIZE];
 13 
 14 unsigned char hash(char *s)
 15 {
 16     unsigned int hashval;
 17     for (hashval = 0; *s != '\0'; s++) {
 18         hashval = hashval * 31 + *s;
 19     }
 20     return hashval % HASHSIZE;
 21 }
 22 
 23 struct nlist *lookup_hash(char *s)
 24 {
 25     struct nlist *np;
 26     for (np = hashtab[hash(s)]; NULL != np; np = np->next) {
 27         if (!strcmp(s, np->name)) {
 28             return np;
 29         }
 30     }
 31     return NULL;
 32 }
 33 
 34 struct nlist *insert_hash(char *name, char *defn)
 35 {
 36     struct nlist *np;
 37     unsigned char  hashval;
 38     if (NULL == (np = lookup_hash(name))) {
 39         np = (struct nlist *)malloc(sizeof(struct nlist));
 40         if (NULL == np || NULL == (np->name = strdup(name))) {
 41             return NULL;
 42         }
 43         hashval = hash(name);
 44         np->next = hashtab[hashval];
 45         hashtab[hashval] = np;
 46     }
 47     if (NULL == (np->defn = strdup(defn))) {
 48         return NULL;
 49     }
 50     return np;
 51 }
 52 int remove_hash(char *name)
 53 {
 54     struct nlist *np, *prev = NULL;
 55     for (np = hashtab[hash(name)]; NULL != np; np = np->next) {
 56         if (!strcmp(name, np->name)) {
 57             break;
 58         }
 59         prev = np;
 60     }
 61     if (NULL == np) {
 62         return -1;
 63     }
 64 
 65     free((void *)np->defn);
 66     free((void *)np->name);
 67     if (NULL == prev) { 
 68         /*删除头链表数据*/
 69         hashtab[hash(name)] = np->next;
 70     }
 71     else {
 72         prev->next = np->next;
 73     }
 74     free((void *)np);
 75     return 0;
 76 }
 77 
 78 void printNode(struct nlist *np)
 79 {
 80     if (NULL != np) {
 81         printf("%s %s\t", np->name, np->defn);
 82         printNode(np->next);
 83     }
 84 }
 85 
 86 void print()
 87 {
 88     unsigned char i;
 89     for (i = 0; i < HASHSIZE; i++) {
 90         printNode(hashtab[i]);
 91         printf("\n");
 92     }
 93 }
 94 
 95 int main(int argc, char const **argv)
 96 {
 97     insert_hash("Kevin_Hwang", "Welcome!");
 98     insert_hash("test1", "This is the test1!");
 99     insert_hash("test2", "This is the test2!");
100     insert_hash("test3", "This is the test3!");
101     insert_hash("test4", "This is the test4!");
102     remove_hash("test1");
103     remove_hash("test4");
104     insert_hash("test2", "The test4 has modified!");
105     print();
106     return 0;
107 }

链条哈希表算法插入一个数据思路是:

1:开辟一个初始数组作为哈希表(如果空间没问题越大越好);

2:根据新插入的数据计算出对应哈希值作为哈希表的索引,若对应索引号的哈希序号没数据则直接插入。若已有数据冲突,则把此哈希序号的值指向

新插入数据(hashtab[hashval] = np),并把新插入数组的下一个链条指针指向旧数据(np->next = hashtab[hashval];)。

删除一个数据时,以上程序只要注意检查要删除的数据是否是链表头数据,中间和末端不用做特别处理。

 

posted @ 2016-06-17 15:42  Kevin_Hwang  阅读(317)  评论(0编辑  收藏  举报