摘要:散列表是一种很有用的数据结构,特别是对于Find操作只需要常数时间.本文的散列表利用空间避免冲突,利用率很高.
(1)散列的基本数据结构,由一个大小变量和一个指针数组(指针指向一个链表)构成.
#define Num 100
#define MinTableSize 5
typedef struct Hashtbl *HashTable;
typedef struct ListNode * List;
struct ListNode
{
int Element;
List Next;
};
struct Hashtbl
{
int TableSize;
List* TheLists;
};
(2)对表的初始化,注意主要结构是指针数组,所有的指针都是野指针,必须给每个指针指定相应的内存空间.
HashTable Initialize(int TableSize)
{
HashTable H ;
if (TableSize < MinTableSize)
{
puts("the tablesize is too small");
return NULL;
}
H = (HashTable)malloc(sizeof(Hashtbl));
H->TableSize = TableSize;
H->TheLists = (List*)malloc(sizeof(List)*TableSize);
for(int i = 0;i<=TableSize-1;i++)
{
H->TheLists[i] = (List)malloc(sizeof(ListNode));
if(H->TheLists[i] == NULL)
{
puts("out of space");
return NULL;
}
else
H->TheLists[i]->Next=NULL;
}
return H;
}
(3)
采用最简单的hash求值函数:取余,然后采用基本的查找方式,当得hash值对应元素不是要找的元素,向前遍历直到找到。
int Hash(int key,int TableSize)
{
return key%TableSize;
}
List Find(int key,HashTable H)
{
List P;
P = H->TheLists[Hash(key,H->TableSize)];
P = P->Next;//有表头
while(P!=NULL&&P->Element!=key)
P = P->Next;
return P;
}
(4)
插入例程:利用Find找到对应的可用的空间.
void Insert(int key,HashTable H)
{
List L, P,NewCell;
P = Find(key,H);
if(P==NULL)
{
NewCell = (List)malloc(sizeof(ListNode));
L = H->TheLists[Hash(key,H->TableSize)];
NewCell->Next = L->Next;
L->Next = NewCell;
NewCell->Element = key;
}
}
(5)删除例程
void Delete(int key,HashTable H)
{
List P,L,temp;
P = Find(key,H);
if(P!=NULL)
{
L = H->TheLists[Hash(key,H->TableSize)];
//获得P的前一个节点temp
temp = L;
while(temp->Next!=P)
temp = temp->Next;
temp->Next = P->Next;
free(P);
}
}
(6)打印整个hash表
void PrintHashTable(HashTable H)
{
List P;
for(int i = 0;i<= H->TableSize-1;i++)
{
P = H->TheLists[i];
P = P->Next;
while(P!=NULL)
{
printf("%d: ",P->Element);
P = P->Next;
}
putchar('\n');
}
}