使用场景
空间换时间,记录一些数据根据映射结果取
C 实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 链表解决冲突
typedef struct Node {
char *str;
struct Node *next;
} Node;
typedef struct HashTable {
Node **data;
int size;
} HashTable;
// 尾插法
Node *init_node(char *str, Node *head) {
Node *p = (Node *p) malloc(sizeof(Node));
p->str = strdup(str);
p->next = head;
return p;
}
HashTable *init_hashtable(int n) {
HashTable *h = (HashTable *) malloc(sizeof(HashTable));
h->size = n * 2;
h->data = (Node **) malloc(sizeof(Node *));
return h;
}
int BKDRHash(char *str) {
int seed = 31, hash = 0;
for (int i = 0; str[i]; ++i) hash = hash * seed + str[i];
return hash & 0x7fffffff; // 符号位置
}
int insert(HashTable *h, char *str) {
int hash = BKDRHash(str);
int ind = hash % h->size;
h->data[ind] = init_node(str, h->data[ind]);
return 1;
}
int search(HashTable *h, char *str) {
int hash = BKDRHash(str);
int ind = hash % h->size;
Node *p = h->data[ind];
while (p && strcmp(p->str, str)) p = p->next;
return p;
}
void clear_node(Node *node) {
if (node == NULL) return;
Node *p = node, *q;
while (p) {
q = p->next;
free(p->str);
free(p);
p = q;
}
return;
}
void clear_hashtable(HashTable *h) {
if (h == NULL) return;
for (int i = 0; i < h->size; ++i) {
clear_node(h->data[i]);
}
free(h->data);
free(h);
return;
}
int main() {
// 模拟
int op;
#define max_n 100
char str[max_n + 5] = {0};
HashTable *h = init_hashtable(max_n + 5);
while (~scanf("%d%s", &op, str)) {
switch(op) {
case 0:
printf("insert %s to HashTable\n", str);
insert(h, str);
break;
case 1:
printf("search %s from HashTable result = %d\n", str, search(h, str));
break;
}
}
#undef max_n
clear_hashtable(h);
return 0;
}
C++ 实现
#include <bits/stdc++.h>
using namespace std;
class HashTable {
private:
string *elem;
int size;
public:
HashTable() {
size = 2000;
elem = new string[size];
for (int i = 0; i < size; i++) {
elem[i] = "#";
}
}
~HashTable() {
delete[] elem;
}
int hash(string &value) {
int code = 0;
for (size_t i = 0; i < value.length(); i++) {
code = (code * 256 + value[i] + 128) % size;
}
return code;
}
bool search(string &value, int &pos, int ×) {
pos = hash(value);
times = 0;
while (elem[pos] != "#" && elem[pos] != value) {
times++;
if (times < size) {
pos = (pos + 1) % size;
} else {
return false;
}
}
if (elem[pos] == value) {
return true;
} else {
return false;
}
}
int insert(string &value) {
int pos, times;
// 成功找到
if (search(value, pos, times)) {
return 2;
} else if (times < size / 2) { // 冲突,但数据少,开放地址法插入
elem[pos] = value;
return 1;
} else {
// 数据多,聚集可能大,重建
recreate();
insert(value);
return 0;
}
}
void recreate() {
string *temp_elem;
temp_elem = new string[size];
for (int i = 0; i < size; ++i) {
temp_elem[i] = elem[i];
}
int copy_size = size;
size = size * 2;
delete[] elem;
elem = new string[size];
for (int i = 0; i < size; ++i) {
elem[i] ="#";
}
for (int i = 0; i < copy_size; ++i) {
if (temp_elem[i] != "#") {
insert(temp_elem[i]);
}
}
delete[] temp_elem;
}
};