哈希表

ⅰ亾dé卋堺 提交于 2020-02-04 03:03:51

Hash tabel:哈希表,又称散列表,是一种根据键码值(Key Value)而直接进行访问的数据结构。它把键码值映射到表中的一个位置来存储和访问,映射函数叫做哈希函数(又称散列函数)。在哈希表中,每个存储单元我们称之为位桶数组,而每个位桶数组中的元素是链表数据结构。这里的链表是单向链表,每个链表都有两个数据域,一个用来存放键码key,另一个用来存放值value,除此之外,还有一个标签即哈希值和一个指针域用来指向下一个链表。哈希码实际上是键key对象的内存地址经过处理后的结构,由于每个对象的内存地址一般都不一样,所以哈希码一般也不同,但是也有相同的情况。而哈希值是通过哈希码计算得来的,哈希值是链表在哈希表中存放的具体位置,即位桶数组的下标索引。一般来说,常用的有除法散列法、乘法散列法、全域散列法等。这里只简单说一下除法散列法。除法散列法即用哈希码除以位桶数组的长度然后取余得到哈希值,然后在位桶数组的相应哈希值索引处插入链表。
这里在位桶数组大小的设定上有一定的要求。原则上,我们应尽可能避免位桶数组的大小为2的整数次幂。如果数组的大小是2的p次幂,p为正整数,那么经过除法散列函数计算得到的哈希值的低p位将会和哈希码k的低p位相同。也就是说,哈希值和哈希码之间的相关性很大。如果几个键码的哈希码的低p位相同,经过除法散列函数所得到的哈希值也会相同。这样,这几个相同的哈希值所对应的键值对就会映射到位桶数组的同一索引处。然而,我们希望哈希码经过散列函数所得到的哈希值应尽可能的随机一些,使得数据尽可能地随机分布在散列表中。一般来说,一个不太接近2的整数次幂的素数,往往是p的较好选择。

java实现的哈希表代码如下:

public class Bucket<K,V>{
	Node[] table;
	int size=0;
	public Bucket(){
		this.table=new Node[23];
	}
	public static int myhash(int hashcode,int length) {
		return hashcode%length;
	}
	public void put(K key,V value) {
		Node newNode=new Node();
		boolean flag=true;
		newNode.hash=myhash(key.hashCode(),table.length);
		newNode.key=key;
		newNode.value=value;
		newNode.next=null;
		Node temp=table[newNode.hash];
		Node last=null;
		if(temp==null) {
			table[newNode.hash]=newNode;
			size++;
		}
		else {
			while(temp!=null) {
				last=temp;
				temp=temp.next;
			}
			last.next=newNode;
			size++;
		}
	}
	public V get(K key) {
		int hashValue=myhash(key.hashCode(),table.length);
		V value=null;
		if(table[hashValue]!=null) {
			Node temp=table[hashValue];
			while(temp!=null) {
				if(temp.key.equals(key)) {
					value=(V)temp.value;
					System.out.print(value+" ");
					temp=temp.next;
				}
			}
		}
		return value;
	}
	
public String toString() {
		StringBuilder sb=new StringBuilder("{");
		for(int i=0;i<table.length;i++) {
			Node num=table[i];
			while(num!=null) {
				sb.append(num.key+":"+num.value+" ");
				num=num.next;
			}
		}
		sb.setCharAt(sb.length()-1, '}');
		return sb.toString();
	}
	public static void main(String[] args) {
		Bucket<Integer,Integer> map=new Bucket<>();
		map.put(3, 32);
		map.put(1, 18);
		map.put(1, 13);
		map.put(0, 5);
		map.put(2, 20);
		map.put(3, 30);
		map.get(1);  //18 13
		System.out.println(map);  //{0:5 1:18 1:13 2:20 3:32 3:30}
	}
}
public class Node<K,V> {
	int hash;
	V value;
	K key;
	Node next;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!