哈希表-散列表-哈希存储-代码实现

散列技术既是一种存储方法,也是一种查找方法。

哈希查找是一种秒杀查找,时间复杂度为O(1),只要用key通过哈希函数就直接计算出key的存储位置。

散列技术是在记录关键字的存储位置和关键字本身建立了一种对应关系-------就是一种函数关系f

     比如:f(key)=a*key+b (a,b为常数) ,存储的数据是key,存储的位置是f(key),这个f(key)可以是某个数组的下标。

散列函数:这种函数关系如何确定呢?---2个原则:计算简单(计算复杂导致效率低下)、散列地址分布均匀(有效利用空间,同时通过减小冲突而减小耗费时间)

                       几种散列函数参考:

                      (1)直接定址法:f(key)=a*key+b  (a,b为常数)

                      (2)数字分析法 :用于数字较长且有特点。比如类似电话号码处理。11位手机号码-数字比较有特点--基本就最后四位是最经常变化的(前三位是运营商,中间四位是地区,后四位是用户编号)。

                      (3)平方取中法:比如存储关键字1234,平方为1522756,再抽取中间三位227作为存储地址。

                      (4)折叠法:比如存储9876543210,可将其分为四组987|654|321|0,四组求和987+654+3210=962作为存储地址

                      (5)取余数法:f(key)=key%p  (p≤m,m为散列表的长度)

                      (6)随机数法:f(key)=random(key)

散列冲突:当存储两个不同的数据时,通过散列函数却计算得到相同的存储位置。f(key1)=f(key2)----散列冲突

解决散列冲突:散列冲突是很糟糕的事情,必须要解决,否则数据无法正常存储和查找。

                   解决方法参考如下:

                 (1)开放定址法---线性探测 :fi(key)=(f(key)+di)%m (di=1 ,2 , 3,....)

                 (2)开放定址法---二次探测:fi(key)=(f(key)+di)%m (di=1 ^2,-1^2,2^2,-2^2 , 3^2,....)

                 (3)开放定址法---随机探测:fi(key)=(f(key)+di)%m (di是随机数)

                 (4)再散列函数:就是事先准备多个散列函数,当冲突时更换散列函数再计算。

                 (5)链地址法:

                 (4)公共溢出区法:建立多个散列表。其中一个为基本表,另外为溢出表。当冲突时,将数据存储到溢出表中。

创建哈希表思路:

             1、确定哈希表的长度,根据长度建立哈希存储空间(比如定义数组)

             2、确定散列函数。

             3、有了空间可散列函数就要开始存数据了,取数据的关键字key,计算key的存储地址

             4、如果有冲突就转到相应的冲突解决方法。

哈希查找思路:

           1、给定key值和查找的对象存储空间(比如给以数组或链表)

            2、通过散列函数计算key值对应的存储地址

           3、同时判别是否冲突,冲突则通过更换地址继续查找,若找完散列表所有地址也没有找到key,则返回查找失败。


散列实现:存储方法:取余数法      +      解决散列冲突:开放定址法---线性探测法

#include"stdio.h"
#include"assert.h"
#include"math.h"
#include"stdlib.h"

#define SUCCESS 1
#define UNSUCCESS 0
#define HASHBIAOSIZE  15 //决定散列表大小的参数

#define M 12 //
#define NULLKEY -65535
//-----------------------------------------------------------------------------------//
typedef struct	HashTable{
	int* element;//
        int count;//
}HashTable;

int m=0;
void InitHashTable(HashTable *H);
void InsertHashKey(HashTable* H,int key);
int  Hash_f(int key);
int SearchHashKey(HashTable* H,int key);
//-----------------------------------------------------------------------------------//


void main(){
    int a[]={1,12,5,4,6,8,7,45,21,13,18,35};
	HashTable H;
	InitHashTable(&H);
	for(int i=0;i<M;i++){
		InsertHashKey(&H,a[i]);}
	for(int j=0;j<M;j++){
	if(-1==SearchHashKey(&H,a[j]))	printf("没查找到\n");
	else printf("查找元素存储的标号 %d\n",SearchHashKey(&H,a[j]));
	}

}



//-----------------------------------------------------------------------------------//
void InitHashTable(HashTable *H)
{
     m=HASHBIAOSIZE;   
	 H->element=(int*)malloc(m*sizeof(int));
	 H->count=HASHBIAOSIZE;
   
	for(int i=0;i<m;i++){
	    H->element[i]=NULLKEY;
	}
}
//-----------------------------------------------------------------------------------//
//存储元素
//这里采用取余数法
void InsertHashKey(HashTable* H,int key){
     
	int addr=Hash_f(key);
	while(H->element[addr]!=NULLKEY){ //冲突了
	   addr=(addr+1)%M;//解决冲突
	}
	H->element[addr]=key;

}
//-----------------------------------------------------------------------------------//
//查找元素
int SearchHashKey(HashTable* H,int key){
  
	int addr=Hash_f(key);
	while(H->element[addr]!=key){

	addr=(addr+1)%M;
	if(H->element[addr]==NULLKEY || addr==Hash_f(key)){return -1;}//UNSUCCESS
	}
	return addr;//查找成功,返回存储位置
}
//-----------------------------------------------------------------------------------//
int  Hash_f(int key){
	return key%M;
}
//-----------------------------------------------------------------------------------//




  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值