# 散列表(拉链法与线性探测法)Java实现

```package practice;

import java.security.Principal;
import java.util.Scanner;

import edu.princeton.cs.algs4.*;

public class TestMain {
public static void main(String[] args) {
//50个随机数字
Integer[] a = new Integer[50];
for (int i = 0; i < a.length; i++) {
a[i] = new Integer(StdRandom.uniform(1, 1000));
}

//50个随机字符串
char ch = 'a';
int chl;
String []b = new String[50];
for (int i = 0; i < b.length; i++) {
int sl = StdRandom.uniform(1, 10);
b[i] = new String();
for (int j = 0; j < sl; j++) {
chl = StdRandom.uniform(0, 23);
b[i] += (char)(ch + chl);
}
}
//构建散列表
/*SeparateChainingHashST<String, Integer> hashmap = new SeparateChainingHashST<String, Integer>(50);

for (int i = 0; i < b.length; i++) {
hashmap.put(b[i], a[i]);
}*/

LinearProbingHashST<String, Integer> hashmap = new LinearProbingHashST<String, Integer>();
//占有率最好在1/2和1/8之间（数学证明结果），占有率越高，查找操作越难以命中，如果占有率为1，输入没有的值就会无限循环
for (int i = 0; i < b.length; i++) {
hashmap.put(b[i], a[i]);
}

hashmap.show();

String KeyShuRu;
Scanner ShuRu = new Scanner(System.in);
while (true) {
KeyShuRu = ShuRu.nextLine();
System.out.println(hashmap.get(KeyShuRu));
hashmap.delete(KeyShuRu);
hashmap.show();
}
}
}

/*
* 基于拉链法的散列表
* 散列值相同时，用一个链表储存
*/
class SeparateChainingHashST<K, V> {
private K key;
private V value;
private int M;
private SequentialSearchST<K, V>[] st;
public SeparateChainingHashST(int M) {
st = (SequentialSearchST<K, V>[]) new SequentialSearchST[M];
for (int i = 0; i < M; i++) {
st[i] = new SequentialSearchST();
}
}
/*
* 插入
*/
public void put(K key, V value) {
st[hash(key)].put(key, value);
}
/*
* 查找
*/
public V get(K key) {
return st[hash(key)].get(key);
}
/*
* 输出整个表
*/
public void show() {
for (int i = 0; i < M; i++) {
System.out.print("chain ["+i+"]  ");
st[i].show();
System.out.println();
}
}
/*
* 获取哈希值
*/
private int hash(K key) {
return (key.hashCode() & 0x7fffffff) % M; //可以返回一个M以内的正整数hash值

}
}

/*
* 基于线性探测法的散列表
* 散列值处已经有元素，就把值存在散列值处的后面（触底返0）
*/
class LinearProbingHashST<K, V> {
private K[] key;
private V[] value;
private int M = 16; //线性探测表的大小
private int N; //表中键值对的多少
public LinearProbingHashST() {
key = (K[]) new Object[M];
value = (V[]) new Object[M];
}
/*
* 插入
*/
public void put(K key, V value) {
if (N >= M/2) { resize(2*M);}

int hashv = hash(key);
while (true) {
if (hashv == M) { hashv = 0;}

if (this.key[hashv] == null) {
this.key[hashv] = key;
this.value[hashv] = value;
N++;
break;
}
else if (key.equals(this.key[hashv])) {
this.value[hashv] = value;
break;
}

hashv++;
}
}
/*
* 查找
*/
public V get(K key) {
int hashv = hash(key);
while (true) {
System.out.println("hashv = "+hashv);
if (this.key[hashv] == null) { return null;}
if (key.equals(this.key[hashv])) { return this.value[hashv];}
hashv++;
if (hashv == M) { hashv = 0;}
}
}
/*
* 输出表
*/
public void show() {
for (int i = 0; i < M; i++) {
System.out.printf("[%d]  %-10s%4d  \n", i, key[i], value[i]);
}
}
/*
* 删除元素
*/
public void delete(K key) {
//将元素删除
int hashv = hash(key);
while (true) {
if (this.key[hashv] == null) {
System.out.println("the value is not exist");
return;
}

if (key.equals(this.key[hashv])) {
this.key[hashv]   = null;
this.value[hashv] = null;
N--;
System.out.println("The value has been deleted");
break;
}

hashv++;
if (hashv == M) { hashv = 0;}
}

//将后面的元素全部重新插入
hashv = hash(key) + 1;
while (this.key[hashv] != null) {
K tempkey   = this.key[hashv];
V tempvalue = this.value[hashv];

this.key[hashv]   = null;
this.value[hashv] = null;
N--;

put(tempkey, tempvalue);

hashv ++;
if (hashv == M) { hashv = 0;}
}
}
/*
* 获取哈希值
*/
private int hash(K key) {
return (key.hashCode() & 0x7fffffff) % M;
}
/*
* 改变大小
*/
private void resize(int M) {
this.M = M;
K[] tempkey   = (K[]) new Object[M];
V[] tempvalue = (V[]) new Object[M];

for (int i = 0; i < key.length; i++) {
tempkey[i]   = key[i];
tempvalue[i] = value[i];
}

key   = tempkey;
value = tempvalue;
}
}

/*
* 链表
*/
class SequentialSearchST<K, V> {
private Node root;
class Node {
private K key;
private V value;
private Node next;
private Node(K key, V value) {
this.key   = key;
this.value = value;
}
/*
* 输出节点
*/
private void show() {
System.out.printf("%-10s%4d  ", key, value);
}
}
/*
* 插入
*/
public void put(K key, V value) {
if (root != null) {
Node tempnode = root;
while (true) {
if (key.equals(tempnode.key)) {
tempnode.value = value;
return;
}

if (tempnode == head) { break;}
tempnode = tempnode.next;
}
}
//上面是避免有重复的key
Node newnode = new Node(key, value);
if (root == null) {
root = newnode;
return;
}

}
/*
* 查找
*/
public V get(K key) {
Node tempnode = root;

while (!(tempnode == null)) {
if (key.equals(tempnode.key)) { return tempnode.value;}
tempnode = tempnode.next;
}

return null;
}
/*
* 输出整条链
*/
public void show() {
Node tempnode = root;
while (!(tempnode == null)) {
tempnode.show();
tempnode = tempnode.next;
}
}

}```

原文作者：zhangqi66
原文地址: https://www.cnblogs.com/zhangqi66/p/7325627.html
本文转自网络文章，转载此文章仅为分享知识，如有侵权，请联系博主进行删除。