分离链接法部分代码:
#include<stdio.h>
#include<stdlib.h>
#define MINTABLESIZE 5
//结构体定义
struct ListNode //链表的节点定义
{
int element;
struct ListNode* next;
};
struct HashTbl //哈希表定义
{
int tablesize; //哈希表的大小
struct ListNode** thelists; //thelists为指向链表节点ListNode的指针的指针
};
//初始化操作
struct HashTbl* InitializeTable(int tablesize)
{
struct HashTbl* H;
if (tablesize < MINTABLESIZE) //定义的哈希表太小
{
printf("Table size too small!");
return NULL;
}
H = (struct HashTbl*)malloc(sizeof(struct HashTbl)); //为哈希表分配空间
if (H == NULL)
{
printf("Out of space!");
return NULL;
}
H->tablesize = NextPrime(tablesize); //哈希表长度应当选择素数
H->thelists = (struct ListNode**)malloc(sizeof(struct ListNode*) * H->tablesize);
if (H->thelists == NULL)
{
printf("Out of space!");
return NULL;
}
for (int i = 0; i < H->tablesize; i++) //为指向ListNode的指针分配空间
{
H->thelists[i] = (struct ListNode*)malloc(sizeof(struct ListNode)); //每一个指针指向ListNode节点
if (H->thelists[i] == NULL)
{
printf("Out of space!");
return NULL;
}
else
H->thelists[i]->next = NULL;
}
return H;
}
//查找操作
struct ListNode* Find(int key, struct HashTbl* H)
{
struct ListNode* p; //p指向查找的元素所在节点
struct ListNode* loc; //loc指向链表头结点
loc = H->thelists[Hash(key, H->tablesize)];
p = loc->next;
while (p != NULL && p->element != key)
{
p = p->next;
}
return p;
}
//插入操作
void Insert(int key, struct HashTbl* H)
{
struct ListNode* pos;
pos = Find(key, H);
if (pos == NULL) //未找到时插入
{
struct ListNode* newlistnode = (struct ListNode*)malloc(sizeof(struct ListNode)); //要插入的新节点
if (newlistnode == NULL)
{
printf("Out of space!");
}
else
{
struct ListNode* loc = H->thelists[Hash(key, H->tablesize)]; //要插入队列的头结点
newlistnode->element = key;
newlistnode->next = loc->next;
loc->next = newlistnode; //在队头插入
}
}
}
开放定址法完整代码:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAXTABLESIZE 999 //允许开辟的最大散列表长度
typedef enum { Legitimate, Empty, Deleted } EntryType; //合法元素、空单元、有已删除元素
//散列表单元类型
struct HashEntry
{
int Data; //存放元素
EntryType Info; //单元状态
};
//散列表结点定义
struct TblNode
{
int TableSize; //表的最大长度
struct HashEntry* Cells; //存放散列单元数据的数组
};
//哈希函数
int Hash(int key, int TableSize) //除留余数法
{
return key % TableSize;
}
//返回大于N且不超过MAXTABLESIZE的最小素数
int NextPrime(int N)
{
int i, p = (N % 2) ? N + 2 : N + 1; //从大于N的下一个奇数开始
while (p <= MAXTABLESIZE)
{
for (i = (int)sqrt(p); i > 2; i--)
{
if (!(p % i)) //p不是素数
{
break;
}
}
if (i == 2) //for正常结束,说明p是素数
{
break;
}
else //否则试探下一个奇数
{
p += 2;
}
}
return p;
}
//初始化操作
struct TblNode* CreateTable(int TableSize)
{
struct TblNode* H;
int i;
H = (struct TblNode*)malloc(sizeof(struct TblNode));
if (H == NULL)
{
printf("空间溢出!!!\n");
return NULL;
}
H->TableSize = NextPrime(TableSize); //保证散列表最大长度是素数
H->Cells = (struct HashEntry*)malloc(H->TableSize * sizeof(struct HashEntry)); //声明单元数组
if (H->Cells == NULL)
{
printf("空间溢出!!!\n");
return NULL;
}
for (i = 0; i < H->TableSize; i++) //初始化单元状态为“空单元”
H->Cells[i].Info = Empty;
return H;
}
//查找操作
int Find(struct TblNode* H, int Key)
{
int CurrentPos, NewPos;
int CNum = 0; //记录冲突次数
NewPos = CurrentPos = Hash(Key, H->TableSize); //初始散列位置
while (H->Cells[NewPos].Info != Empty && H->Cells[NewPos].Data != Key)//当该位置的单元非空,并且不是要找的元素时,发生冲突
{
if (++CNum % 2) //奇数次冲突
{
NewPos = CurrentPos + (CNum + 1) * (CNum + 1) / 4; //增量为+[(CNum+1)/2]^2
if (NewPos >= H->TableSize)
NewPos = NewPos % H->TableSize; //可能超出表大小,调整为合法地址
}
else //偶数次冲突
{
NewPos = CurrentPos - CNum * CNum / 4; //增量为-(CNum/2)^2
while (NewPos < 0)
NewPos += H->TableSize; //可能超出表大小,调整为合法地址
}
}
return NewPos; //此时NewPos或者是Key的位置,或者是一个空单元的位置(表示找不到)
}
//插入操作
bool Insert(struct TblNode* H, int Key)
{
int Pos = Find(H, Key); //先检查Key是否已经存在
if (H->Cells[Pos].Info != Legitimate) //如果这个单元没有被占,说明Key可以插入在此
{
H->Cells[Pos].Info = Legitimate;
H->Cells[Pos].Data = Key;
return true;
}
else
{
printf("键值已存在\n");
return false;
}
}
//删除操作
bool Delete(struct TblNode* H, int Key)
{
int Pos = Find(H, Key); //先检查Key是否已经存在
if (H->Cells[Pos].Info == Legitimate) //如果这个单元没有被占,说明Key可以插入在此
{
H->Cells[Pos].Info = Deleted;
return true;
}
else
{
printf("键值不存在\n");
return false;
}
}
//打印散列中的元素
void printHash(struct TblNode* H)
{
for (int i = 0; i < H->TableSize; i++)
{
if (H->Cells[i].Info == Legitimate)
{
printf("Cell[%d]:%d\n", i, H->Cells[i].Data);
}
}
}
//主函数
int main()
{
int a[] = { 47, 27, 29, 30, 29, 66 };
int lena = sizeof(a) / sizeof(a[0]); //元素个数
struct TblNode* tab = CreateTable(10);
printf("表的大小:TableSize=%d\n", tab->TableSize);
printf("===================================\n\n");
for (int i = 0; i < lena; i++)
{
Insert(tab, a[i]);
}
printHash(tab);
printf("===================================\n");
Delete(tab, 30);
printHash(tab);
return 0;
}