散列表

 

散列表

1.直接寻址表

 

如图:关键字集合U={0,1,2,...,m-1},用一个数组T来表示,每个关键字指向一个数据,当然数据不一定是存满的,也就是说有些关键字可能会用不到。key表示已经存储数据的关键字集合。

当关键字的全域U比较小时,直接寻址是一种简单有效的技术。查找,删除等操作只需要O(1)时间。

如果U很大,要保存一个|U|大小的T显然是不可能的,实际情况是用到的关键字集合key对U来说可能很小,因而分配给T的大部分空间会造成浪费。这就好比腾讯有上亿的用户,但某一时间在线的用户可能只会是其中的一部分,如采用直接寻址法就会产生上述问题。

 

2.散列表

 

    如果U很大,用散列表来解决上述问题。在直接寻址方式下key直接指向对应元素;在散列方式下,具有关键字key的元素处在hash(key)中。亦即,利用散列函数hash(),根据关键字key计算其hash(key)值,将元素存在hash(key)对应处。

这样,又产生了不同的key可能有相同的hash()值的冲突问题,这种情形称作碰撞。解决这个问题可用链接法和开发寻址法。

链表法就是将散列到同一位置处的元素放在一个链表中。链表是无序的,在查找一个元素时要遍历链表。

3.开放寻址法

 

在开放寻址法中,所有元素都在散列表中,当查找一个元素时,要查找所有表项,直到找到所需元素,或者最终发现不在表中。在这种方法中,散列表可能被填满,以至于不能插入任何新的元素,但装载因子绝对不会大于1。

 

下面是我写的代码,当产生冲突时用链表法解决:

 

每个元素用结点表示,关键字ID

public class StudentNode {
	
	//学号
	public String ID;
	//子结点
	public StudentNode child;
}
 

BKDRHash算法:

package hash.net;
/**
 * BKDRHash算法
 * @author wenxiaodong
 *2012-10-20 下午04:55:21
 */
public class HashArithmetic {
	
	//保存结点的数组
	public StudentNode[] students=new StudentNode[20];
	
	//BKDRHash算法,得到hash值
	public int BKDRHash(String s){
		//哈希值
		int hash=0;
		int seed=31;
		int i=0;
		while(i<s.length()){
			hash=hash*seed+s.charAt(i);
			i++;
		}
		return hash;
	}
	
	
	//添加结点的方法
	public void put(String ID){
		StudentNode sn=new StudentNode();
		sn.ID=ID;
		//得到hash值
		int key=BKDRHash(ID)%20;
		//如果此位置为空
		if(students[key]==null){
		students[key]=sn;
		}else{//如果已经有元素了
		sn.child=students[key];
		students[key]=sn;
		}
		System.out.print("key值"+key);
	}
	
	
	//删除结点的方法
	public void delete(String ID){
		//得到hash值
		int key=BKDRHash(ID)%20;
		//如果此处元素不存在
		if(students[key]==null){
			System.out.println("此处元素为空");
		}else{//此处存在元素
			StudentNode s1 = null;
			StudentNode s2=students[key];
			while(s2!=null){
				if(s2.ID==ID){
					if(s1==null){
						students[key]=s2.child;
					}else{
						s1.child=s2.child;
					}
					return;
				}
				s1=s2;
				s2=s2.child;
			}
		}
		System.out.println("要删除的元素不存在");
	}
	
	
	
}

 

主函数:

public class TestMain {
	
	public static void main(String args[]){
		
		HashArithmetic ha=new HashArithmetic();
		String str=new String();
		for(int i=0;i<40;i++){
			ha.put(str+i);
			System.out.println("   ID:"+ha.students[ha.BKDRHash(str+i)%20].ID);
		}
	}

}
 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值