散列表是一种支持在O(1)时间内实现字典操作,即Insert, Find,Delete操作的数据结构,
常用在编译器中实现符号表,或在程序中实现拼写检查。
下面给出散列表的分离链表法的实现:
// Hash: 分离链表法实现
struct ListNode;
typedef struct ListNode *Position;
struct HashTbl;
typedef Position List;
typedef struct HashTbl *HashTable;
HashTable InitializeTable( int TableSize );
void DestoryTable( HashTable H );
Position Find( ElementType X, HashTable H );
void Insert( ElementType X, HashTable H );
ElementType Retrieve( Position P );
struct ListNode
{
ElementType Element;
Position Next;
};
struct HashTbl
{
int TableSize;
List *TheLists; // 指向指向ListNode结构指针的指针
};
HashTable InitializeTable( int TableSize )
{
int i;
HashTable H;
if ( TableSize < MinTableSize )
{
printf( "Table size too small" );
return NULL;
}
/* Allocate table */
H = (HashTable)malloc( sizeof(struct HashTbl) );
if ( H == NULL )
{
printf( "Out of space" );
return NULL;
}
H->TableSize = NextPrime( TableSize );
/* Allocate array of lists */
H->TheLists = (List *)malloc( sizeof( List ) * H->TableSize );
if ( H->TheLists == NULL )
{
printf( "Out of space" );
return NULL;
}
/* Allocate list headers */
for ( i = 0; i < H->TableSize; ++i )
{
H->TheLists[i] = (Position)malloc( sizeof(struct Node) );
if ( H->TheLists[i] == NULL )
{
printf( "Out of space" );
return NULL;
}
else
H->TheLists[i]->Next = NULL;
}
return H;
}
/*
* 查找的一般的思路:
* 1.寻找到Key的被Hash函数分配的链表
* 2.用链表的基本操作进行查找,未找到返回NULL
*/
Positon Find( ElementType Key, HashTable H )
{
Positon P;
List L;
if ( H == NULL )
{
printf( "Empty HashTable" );
return NULL;
}
L = H->TheLists[ Hash( Key, H->TableSize ) ];
P = L->Next;
while ( P != NULL && P->Element != Key )
P = P->Next;
return P;
}
/*
* 插入的基本思路:
* 1.寻找表中是否有相同关键字,若无,将该关键字放入表中
*/
void Insert( Element Key, HashTable H )
{
Positon Pos, NewCell;
List L;
Pos = Find( Key, H );
if ( Pos == NULL ) /* Key is not found */
{
NewCell = (Positon)malloc( sizeof(struct ListNode) );
if ( NewCell == NULL )
{
printf( "Out of space" );
return;
}
else
{
L = H->TheLists[ Hash( Key, H->TableSize ) ];
NewCell->Next = L->Next;
NewCell->Element = Key;
L->Next = MewCell;
}
}
}