哈希表的构造和查找算法

实现哈希表的构造和查找算法,要求:用除留余数法构造哈希函数,分别用一次探测再散列、二次探测再散列解决冲突。


#include<stdio.h>
#include<stdlib.h>
#include<math.h>
/*typedef struct {
	ElemType *elem;
	int count;
	int sizeindex;
}HashTable;*/
typedef struct{
    int key;
}keytype;

typedef struct { 
    keytype elem[100];
    int length;   /*当前的长度*/
    int size;  /*哈希表的总长*/
}hashtable; 
int a=0,b=0,select;
int hash2(int i,int t)
{  if(i%2==0)
     t=t+pow(++a,2);
   else
     t=t-pow(++b,2);
   return t;
}
int hash1(int i,int t)
{ 
i++;
 t=i;
   return t;
}
int hash(hashtable h,int k)
{
    return  k%(h.size);
}
void creat(hashtable *h)
{  int i,j,key,t,p;
   printf("请输入哈希表的长度,和表中的记录长:");
   scanf("%d%d",&h->size,&h->length);
   printf("请选择:\n1。采用线性探测再散列处理冲突\n2。采用二次探测再散列处理冲突"); 
   scanf("%d",&select);
   for(i=0;i<h->size;i++)//初始化将哈希表中的关键字都置为-1,代表此存储位子为空 
   h->elem[i].key=-1;
   printf("input data:\n");
   for(j=0;j<h->length;j++)
    {  scanf("%d",&key);
       p=hash(*h,key);
       if(h->elem[p].key==-1)
         h->elem[p].key=key;
       else
         {  i=0;
            t=p;
            while(h->elem[p].key!=-1&&h->elem[p].key!=key&&i<h->size/2)
              {  
              if(select==2){
			  
			  p=hash2(i,t);
                 i++;
             }else if(select==1){
			 
             p=hash1(i,t);
                 i++;
             }
              }
            a=b=0;     //此纪录找到储存位置,将a,b参数置0,为下一个记录冲突做准备 
            h->elem[p].key=key;
         }
     }
}
int SearchHash(hashtable H,int k){
        int  p,i=0,t=0;
	p=hash(H,k);                                //求得Hash的地址 
	while(H.elem[p].key!=-1&&(k!=H.elem[p].key))//该地址中有记录,并且关键字不相等 
	 {
	 	if(select==2){
		 
	 p=hash2(i,t);                            // 用二次探测法求的下一个探测的地址 
	 i++;   
         }else if(select==1){
         	 p=hash1(i,t);                            // 用二次探测法求的下一个探测的地址 
	         i++;
		 }
    }
	if(k==H.elem[p].key)
	return p;
	else
	return -1;
	
}

void printhash(hashtable *h)

{  int i;

   for(i=0;i<h->size;i++)

    printf("%-4.2d",i);

     printf("\n");

    for(i=0;i<2*h->size;i++)

    printf("--");

    printf("\n");

    for(i=0;i<h->size;i++)

    printf("%-4.2d",h->elem[i].key);

}
int main()

{   hashtable t;
    int i,key,key1,c;
    creat(&t);
    printf("显示哈希表:\n\n");
    printhash(&t);
    printf("\n\n当前哈希表记录长为:%d\n",t.length);
    printf("\n请输入要查找记录的关键字:");
    scanf("%d",&key);
    c=SearchHash(t,key);
    if(c!=-1)
      printf("该记录的位子是:%d\n",c);
    else
      printf("没有找到该记录!\n");
      
      
      
      
      return 0;

}

测试结果如下:

请输入哈希表的长度,和表中的记录长:30 10
请选择:
1。采用线性探测再散列处理冲突
2。采用二次探测再散列处理冲突2
input data:
12 13 14 56 25 35 36 38 37 12
显示哈希表:

00  01  02  03  04  05  06  07  08  09  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  
------------------------------------------------------------------------------------------------------------------------
-01 -01 -01 -01 -01 35  36  37  38  -01 -01 -01 12  13  14  -01 -01 -01 -01 -01 -01 -01 -01 -01 -01 25  56  -01 -01 -01 

当前哈希表记录长为:10

请输入要查找记录的关键字:14
该记录的位子是:14

 

  • 5
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 哈希表构造算法: 1. 选择一个质数作为哈希表的长度m。 2. 对于每个要存储的元素x,使用除留余数法计算出哈希函数h(x)=x mod m的值,并将元素x存储在h(x)处。 查找算法: 1. 计算出要查找元素x的哈希值h(x) 2. 先在h(x)处查找,如果找到了,返回x。 3. 如果没有找到,使用二次探测再散列或链地址法解决冲突。 二次探测再散列:如果h(x)处有元素,则尝试在h(x)+1^2,h(x)-1^2,h(x)+2^2,h(x)-2^2...处查找,直到找到或者空置。 链地址法:如果h(x)处有元素,则将x插入到h(x)处的链表查找时遍历h(x)处的链表寻找x. ### 回答2: 哈希表是一种基于哈希函数实现的数据结构,可以用于快速的查找、插入、删除数据项。哈希函数的目的是将关键字映射到特定的置,使得访问数据时具有高效性。 构造哈希函数最常见的方法是除留余数法,它将关键字取余数后映射到一个连续的地址空间。具体来说,哈希函数可以定义为:Hash(k) = k % M,其k是关键字值,M是哈希表的容量。 在哈希表,解决冲突问题是十分关键的,因为不同关键字可能映射到相同的地址空间。解决冲突的两种方法是二次探测再散列和链地址法。 二次探测再散列是一种开放定址的方法,即当发生冲突时,探测该空间的下一个空间是否可用。具体来说,如果哈希函数的结果为h,但是该置已经被占用,那么我们就需要探测h+1、h+4、h+9...等等,直到找到一个可用的置。这样的方法称为二次探测。当然,如果我们探测到哈希表的最后,那么就需要从头开始。如果发现哈希表已经达到了它的最大容量,则需要进行再散列(即重新构建一个更大的哈希表,并将原来的数据复制到新表)。 链地址法是另一种解决哈希表冲突的方法。它的基本思想是,将哈希表具有相同哈希值的项链接在一起,形成一个链表。当我们查找一个值时,先通过哈希函数计算出该值在哈希表置,再在相应的链表搜索目标键值。 总之,在构建和查找哈希表时,哈希函数的设计和冲突解决方法都是至关重要的。除留余数法是构建哈希函数的最基础方法,而二次探测再散列和链地址法则是解决哈希表冲突的两种常见策略。我们需要根据自己的实际需要,选择适合的方法,来实现高效的哈希表操作。 ### 回答3: 哈希表是一种常见的数据结构,用于快速地查找和插入数据。哈希表的核心是哈希函数,通过哈希函数将数据映射到一个固定的置。本文将介绍哈希表构造方法和查找算法,其哈希函数采用除留余数法,解决冲突的方法分别采用二次探测再散列和链地址法。 一、哈希函数的构造 哈希函数是哈希表实现的核心,它将数据映射到哈希表的一个置,使得数据可以快速地进行查找。除留余数法是一种比较简单的哈希函数构造方法,它的基本思想是将关键字通过取余运算映射到哈希表置。 假设哈希表的长度为m,关键字为k,那么哈希函数h(k)可以用以下公式表示: h(k)=k mod m 其mod表示取余运算。除留余数法的优点是简单易用,缺点是当哈希表数据分布不均匀时,容易引起哈希冲突。 二、解决冲突的方法 在哈希表,当两个数据经过哈希函数映射到同一个置时,就会发生冲突。为了解决冲突,可以采用两种方法:二次探测再散列和链地址法。 1. 二次探测再散列 二次探测再散列是一种基于探测的方法,它通过在哈希表寻找下一个空槽,将冲突的数据放在该置上。 假设哈希表有冲突的元素k1,它的哈希值为h(k1),如果h(k1)的置已经被占用,那么就查找h(k1)+1、h(k1)+4、h(k1)+9等置,直到找到一个空置。具体算法如下: 1. 计算元素k的哈希值h(k) 2. 如果h(k)的置为空,则将元素k插入该置,结束 3. 如果h(k)的置已经被占用,那么就寻找下一个空槽,具体方法是h(k)+1、h(k)+4、h(k)+9等置,直到找到一个空置 4. 如果哈希表已满,则进行再散列,增加哈希表的长度 二次探测再散列的优点是简单易用,缺点是容易引起聚集效应,导致哈希表的性能下降。 2. 链地址法 链地址法是一种基于链表的方法,它将哈希表同一个置上的元素用一个链表来存储。这样,当发生冲突时,只需要将元素插入对应置的链表即可。 具体算法如下: 1. 计算元素k的哈希值h(k) 2. 将元素k插入到h(k)所在的链表 链地址法的优点是几乎不会出现冲突,缺点是需要额外的空间来存储链表,且插入和删除操作需要遍历整个链表。 三、哈希表查找算法 哈希表查找算法分两步走:首先通过哈希函数计算出要查找的元素所在的置,然后在该置上查找元素。 具体算法如下: 1. 计算元素k的哈希值h(k) 2. 查找哈希表h(k)置上的元素 如果哈希表h(k)置上的元素不是要查找的元素,则按照冲突解决方法的规则,依次查找h(k)+1、h(k)+4、h(k)+9等置上的元素,直到找到要查找的元素或者哈希表不存在要查找的元素为止。 以上就是哈希表构造方法和查找算法,其哈希函数采用除留余数法,解决冲突的方法分别采用二次探测再散列和链地址法。哈希表是一种常用的数据结构,在具有大量数据的应用场景发挥着重要的作用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值