10. 分离链接散列表
fatal.h
#include <stdio.h>
#include <stdlib.h>
#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1)
hashsep.h
/* Interface for separate chaining hash table */
typedef int ElementType;
typedef unsigned int Index;
#ifndef _HashSep_H
#define _HashSep_H
struct ListNode;
typedef struct ListNode *Position;
struct HashTbl;
typedef struct HashTbl *HashTable;
HashTable InitializeTable(int TableSize);
void DestroyTable(HashTable H);
Position Find(ElementType Key, HashTable H);
void Insert(ElementType Key, HashTable H);
ElementType Retrieve(Position P);
void PrintTable(HashTable H);
/* Routines such as Delete are MakeEmpty are omitted */
#endif /* _HashSep_H */
hashsep.c
#include "fatal.h"
#include "hashsep.h"
#include <stdlib.h>
#define MinTableSize (10)
struct ListNode
{
ElementType Element;
Position Next;
};
typedef Position List;
/* List *TheList will be an array of lists, allocated later */
/* The lists use headers (for simplicity), */
/* though this wastes space */
struct HashTbl
{
int TableSize;
List *TheLists;
};
/* Return next prime; assume N >= 10 */
static int NextPrime(int N)
{
int i;
if(N % 2 == 0)
N++;
for( ; ; N += 2)
{
for(i = 3; i * i <= N; i += 2)
if (N % i == 0)
break;
if (i*i > N)
return N;
}
}
/* Hash function for ints */
Index Hash(ElementType Key, int TableSize)
{
return Key % TableSize;
}
HashTable InitializeTable(int TableSize)
{
HashTable H;
int i;
if (TableSize < MinTableSize)
{
Error("Table size too small");
return NULL;
}
/* Allocate table */
H = malloc(sizeof(struct HashTbl));
if (H == NULL)
FatalError("Out of space!!!");
H->TableSize = NextPrime(TableSize);
/* Allocate array of lists */
H->TheLists = malloc(sizeof(List) * H->TableSize);
if (H->TheLists == NULL)
FatalError("Out of space!!!");
/* Allocate list headers */
for (i = 0; i < H->TableSize; i++)
{
H->TheLists[i] = malloc(sizeof(struct ListNode));
if (H->TheLists[i] == NULL)
FatalError("Out of space!!!");
else
H->TheLists[i]->Next = NULL;
}
return H;
}
Position Find(ElementType Key, HashTable H)
{
Position P;
List L;
L = H->TheLists[Hash(Key, H->TableSize)];
P = L->Next;
while (P != NULL && P->Element != Key)
/* Probably need strcmp!! */
P = P->Next;
return P;
}
void Insert(ElementType Key, HashTable H)
{
Position Pos, NewCell;
List L;
Pos = Find(Key, H);
if (Pos == NULL) /* Key is not found */
{
NewCell = malloc(sizeof(struct ListNode));
if (NewCell == NULL)
FatalError("Out of space!!!");
else
{
L = H->TheLists[Hash(Key, H->TableSize)];
NewCell->Next = L->Next;
NewCell->Element = Key; /* Probably need strcpy! */
L->Next = NewCell;
}
}
}
ElementType Retrieve(Position P)
{
return P->Element;
}
void DestroyTable(HashTable H)
{
int i;
for(i = 0; i < H->TableSize; i++)
{
Position P = H->TheLists[i];
Position Tmp;
while(P != NULL)
{
Tmp = P->Next;
free(P);
P = Tmp;
}
}
free(H->TheLists);
free(H);
}
void PrintTable(HashTable H)
{
Position P;
List L;
int i;
for (i = 0; i < H->TableSize; i++)
{
L = H->TheLists[i];
P = L->Next;
while (P != NULL)
{
printf("%d\t", Retrieve(P));
P = P->Next;
}
printf("\n\n");
}
}
testhash.c
#include "hashsep.h"
#include <stdio.h>
#define NumItems 400
int main()
{
HashTable H;
Position P;
int i;
int j = 0;
int CurrentSize;
H = InitializeTable(CurrentSize = 29);
for (i = 0; i < NumItems; i++, j += 71)
Insert(j, H);
PrintTable(H);
for (i = 0, j = 0; i < NumItems; i++, j += 71)
if ((P = Find(j, H)) == NULL || Retrieve(P) != j)
printf("Error at %d\n", j);
printf("End of program.\n");
return 0;
}