数据结构——哈希表/散列表

  
    
#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);
}
// print

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 ;
}

 

你可能感兴趣的:(数据结构)