哈希表定义及实现

哈希表也叫散列表,是快速执行查找,删除,插入的技术,不支持元素排序信息。原理是通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。
关键码值到存储位置的映射被称为哈希函数也叫散列函数,当不同关键key被映射到同一value时,称为冲突。
解决冲突主要有:
分离链接法:对Hash表中每个Hash值建立一个冲突表,即将冲突的几个记录以表的形式存储在其中。
开发定址法:根据冲突算法找到空的单元为止(线性探测法,平方探测法...)。

编程实例

算法实现

采用平方探测法的实现放在git@code.aliyun.com:c-program/projecteuler.git上projecteulerccommonstruct目录下elr_hash_int.h elr_hash_int.c两个单元内。

解决问题

https://www.hackerrank.com/ch...
要求用一个map结构存放名字name和电话phone。

定义结构

#define MaxStr 20typedef unsigned long int Index;typedef Index Position;typedef char *KeyType;typedef long int *ValueType;struct HashTbl;typedef struct HashTbl *HashTable;enum KindOfEntry { Legitimate, Empty, Deleted };struct HashEntry {  KeyType Key;  ValueType Value;  enum KindOfEntry Info;};typedef struct HashEntry Cell;struct HashTbl {  long int TableSize;  Cell *TheCells;};

初始化及释放

HashTable InitializeTable(long int TableSize) {  HashTable H;  long int i;  H = malloc(sizeof(struct HashTbl));  if (H == NULL) {    printf("Out of space!\n");  }  H->TableSize = TableSize;  H->TheCells = malloc(sizeof(Cell) * H->TableSize);  if (H->TheCells == NULL) {    printf("Out of space!\n");  }  for (i = 0; i < H->TableSize; i++) {    H->TheCells[i].Info = Empty;    H->TheCells[i].Key = NULL;    H->TheCells[i].Value = 0;  }  return H;}void DestroyTable(HashTable H) {  int i;  if (H == NULL) {    return;  }  for (i = 0; i < H->TableSize; i++) {    H->TheCells[i].Info = Empty;    if (H->TheCells[i].Key != NULL) {      free(H->TheCells[i].Key);    }  }  free(H);}

哈希及冲突插入操作

Position Hash(KeyType Key, long int TableSize) {  long int keyValue = 0;  register unsigned char *p;  for (p = (unsigned char *)Key; *p; p++) {    keyValue = 31 * keyValue + *p;  }  return keyValue % TableSize;}int KeyEqual(KeyType a, KeyType b) {  if ((a == NULL) || (b == NULL)) {    return 1;  }  return strcmp(a, b) == 0 ? 0 : 1;}int Find(KeyType Key, HashTable H, Position *Pos) {  Position CurrentPos;  long int CollisionNum;  int rst = 0;  CollisionNum = 0;  CurrentPos = Hash(Key, H->TableSize);  while (1) {    if (H->TheCells[CurrentPos].Info == Empty)      break;    if (KeyEqual(H->TheCells[CurrentPos].Key, Key) == 0) {      rst = 1;      break;    }    CurrentPos += (++CollisionNum << 1) - 1;    if (CurrentPos >= H->TableSize) {      CurrentPos -= H->TableSize;    }  }  *Pos = CurrentPos;  return rst;}void Insert(KeyType Key, ValueType Value, HashTable H) {  Position Pos;  int exist;  exist = Find(Key, H, &Pos);  H->TheCells[Pos].Info = Legitimate;  if (!exist) {    H->TheCells[Pos].Key = malloc(sizeof(char) * MaxStr);  }  strcpy(H->TheCells[Pos].Key, Key);  H->TheCells[Pos].Value = Value;}

调用解决问题

#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>int main() {  long int n = 0;  scanf("%ld", &n);  HashTable H = InitializeTable(n * 2);  for (int i = 0; i < n; i++) {    char name[20];    long int phone;    scanf("%s %ld", name, &phone);    Insert(name, phone, H);    }    for (int i = 0; i < n; i++) {      char name[20];      Position Pos;      int exist;      scanf("%s", name);      // while (() != '\n');      exist = Find(name, H, &Pos);      if (exist == 1) {          ValueType Value = H->TheCells[Pos].Value;          printf("%s=%ld\n", name, Value);      } else {        printf("Not found\n");      }      if (getchar() == EOF)        break;    }    DestroyTable(H);        return 0;}