散列表(一)

一、基本概念

1.散列表,也叫哈希表:存放关键码散列地址的数组;
2.散列地址冲突:将不同的关键码映射到同一个散列地址上;
 (一般关键码集合比散列地址集合打得多)
3.散列函数选取原则:计算简单&分布均匀

二、散列函数构造方法

1.直接定址法:
  一一映射,要求散列地址空间的大小与关键吗集合的大小相同。
2.数字分析法:
取关键字中的若干位或其组合作哈希地址。
3.平方取中法:
取关键字平方后中间几位作哈希地址。
4.折叠法:
部分数字的叠加方法有:移位法和分界法。
5.随机数法:
取关键字的随机函数值作为散列地址。
6.除留余数法:
散列函数为:hash(key) = key%p  p<=m  (m为散列表中允许的地址数)。
根据经验,取一个小于等于m的置数p,得到的散列函数较好。
若p<m,存在几个散列地址在一开始不可能用散列函数计算出来,只可能在处理溢出是用到这些地址。
7.乘余取整法:
散列函数为: hash(key)= [n*(A*key%1)]   (用[]表示下取整,0<A<1, n为常数)

三、常见字符串哈希函数

常见的8个字符串哈希函数有:
SDBMHash, RSHash, JSHash, PJWHash, ELFHash, BKDRHash, DJBHash, APHash.
这些都是计算机科学家研究出来的,计算出来的哈希地址分布均匀,冲突较少。
使用时需注意:返回值要%地址总数,才会映射到哈希表的地址范围内。
下面的程序用来测试产生冲突的情况:
#include 
     
     
      
      
#define BUCKETS 101

unsigned int SDBMHash(char *str){
	unsigned int hash =0;
	while (*str)
		hash =(*str++)+(hash<<6)+(hash<<16)-hash;
	return (hash & 0x7fffffff)%BUCKETS;
}

int main(){
	char *keywords[]={
		"auto","break","case","char","const","continue","default","do",
		"double","else","enum","extern","float","for","goto","if",
		"int","long","register","return","short","signed","sizeof","static",
		"struct","switch","typedef","union","unsigned","void","volatile","while"
	};
	int count[BUCKETS]={0};
    int number=sizeof(keywords) /sizeof(keywords[0]);
	int i;
	for (i=0;i
      
      
     
     
运行结果: 结果显示的依次为——关键字、散列地址和该地址的映射次数

说明:
1.一维数组初始化时,若为全部赋值,则剩下的被初始化为0;
2.字符串数组可以定义为 char *a[]
  字符串用指针标志,eg: char *a[5]={"red","yellow","blue","white","black"};
  向散列函数传递的实参为char *,即keywords[i].
  另外,sizeof(char *) =4.
3.printf: 
 格式替代符 %s:字符串
 %-10s 格式为左对齐且宽度为10的字符串代替(-表示左对齐,不使用则是右对齐)

























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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值