哈希表的运算算法
一、开放定址法构造的哈希表的运算算法
1、哈希表类型
#define NULLKEY-1 //定义空关键字
#define DELKEY-2 //定义被删关键字
typedef int KeyType; //关键字类型
typedef struct
{
KeyType key; //关键字域
int count; //探测次数域
}HashTable;
2、插入建表算法
void InsertHT(HashTable ha[],int &n,int m,int p,KeyType k)
{
int i,adr;
adr=k%p; //计算哈希函数值
if(ha[adr].key==NULLKEY||ha[adr].key==DELKEY)
{
ha[adr].key=k; //k可以直接放在哈希表中
ha[adr].count=1;
}
else //发生冲突,用线性探测法解决冲突
{
i=1; //i记录k发生冲突的次数
do
{
ard=(ard+1)%m; //线性探测
i++;
}while(ha[adr].key!=NULLKEY&&ha[adr].key!=DELKEY);
ha[adr].key=k; //在adr处放置k
ha[adr].count=i; //设置探测次数
}
n++; //哈希表中总元素个数增1
}
void CreateHT(HashTable ha[],int &n,int m,int p,KeyType keys[],int nl)
{
for(int i=0;i<m;i++)
{
ha[i].key=NULLKEY;
ha[i].count=0;
}
n=0; //哈希表中总元素个数从0开始递增
for(i=0;i<nl;i++)
{
InsertHT(ha,n,m,p,keys[i]); //插入n个关键字
}
}
3、删除算法
bool DeleteHT(HashTable ha[],int &n,int m,int p,KeyType k)
{
int adr;
adr=k%p; //计算哈希函数值
while(ha[adr].key!=NULLKEY&&ha[adr].key!=k)
{
adr=(adr+1)%m; //线性探测
}
if(ha[adr].key==k) //查找成功
{
ha[adr].key=DELKEY; //删除k
return true;
}
else
return fales;
}
4、查找算法
void SearchHT(HashTable ha[],int m,int p,KeyType k)
{
int i=1,adr;
adr=k%p;
while(ha[adr].key!=NULLKEY&&ha[adr].key!=k)
{
i++; //累计关键字比较次数
adr=(adr+1)%m; //线性探测
}
if(ha[ard].key==k) //查找成功
{
printf("成功:关键字%d,比较%d次\n",k,i);
}
else
{
printf("失败:关键字%d,比较%d次\n",k,i);
}
}
5、线性探测计算成功和不成功平均查找长度
对于查找不成功的理解:
根据哈希函数地址为mod7,因此任何一个数经散列函数计算以后的初始地址只可能在0~6的位置
查找0~6位置查找失败的查找次数为:
地址0,到第一个关键字为空的地址2需要比较3次,因此查找不成功的次数为3
地址1,到第一个关键字为空的地址2需要比较2次,因此查找不成功的次数为2
地址2,到第一个关键字为空的地址2需要比较1次,因此查找不成功的次数为1
地址3,到第一个关键字为空的地址4需要比较2次,因此查找不成功的次数为2
地址4,到第一个关键字为空的地址4需要比较1次,因此查找不成功的次数为1
地址5,到第一个关键字为空的地址9,需要比较5次,因此查找不成功的次数为5
地址6,到第一个关键字为空的地址,9,需要比较4次,因此查找不成功的次数为4
二、拉链法构造的哈希表的运算
1、哈希表类型
typedef int KeyType; //关键字类型
typedef struct node
{
KeyType key; //关键字域
struct node *next; //下一个结点指针
}NodeType;
typedef struct
{
NodeType *firstp; //首节点指针
}HashTable;
2、插入建表算法
void InsertHT(HashTable ha[],int &n,int p,KeyType k)
{
int adr;
adr=k%p; //计算哈希函数值
NodeType *q;
q=(NodeType *)malloc(sizeof(NodeType));
q->key=k; //创建结点q,存放k
q->next=NULL;
if(ha[adr].firstp==NULL) //若单链表adr为空
{
ha[adr].firstp=q;
}
else
{
q->next=ha[adr].firstp; //头插法
ha[adr].firstp=q;
}
n++; //哈希表中结点总个数增1
}
void CreateHT(HashTable ha[],int &n,int m,int p,KeyType keys[],int nl)
{
for(int i=0;i<m;i++) //置初值
{
ha[i].firstp=NULL;
}
n=0;
for(i=0;i<nl;i++)
{
InsertHT(ha,n,p,keys[i]); //插入n个关键字
}
}
3、删除算法
bool DeleteHT(HashTable ha[],int &n,int m,int p,KeyType k)
{
int adr;
adr=k%p; //计算哈希函数值
NodeType *q,*preq;
q=ha[adr].firstp; //q指向首节点
if(q==NULL)
return false;
if(q->key==k) //首节点为k
{
ha[adr].firstp=q->next; //删除结点q
free(q);
n--;
return true;
}
preq=q; q=q->next; //首节点不为k
while(q!=NULL)
{
if(q->key==k) //查找成功
break; //退出循环
q=q->next;
}
if(q!=NULL) //查找成功
{
preq->next=q->next; //删除结点q
free(q);
n--; //结点总数减1
return true;
}
else
return false;
}
4、查找算法
void SearchHT(HashTable ha[],int m,int p,KeyType k)
{
int i=1,adr;
adr=k%p;
NodeType *q;
q=ha[adr].firstp; //q指向对应单链表的首节点
while(q!=NULL) //扫描adr单链表所有结点
{
i++;
if(q->key==k) //查找成功
break;
q=q->next;
}
if(q!=NULL)
{
printf("成功:关键字%d,比较%d次\n",k,i);
}
else
{
printf("失败:关键字%d,比较%d次\n",k,i);
}
}