#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct Node {
char *str;
struct Node *next;
} Node;
typedef struct HashTable {
Node **data;
int size;
} HashTable;
Node *initNode(char *str) {
Node *n = (Node *)malloc(sizeof(Node));
//n->str = (char *)malloc(strlen(str) + 1); strcpy(n->str, str);//还要多存结束标志'\0'
n->str = strdup(str); //此行语句和上一行等价 需包含string.h
n->next = NULL;
return n;
}
void freeNode(Node *p) {
if (!p) return ;
free(p->str);
free(p);
return ;
}
void freeList(Node *head) {
if (!head) return ;
Node *k;
while (head) {
k = head;
head = head->next;
freeNode(k);
}
return ;
}
HashTable *initHashTable(int n) {
HashTable *h = (HashTable *)malloc(sizeof(HashTable));
h->size = n + n; //哈希表的空间一般都会比存值大数量大 减少哈希碰撞
h->data = (Node **)calloc(h->size, sizeof(Node *)); //比malloc多了一个赋初始值0
return h;
}
void freeHashTable(HashTable *h) {
for (int i = 0; i < h->size; ++i)
freeList(h->data[i]);
free(h->data);
free(h);
return ;
}
Node *insertNode(Node *head, Node *p) {
p->next = head;
return p;
}
int BKDHash(char *str) {//哈希算法
int hash = 0, seed = 31; //seed任意取一个质数
while (*str) {
hash = hash * seed + str[0]; //哈希公式
++str;
}
return hash & 0x7fffffff; //32位整型的最高位置为0
}
int insertHash(HashTable *h, char *str) { //插入哈希表
if (!h) return 0;
int hash = BKDHash(str), ind = hash % h->size;
h->data[ind] = insertNode(h->data[ind], initNode(str));
return 1;
}
Node *searchList(Node *p, char *str) {
while (p && strcmp(p->str, str))
p = p->next;
return p;
}
Node *searchHash(HashTable *h, char *str) { //查找哈希表
if (!h) return NULL;
int hash = BKDHash(str), ind = hash %h->size;
return searchList(h->data[ind], str);
}
//生成随机长度字符串
char *makeStr(char *str, int n) {
int len = rand() % (n - 1) + 1; //n-1:保留最后一位存\0, +1:不能让字符串有len=0的空字符串
char c;
for (int i = 0; i < len; ++i) {
switch (rand() % 3) {
case 0:
c = 'A' + rand() % 26;
break;
case 1:
c = 'a' + rand() % 26;
break;
case 2:
c = '0' + rand() % 10;
break;
default:
c = '1';
break;
}
str[i] = c;
}
str[len] = 0; // \0的ASCII值为0
return str;
}
int main() {
srand(time(0)); //设定随机数种子
char str[8];
int cnt = 10;
HashTable *h = initHashTable(10);
while (cnt--) {
makeStr(str, 8);
insertHash(h, str);
printf("%s ", str);
}
putchar(10); //换行符\n的ASCII码的值为10
while (~scanf("%s", str)) {
if (!strcmp(str, "q")) break; //退出循环的字符串
Node *n = searchHash(h, str);
if (n) printf("hash=%d addr=%p, str=%s", BKDHash(str), n, n->str);
else printf("%s is not found! ", str);
}
freeHashTable(h);
return 0;
}
C语言 实现hash哈希表构造 插入 查找
于 2021-08-06 22:13:13 首次发布