哈希表
哈希表又称散列表,是根据关键字key来加速访问的数据结构。通过一个关键字key通过一个映射函数到达表中一个位置访问记录,从而加快查询速度。而映射函数成为散列函数,存储记录的表成为散列表。
- 自实现一个简单哈希表采用数组+链表的形式
- 每一个数组维护了一个链表,链表中保存了具体数据
- 哈希算法采用了简单的取模算法
示意图
代码示例
- HashTab 用户直接操作的哈希表
- NodeLinkedList 哈希表中数组中内部维护的一个链表
- Node 存储数据的节点 真正保存数据的类
- HashTab中的增删改查方便本质上是通过数据key调用哈希函数确定数据在哪一个链表中从而调用链表的增删改查方法
public class HashTabDemo {
public static void main(String[] args) {
HashTab hashTab = new HashTab(5);
Node node1 = new Node(1, "jack");
Node node2 = new Node(3, "tom");
Node node3 = new Node(8, "tomas");
hashTab.add(node1);
hashTab.add(node2);
hashTab.add(node3);
hashTab.list();
node2.data = "tom-update";
hashTab.update(node2);
System.out.println("hashTab find " + hashTab.find(3).data);
System.out.println("hashTab find " + hashTab.find(4));
hashTab.del(node2);
System.out.println("after delete");
hashTab.list();
}
}
/**
* 面向用户使用的哈希表
*/
class HashTab {
// maxSize用于控制hash表中链表的数量
private final int size;
// 具体的hash表个数
private NodeLinkedList[] nodeLinkedLists;
HashTab(int size) {
this.size = size;
nodeLinkedLists = new NodeLinkedList[size];
// 初始化哈希表中每一个链表
for (int i = 0; i < size; i++) {
nodeLinkedLists[i] = new NodeLinkedList();
}
}
/**
* hash函数用于判断节点应该存在哪一个hash链上 这里采用了取模法
*
* @param id
* @return
*/
public int hash(int id) {
return id % size;
}
public void add(Node node) {
int hash = hash(node.id);
nodeLinkedLists[hash].add(node);
}
public void update(Node node) {
int hash = hash(node.id);
nodeLinkedLists[hash].update(node);
}
public void del(Node node) {
int hash = hash(node.id);
nodeLinkedLists[hash].del(node);
}
public Node find(int id) {
int hash = hash(id);
return nodeLinkedLists[hash].find(id);
}
public void list() {
for (int i = 0; i < size; i++) {
NodeLinkedList nodeLinkedList = nodeLinkedLists[i];
if (nodeLinkedList.isEmpty()) {
System.out.printf("第%d链表为空\n", i);
} else {
System.out.printf("第%d链表数据为", i);
nodeLinkedList.list();
}
}
}
}
/**
* 每一个数组中维护的链表
*/
class NodeLinkedList {
Node head;
public void add(Node node) {
if (head == null) {
head = node;
return;
}
Node temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = node;
}
public void update(Node node) {
if (head == null) {
return;
}
Node temp = head;
while (temp != null) {
if (node.id == temp.id) {
break;
}
temp = temp.next;
}
if (temp != null) {
temp.data = node.data;
}
}
public void del(Node node) {
if (head == null) {
return;
}
boolean isFind = false;
Node temp = head;
if (head.id == node.id) {
head = head.next;
return;
}
while (temp.next != null) {
if (temp.next.id == node.id) {
isFind = true;
break;
}
temp = temp.next;
}
if (isFind) {
temp.next = temp.next.next;
}
}
public Node find(int id) {
if (head == null) {
return null;
}
Node temp = head;
boolean isFind = false;
while (temp != null) {
if (temp.id == id) {
isFind = true;
break;
}
temp = temp.next;
}
if (isFind) {
return temp;
}
return null;
}
public void list() {
if (head == null) {
System.out.println("linked list is empty!");
return;
}
Node temp = head;
StringBuilder builder = new StringBuilder();
while (temp != null) {
builder.append(temp.data.toString()).append("\t");
temp = temp.next;
}
System.out.println(builder.toString());
}
public boolean isEmpty() {
return head == null;
}
public int size() {
if (head == null) {
return 0;
}
int size = 0;
Node temp = head;
while (temp != null) {
size++;
temp = temp.next;
}
return size;
}
}
/**
* 存储数据的节点
*/
class Node {
int id;
Object data;
Node next;
public Node(int id, Object data) {
this.id = id;
this.data = data;
}
}