散列以常数时间执行插入、删除和查找技术
散列不支持findMax,findMin等排序操作
分离链接法
如图:
在Java中对象要作为key要实现***equals***和***hascode***方法。
装填因子
λ为散列表中的元素个数对该表大小的比。
不使用链表的散列表
线性探测法
适用场景: λ <0.5,也就是元素不到表大小的一半情况下。 hash = x mode TableSize,如果原先的位置上已经有人了,那就往后挪动,一直到找到一个空位置。
平方探测法
原理 : hash = x mode TableSize,如果位置上已经有人了,那么就采用hash + 1^2 ,如果还是有人,那么接着用 hash - 1^2 , 如果还是有人,那么接下来用 hash + 2^2 = hash + 4, 如果 有人,同样, 采用 hash - 2^2 = hash - 4......等等,一直到找到位置为止。
双散列
原理 : hash(x) = R - (x mod R) 其中,R是小于TableSize的素数
代码如下:
分离链接散列表
public class SeparateChainingHashTable<AnyType> {
private int size ;
public SeparateChainingHashTable(){
this(DEFAULT_TABLE_SIZE);
}
public SeparateChainingHashTable(int size) {
theLists = new LinkedList[nextPrime(size)];
for (int i = 0; i< theLists.length ; i++){
theLists[i] = new LinkedList<AnyType>();
}
}
public void insert(AnyType x) {
List<AnyType> whichList = theLists[myhash(x)];
if (!whichList.contains(x)){
whichList.add(x);
//rehash
if (++ currentSize > theLists.length){
rehash();
}
}
}
public void remove(AnyType x){
List<AnyType> whichList = theLists[myhash(x)];
if (whichList.contains(x)){
whichList.remove(x);
currentSize -- ;
}
}
public boolean contains(AnyType x){
List<AnyType> whichList =theLists[myhash(x)];
return whichList.contains(x);
}
public void makeEmpty(){
for (int i=0; i < theLists.length ; i++){
theLists[i].clear();
}
currentSize = 0;
}
private static final int DEFAULT_TABLE_SIZE = 101;
private List<AnyType>[] theLists;
private int currentSize;
private void rehash(){
List<AnyType>[] oldArray = theLists;
theLists = new List[nextPrime(2* theLists.length)];
for (int j = 0; j < theLists.length ; j++){
theLists[j] = new LinkedList<>();
}
//copy
currentSize = 0;
for(int i= 0; i < oldArray.length ; i++){
for (AnyType item : oldArray[i]){
insert(item);
}
}
}
private int myhash(AnyType x){
int hashVal = x.hashCode();
hashVal %= theLists.length;
if(hashVal < 0 ){
hashVal += theLists.length;
}
return hashVal;
}
private static int nextPrime(int n){
if (n <= 2) {
return 2;
}else{
while (!isPrime(n)) {
n++;
}
return n;
}
}
private static boolean isPrime(int n){
for (int i = 2; i < sqrt(n); i++) {
if (n%i == 0) {
return false;
}
}
return true;
}
}
复制代码
平方探测散列表
/**
* 平方探测方法的散列表
* @param <AnyType>
*/
public class QuadraticProbingHashTable<AnyType> {
public QuadraticProbingHashTable(){
this(DEFAULT_TABLE_SIZE);
}
public QuadraticProbingHashTable(int size){
allocateArray(size);
makeEmpty();
}
public void makeEmpty(){
currentSize = 0;
for (int i=0; i<array.length ; i++){
array[i] = null;
}
}
public boolean contains(AnyType x){
int currentPos = findPos(x);
return isActive(currentPos);
}
public void insert(AnyType x){
int pos = findPos(x);
while(isActive(pos)){ // duplicate,do nothing
return;
}
array[currentSize] = new HashEntry<AnyType>(x,true);
//rehash
if (++ currentSize >= array.length /2 ){
rehash();
}
}
public void remove(AnyType x){
int currentPos = findPos(x);
if (isActive(currentPos)){
array[currentPos].isActive = false;
}
}
private static class HashEntry<AnyType>{
public AnyType element;
public boolean isActive;
public HashEntry(AnyType e){
this(e,true);
}
public HashEntry(AnyType e,boolean i){
this.element = e;
this.isActive = i;
}
}
private static final int DEFAULT_TABLE_SIZE = 11;
private HashEntry<AnyType>[] array;
private int currentSize;
private void allocateArray(int arraySize){
array = new HashEntry[arraySize];
}
private boolean isActive(int currentPos){
// if (currentPos < 0 || currentPos > currentSize){
// return false;
// }
// //forget to judge null
// return array[currentPos].isActive;
return array[currentPos] != null && array[currentPos].isActive;
}
private int findPos(AnyType x){
int offset = 1;
int currentPos = myhash(x);
while(array[currentPos] != null && !array[currentPos].element.equals(x)){
currentPos += offset;
offset += 2;//todo why???
if (currentPos >= array.length){
currentPos -= array.length; // 从头开始
}
}
return currentPos;
}
private void rehash(){
HashEntry<AnyType>[] oldArray = array;
//create a new double-sized empty table
allocateArray(nextPrime(2* oldArray.length));
currentSize = 0;
//copy
for (int i=0; i < oldArray.length ; i++){
if(oldArray[i] != null && oldArray[i].isActive){
insert(oldArray[i].element);
}
}
}
private int myhash(AnyType x){
int hashVal = x.hashCode();
hashVal %= array.length;
if(hashVal < 0 ){
hashVal += array.length;
}
return hashVal;
}
private static int nextPrime(int n){
if (n <= 2) {
return 2;
}else{
while (!isPrime(n)) {
n++;
}
return n;
}
}
private static boolean isPrime(int n){
for (int i = 2; i < sqrt(n); i++) {
if (n%i == 0) {
return false;
}
}
return true;
}
}
复制代码