散列 - 开放定址散列
开放定址散列法是另一种不用链表解决冲突的方法
不过, 在开放定址散列标准的删除方法不能使用
而大致的算法思路跟其散列-分离链表法类似
//enum 中 L, M, Delede代表链表的三种状态
struct ListNode;
struct HashTbl;
typedef struct ListNode *Position;
typedef struct HashTbl *HashTabl;
const int N = 10;
enum Kind { L, M, Deleted };
struct ListNode
{
char *ch;
enum Kind Enum;
};
struct HashTbl
{
int The_SIZE;
Position *The_ListNode;
};
其他的插入都是一样的思路, 这里讲解的是, 两个初始化
程序开始时的基本初始化
//初始化
HashTabl Creat(int SIZE)
{
HashTabl H;
H = (HashTabl)malloc(sizeof(struct HashTbl));
if (H == NULL)
exit(0);
H->The_SIZE = SIZE;
H->The_ListNode = (Position *)malloc(sizeof(Position));
if (H->The_ListNode == NULL)
exit(0);
//状态 M = 1 ,表示初始化化过
for (int i = 0; i < SIZE; i++)
H->The_ListNode[i]->Enum = M;
return H;
}
以及扩大数组的后续初始化
//当初始化的数组被占据很多的时候,
//我们需要重新开辟一个更大的数组范围, 并将之前保存的数据拷贝过来
void ReHash(HashTabl &H)
{
int ReSIZE;
Position *P;
ReSIZE = H->The_SIZE;
P = H->The_ListNode;
H = Creat(2 * ReSIZE);
for (int i = 0; i < ReSIZE; i++)
if (P[i]->Enum == L)
Inset(H, P[i]->ch);
}
源代码
#include <stdio.h>
#include <stdlib.h>
struct ListNode;
struct HashTbl;
typedef struct ListNode *Position;
typedef struct HashTbl *HashTabl;
const int N = 10;
//enum 中 L, M, Delede代表链表的三种状态
enum Kind { L, M, Deleted };
struct ListNode
{
char *ch;
enum Kind Enum;
};
struct HashTbl
{
int The_SIZE;
Position *The_ListNode;
};
//字符串转换数字
unsigned int Hash(char *key, int SIZE)
{
unsigned int HashSIZE = 0;
while (*key != '\0')
HashSIZE = (HashSIZE << 5) + *key++;
return HashSIZE % SIZE;
}
//初始化
HashTabl Creat(int SIZE)
{
HashTabl H;
H = (HashTabl)malloc(sizeof(struct HashTbl));
if (H == NULL)
exit(0);
H->The_SIZE = SIZE;
H->The_ListNode = (Position *)malloc(sizeof(Position));
if (H->The_ListNode == NULL)
exit(0);
//状态 M = 1 ,表示初始化化过
for (int i = 0; i < SIZE; i++)
H->The_ListNode[i]->Enum = M;
return H;
}
//查找
unsigned int Find(char *key, HashTabl H)
{
unsigned int NUM;
int num; num = 0;
//找到对应的钥匙
NUM = Hash(key, H->The_SIZE);
// != M 代表没有被初始化, 即数组结束
while (H->The_ListNode[NUM]->Enum != M && H->The_ListNode[NUM]->ch != key)
{
NUM = NUM + 2 * (++num) - 1;
if (NUM >= H->The_SIZE)
NUM -= H->The_SIZE;
}
//返回对应数组角标
return NUM;
}
//插入
void Inset(HashTabl H, char *key)
{
unsigned int NUM;
NUM = Hash(key, H->The_SIZE);
while (H->The_ListNode[NUM]->Enum != L)
{
H->The_ListNode[NUM]->Enum = L;
H->The_ListNode[NUM]->ch = key;
}
}
//当初始化的数组被占据很多的时候,
//我们需要重新开辟一个更大的数组范围, 并将之前保存的数据拷贝过来
void ReHash(HashTabl &H)
{
int ReSIZE;
Position *P;
ReSIZE = H->The_SIZE;
P = H->The_ListNode;
H = Creat(2 * ReSIZE);
for (int i = 0; i < ReSIZE; i++)
if (P[i]->Enum == L)
Inset(H, P[i]->ch);
}
int main()
{
system("pause");
return 0;
}