hash散列表链表冲突

总所周知,利用哈希散列能很快的找到你数据存储的地方,减少索引时的时间复杂度,但是你使用的哈希算法,数据量一大就会有冲突问题,是用哈希最头疼的问题。

那么:

冲突是如何产生的?

上文中谈到,哈希函数是指如何对关键字进行编址的规则,这里的关键字的范围很广,可视为无限集,如何保证无限集的原数据在编址的时候不会出现重复呢?

如何解决冲突问题
既然不能避免冲突,那么如何解决冲突呢,显然需要附加的步骤。通过这些步骤,以制定更多的规则来管理关键字集合,通常的办法有:
a)开放地址法
开放地执法有一个公式:Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)
其中,m为哈希表的表长。di 是产生冲突的时候的增量序列。如果di值可能为1,2,3,...m-1,称线性探测再散列。
如果di取1,则每次冲突之后,向后移动1个位置.如果di取值可能为1,-1,2,-2,4,-4,9,-9,16,-16,...k*k,-k*k(k<=m/2) 
称二次探测再散列。如果di取值可能为伪随机数列。称伪随机探测再散列。

b)再哈希法 
当发生冲突时,使用第二个、第三个、哈希函数计算地址,直到无冲突时。缺点:计算时间增加。
比如上面第一次按照姓首字母进行哈希,如果产生冲突可以按照姓字母首字母第二位进行哈希,再冲突,第三位,直到不冲突为止。


c)链地址法
将所有关键字为同义词的记录存储在同一线性链表中。

下面就取一个链地址法的解决方案。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define  SIZE 10


//链表节点
typedef struct node
{
int data;
struct node* next;
}node;


//hash表的元素结构
//first:链表首地址
//last:链表最后一个节点地址
//这样当我有新的节点要来时,我就不用每次从第一个节点开始搜索判断,直接放到last后面
typedef struct block
{
node *first;
node* last;
}block;


//初始化hash表
void  inithashtable(block* hashtable[])
{
     int i;
     for(i=0;i<SIZE;i++)
     {
      hashtable[i]=NULL;
     }
}


//存储数据并用链表法解决冲突问题
void savehashtable(block* hashtable[])
{
    int i=0;  
    int j=0;  
int data;
srand((time_t)time(NULL));
for(i=0;i<100;i++)//模仿多个数据(随机生成100个2位整数)
{
        data=rand()%100;
        printf("%d\t",data);
        node * newnode=(node*)malloc(1*sizeof(node));
        while(newnode==NULL)
        {
        newnode=(node*)malloc(1*sizeof(node));
        }
        newnode->data=data;
        newnode->next=NULL;


        
        if(hashtable[data%10]==NULL)
        {
        block* bp;
       bp=(block*)malloc(1*sizeof(block));
            while(bp==NULL)
            {
                bp=(block*)malloc(1*sizeof(block));
            }        
        bp->first=newnode;
        bp->last=newnode;
        newnode=NULL;


        hashtable[data%10]=bp;
        }
        else
        {
        block* tmp=hashtable[data%10];
        tmp->last->next=newnode;
        tmp->last=newnode;
        newnode=NULL;
        }
}
}


//查找hash表
void queryhashtable(block* hashtable[],int  data)
{
     int flag=0;
     block* bh=hashtable[data%10];
     if(bh!=NULL)
     {
      node * curr;
      for(curr=bh->first;curr!=bh->last;curr=curr->next)
      {
      if(curr->data==data)
      {
      flag=1;
      printf("%d find\n",data);
      }
      }
     }
     if(flag==0)
     {
      printf("%d not find\n",data);
     }
}


int main(int argc, char const *argv[])
{
block * hashtable[SIZE];
inithashtable(hashtable);   
savehashtable(hashtable);
//测试代码
printf("\n");
int data;
scanf("%d",&data);
queryhashtable(hashtable,data);
return 0;
}


这是我学习中的心得,希望对大家能有帮助。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值