import
java.util.BitSet;
import
java.util.Vector;
class
DoubleHash {
private
int
TABLE_SIZE, keysPresent, PRIME;
private
Vector<Integer> hashTable;
private
BitSet isPrime;
private
static
final
long
MAX_SIZE = 10000001L;
private
void
setSieve() {
isPrime.set(
0
,
true
);
isPrime.set(
1
,
true
);
for
(
long
i =
2
; i * i <= MAX_SIZE; i++)
if
(!isPrime.get((
int
) i))
for
(
long
j = i * i; j <= MAX_SIZE; j += i)
isPrime.set((
int
) j);
}
private
int
hash1(
int
value) {
return
value % TABLE_SIZE;
}
private
int
hash2(
int
value) {
return
PRIME - (value % PRIME);
}
private
boolean
isFull() {
return
(TABLE_SIZE == keysPresent);
}
public
DoubleHash(
int
n) {
isPrime =
new
BitSet((
int
) MAX_SIZE);
setSieve();
TABLE_SIZE = n;
PRIME = TABLE_SIZE -
1
;
while
(isPrime.get(PRIME))
PRIME--;
keysPresent =
0
;
hashTable =
new
Vector<>();
for
(
int
i =
0
; i < TABLE_SIZE; i++)
hashTable.add(-
1
);
}
private
void
printPrime(
long
n) {
for
(
long
i =
0
; i <= n; i++)
if
(!isPrime.get((
int
) i))
System.out.print(i +
", "
);
System.out.println();
}
public
void
insert(
int
value) {
if
(value == -
1
|| value == -
2
) {
System.out.println(
"ERROR : -1 and -2 can't be inserted in the table"
);
}
if
(isFull()) {
System.out.println(
"ERROR : Hash Table Full"
);
return
;
}
int
probe = hash1(value), offset = hash2(value);
while
(hashTable.get(probe) != -
1
) {
if
(-
2
== hashTable.get(probe))
break
;
probe = (probe + offset) % TABLE_SIZE;
}
hashTable.set(probe, value);
keysPresent +=
1
;
}
public
void
erase(
int
value) {
if
(!search(value))
return
;
int
probe = hash1(value), offset = hash2(value);
while
(hashTable.get(probe) != -
1
)
if
(hashTable.get(probe) == value) {
hashTable.set(probe, -
2
);
keysPresent--;
return
;
}
else
probe = (probe + offset) % TABLE_SIZE;
}
public
boolean
search(
int
value) {
int
probe = hash1(value), offset = hash2(value), initialPos = probe;
boolean
firstItr =
true
;
while
(
true
) {
if
(hashTable.get(probe) == -
1
)
break
;
else
if
(hashTable.get(probe) == value)
return
true
;
else
if
(probe == initialPos && !firstItr)
return
false
;
else
probe = ((probe + offset) % TABLE_SIZE);
firstItr =
false
;
}
return
false
;
}
public
void
print() {
for
(
int
i =
0
; i < TABLE_SIZE; i++)
System.out.print(hashTable.get(i) +
", "
);
System.out.println();
}
}
public
class
Main {
public
static
void
main(String[] args) {
DoubleHash myHash =
new
DoubleHash(
13
);
int
[] insertions = {
115
,
12
,
87
,
66
,
123
};
int
n1 = insertions.length;
for
(
int
i =
0
; i < n1; i++)
myHash.insert(insertions[i]);
System.out.print(
"Status of hash table after initial insertions : "
);
myHash.print();
int
[] queries = {
1
,
12
,
2
,
3
,
69
,
88
,
115
};
int
n2 = queries.length;
System.out.println(
"\n"
+
"Search operation after insertion : "
);
for
(
int
i =
0
; i < n2; i++)
if
(myHash.search(queries[i]))
System.out.println(queries[i] +
" present"
);
int
[] deletions = {
123
,
87
,
66
};
int
n3 = deletions.length;
for
(
int
i =
0
; i < n3; i++)
myHash.erase(deletions[i]);
System.out.print(
"Status of hash table after deleting elements : "
);
myHash.print();
}
}