下列代码主要实现了基于拉链法的散列表的添加元素put(),查找元素get(),删除元素delete(),遍历元素keys()等方法,我们需要首先根据元素值调用hash()方法找到该元素所对应的数组,而每一个数组都是一个链表,遍历链表,若元素不存在,则可以实现元素的添加,若存在,则可以实现元素的更新,删除等操作.
对于每一条链表的操作
package cn.edu.zzuli.api;
import edu.princeton.cs.algs4.Queue;
public class SequentialSearchST<Key, Value> {
private Node first;//链表首结点
private class Node{
//链表结点的定义
private final Key key;
private Value val;
private Node next;
public Node(Key key, Value val, Node next) {
this.key = key;
this.val = val;
this.next = next;
}
public Key getKey() {
return key;
}
public Value getVal() {
return val;
}
public void setVal(Value val) {
this.val = val;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
//查找给定的键,返回相关联的值
public Value get(Key key) {
for(Node i = first; i != null; i = i.next) {
if(key.equals(i.key))
return i.val;
}
return null;
}
//查找给定的键,找到则更新其值,否则在表中新建结点
public void put(Key key, Value val) {
for(Node i = first; i != null; i = i.next) {
if(key.equals(i.key)) {
i.val = val;
return;
}
}
first = new Node(key, val, first);
}
//删除结点
public void delete(Key key) {
first = delete(first, key);
}
private Node delete(Node x, Key key) {
if(x == null) {
return null;
}
if(key.equals(x.key)) {
return x.next;
}
x.next = delete(x.next, key);
return x;
}
public Iterable<Key> keys(){
Queue<Key> q = new Queue<Key>();
for(Node i = first; i != null; i = i.next) {
q.enqueue(i.key);
}
return q;
}
public Key getKey() {
return first.key;
}
}
基于拉链法的散列表
package cn.edu.zzuli.api;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.StdIn;
public class SeparateChainingHashST<Key, Value> {
//SequetialSearchST
private int N;//键值对总数
private int M;//散列表的大小
private SequentialSearchST<Key, Value>[] st;//存放链表对象的数组
public SeparateChainingHashST() {//默认的构造函数会使用997条链表
this(997);
}
public SeparateChainingHashST(int M) {
//创建M条链表
this.M = M;
//创造一个(SequentialSearchST<Key, Value>[])类型的,长度为M的数组
st = (SequentialSearchST<Key, Value>[]) new SequentialSearchST[M];
for(int i = 0; i < M; i++) {
//为每一个数组元素申请一个空间
st[i] = new SequentialSearchST();
}
}
private int hash(Key key) {
return (key.hashCode() & 0x7fffffff) % M;
}
public Value get(Key key) {
return (Value)st[hash(key)].get(key);
}
public void put(Key key, Value val) {
st[hash(key)].put(key, val);
}
public void delete(Key key) {
st[hash(key)].delete(key);
}
public Iterable<Key> keys(){
Queue<Key> queue = new Queue<Key>();
for(int i = 0; i < M; i++) {
System.out.println("第" + i +"个元素的链表");
for(Key key : st[i].keys()) {
queue.enqueue(key);
System.out.print(key + " " + get(key) + " ,");
}
System.out.println();
}
return queue;
}
public static void main(String[] args) {
SeparateChainingHashST<String, Integer> st = new SeparateChainingHashST<String, Integer>(5);
for (int i = 0; i < 13; i++) {
String key = StdIn.readString();
st.put(key, i);
}
for (String s : st.keys())
StdOut.println(s + " " + st.get(s));
st.delete("M");
StdOut.println("*************************************");
for (String s : st.keys()) {
StdOut.println(s + " " + st.get(s));
}
}
}
测试用例
S E A R C H E X A M P L E
不同的机器的hashCode()不一定相同