哈希表

對於C語言而言,實現哈希表加深指針的運用。哈希表是典型空間換時間的算法,解決衝突有多種,如下采用鏈條式。算法

如下是本人造的輪子,作一個記錄。數組

hash.cspa

  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:開闢一個初始數組做爲哈希表(若是空間沒問題越大越好);code

2:根據新插入的數據計算出對應哈希值做爲哈希表的索引,若對應索引號的哈希序號沒數據則直接插入。若已有數據衝突,則把此哈希序號的值指向blog

新插入數據(hashtab[hashval] = np),並把新插入數組的下一個鏈條指針指向舊數據(np->next = hashtab[hashval];)。索引

刪除一個數據時,以上程序只要注意檢查要刪除的數據是不是鏈表頭數據,中間和末端不用作特別處理。rem

相關文章
相關標籤/搜索