#include " stdio.h "
#include " stdlib.h "
#define SUCCESS 1
#define UNSUCCESS 0
#define DUPLICATE -1
#define OK 1
#define ERROR -1
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)< (b))
#define LQ(a,b) ((a)<=(b))
#define BT(a,b) ((a)> (b))
#define NULLKEY -111
int hashsize[] = { 11 , 19 , 29 , 37 }; // 哈希表容量递增表,
// 一个合适的素数序列
int m = 0 ; // 哈希表表长,全局变量
typedef int KeyType;
typedef int info;
typedef struct
{
KeyType key;
// info otherinfo;
}ElemType;
typedef struct
{
ElemType * elem;
int count;
int sizeindex;
}HashTable;
int InitHashTable(HashTable & H)
{ // 操作结果: 构造一个空的哈希表
int i;
H.count = 0 ; // 当前元素个数为0
H.sizeindex = 0 ; // 初始存储容量为hashsize[H.sizeindex]
m = hashsize[ 0 ];
H.elem = (ElemType * )malloc(m * sizeof (ElemType));
if ( ! H.elem)
exit( 0 ); // 存储分配失败
for (i = 0 ;i < m;i ++ )
H.elem[i].key = NULLKEY; // 未填记录的标志
return OK;
}
void DestroyHashTable(HashTable & H)
{ // 初始条件: 哈希表H存在。操作结果: 销毁哈希表H
free(H.elem);
H.elem = NULL;
H.count = 0 ;
H.sizeindex = 0 ;
} // DestroyHashTable
int Hash(KeyType K)
{ // 一个简单的哈希函数(m为表长,全局变量)
// 除留余数法
return K % m;
} // Hash
void collision( int & p, int d) // 线性探测再散列
{ // 开放定址法处理冲突
p = (p + d) % m;
} // collision
int SearchHash(HashTable H,KeyType K, int & p, int & c)
{
p = Hash(K); // 求得哈希地址
while (H.elem[p].key != NULLKEY && ! EQ(K,H.elem[p].key)) // 如果该位置填有记录,并且关键字不相等
{
collision(p, ++ c); // 探测下一个位置p
if (c >= m)
break ;
}
if (EQ(K,H.elem[p].key)) // 查找成功,p返回待查数据元素位置
return SUCCESS;
else // 查找不成功(H.elem[p].key==NULLKEY)
return UNSUCCESS; // p返回的是插入位置
} // SearchHash
int InsertHash(HashTable & H,ElemType e);
void RecreateHashTable(HashTable & H) // 重建哈希表
{
int i,count = H.count;
ElemType * p, * elem = (ElemType * )malloc(count * sizeof (ElemType));
p = elem;
printf( " 重建哈希表\n " );
for (i = 0 ;i < m;i ++ ) // 先保存原有的数据到elem中
if ((H.elem + i) -> key != NULLKEY) // 该单元有数据
* p ++=* (H.elem + i);
H.count = 0 ; // H.coun重置为0
H.sizeindex ++ ; // 增大存储容量
m = hashsize[H.sizeindex];
p = (ElemType * )realloc(H.elem,m * sizeof (ElemType));
if ( ! p)
exit( - 1 ); // 存储分配失败
H.elem = p;
for (i = 0 ;i < m;i ++ )
H.elem[i].key = NULLKEY; // 未填记录的标志(初始化)
for (p = elem;p < elem + count;p ++ ) // 将原有的已经保存的数据按照新的表长插入到重建的哈希表中
InsertHash(H, * p);
} // RecreateHashTable
int InsertHash(HashTable & H,ElemType e)
{ // 查找不成功时插入数据元素e到开放定址哈希表H中,并返回OK;
// 若冲突次数过大,则重建哈希表
int c,p;
c = 0 ;
if (SearchHash(H,e.key,p,c)) // 表中已有与e相同的元素
return DUPLICATE; // SUCCESS=1
else if (c < hashsize[H.sizeindex] / 2 ) // 冲突次数c未达到上限,(c的阀值可调)
{ // 插入e
H.elem[p] = e;
++ H.count;
return OK;
}
else
RecreateHashTable(H); // 冲突次数c达到上限,将原来的哈希表重建,不包括现在正要插入的数据e
return ERROR;
}
int InsertHashD(HashTable & H)
{
ElemType e;
printf( " input the data until -1\n " );
scanf( " %d " , & e.key);
while (e.key !=- 1 )
{
InsertHash(H,e);
scanf( " %d " , & e.key);
} // while
return 1 ;
} // InsertHashD
int SearchHashD(HashTable & H)
{
KeyType key;
int p = 0 ,c = 0 ;
printf( " input the data you want to search:\n " );
scanf( " %d " , & key);
if (SearchHash(H,key,p,c))
printf( " the location is %d,%d\n " ,p,H.elem[p].key);
else printf( " Search Failed!\n " );
return 1 ;
} // SearchHashD
void print( int p,ElemType r)
{
printf( " address=%d (%d)\n " ,p,r.key);
void TraverseHash(HashTable H, void ( * Vi)( int ,ElemType))
{ // 按哈希地址的顺序遍历哈希表
printf( " 哈希地址0~%d\n " ,m - 1 );
for ( int i = 0 ;i < m;i ++ )
if (H.elem[i].key != NULLKEY) // 有数据
Vi(i,H.elem[i]);
} // TraverseHash
void TraverseHashD(HashTable & H)
{
TraverseHash(H,print);
} // TraverseHashD
int main()
{
HashTable H;
InitHashTable(H); // 初始化
InsertHashD(H); // 构造哈希表
// SearchHashD(H); // 查找
TraverseHashD(H); // 遍历
DestroyHashTable(H); // 销毁
return 1 ;
}