hash
Hash
: κ²μκ³Ό λλΆμ΄ λ°μ΄ν°μ μΆκ°μ μμ λ ν¨μ¨μ μΌλ‘ μνν μ μλ λ°©λ² μμ μ΄λμ νμν μκ° λ³΅μ‘λλ O(n)μ΄λ©°, μμ ν λλ κ°μ λΉμ©μΌλ‘ λ°μ
F(key) -> Hashcode -> index -> valueκ²μνκ³ μ νλ ν€κ°μ λ°μμ ν΄μ¬ν¨μλ‘ λλ €μ λ°νλ°μ hashcodeλ₯Ό μ΄μ©ν΄μ λ°°μ΄μ indexλ₯Ό μ΄μ©ν΄μ λ°μ΄ν°μ μλ£μ μ κ·Όνλ λ°©λ² key κ°μ μ«μ, λ¬Έμμ΄, νμΌ λ±μ ν΄λΉνλ€
ν΄μ¬ ν μ΄λΈμ hashcode % sizeλ‘ λλμ΄ μΈλ±μ€λ‘ μ¬μ©νλ€
λ€μ΄μ¬λλ§λ€ linkedListλ‘ μ μ₯νκ³ μ°Ύλλ€
μΆ©λμ λ°λΌμ λΆλ₯(Collision)
O(1) -> O(N)κΉμ§ 볡μ‘λκ° λμ΄λλ€
체μΈλ² : κ°μ ν΄μ κ°μ κ°λ μμλ₯Ό μ°κ²° 리μ€νΈλ‘ κ΄λ¦¬
μ€ν μ£Όμλ² : λΉ λ²ν·μ μ°Ύμ λκΉμ§ ν΄μλ₯Ό λ°λ³΅
ν΄μμ ν΄μ ν¨μμ λνμ¬
λ§μ½ μΆ©λμ΄ μ ν λ°μνμ§ μλλ€λ©΄ ν΄μ ν¨μλ‘ μΈλ±μ€λ₯Ό μ°Ύλ κ²λ§μΌλ‘ κ²μ, μΆκ°, μμ κ° κ±°μ μλ£ λλ―λ‘ μκ° λ³΅μ‘λλ μ΄λ κ²μ΄λ O(1)μ΄ λλ€ ν΄μ ν μ΄λΈμ ν¬κ² νλ©΄ μΆ©λ λ°μμ μ΅μ ν μ μμ§λ§ λ€λ₯Έ ννΈμΌλ‘ λ©λͺ¨λ¦¬λ₯Ό μΈλ°μμ΄ λ§μ΄ μ°¨μ§νλ€ μ¦, μκ°κ³Ό 곡κ°μ μ μΆ(trade-Off)μ΄λΌλ λ¬Έμ κ° νμ λ°λΌ λ€λλλ€. μΆ©λμ νΌνκΈ° μν΄ ν΄μ ν¨μλ ν΄μ ν μ΄λΈ ν¬κΈ° μ΄νμ μ μλ₯Ό λλλ‘ νμͺ½μΌλ‘ μΉμ°μΉμ§ μκ³ κ³ λ₯΄κ² λ§λ€μ΄μΌ νλ€ κ·Έλμ ν΄μ ν μ΄λΈ ν¬κΈ°λ μμκ° μ’λ€κ³ μλ €μ Έμλ€ ν€ κ°μ΄ μ μκ° μλ κ²½μ° ν΄μ κ°μ ꡬν λλ μ’ λ μ κ²½μ μ¨ λ°©λ²μΌ λͺ¨μν΄μΌ νλ€. μ건λ μ€μ ν€ κ°μ λν΄ λΉνΈ μ°μ°(bitwise operation)μ νλ λ°©λ², λ¬Έμμ΄ ν€ κ°μ λν΄ κ° λ¬Έμ μ½λμ κ³±μ κ³Ό λ§μ μ νλ μλ²μ΄ μλ€
μ€ν μ£Όμλ²μ μν ν΄μ
public class OpenHash<K,V> {
// λ²ν·μ μν
enum Status {OCCUPIED, EMPTY, DELETED}; // {λ°μ΄ν° μ μ₯, λΉμ΄ μμ, μμ λ§μΉ¨}
// λ²ν·
static class Bucket<K,V> {
private K key; // ν€ κ°
private V data; // λ°μ΄ν°
private Status stat; // μν
// μμ±μ
Bucket() {
stat = Status.EMPTY; // λ²ν·μ λΉμ΄ μμ
}
// λͺ¨λ νλμ κ°μ μ€μ ν©λλ€.
void set(K key, V data, Status stat) {
this.key = key; // ν€ κ°
this.data = data; // λ°μ΄ν°
this.stat = stat; // μν
}
// μνλ₯Ό μ€μ ν©λλ€.
void setStat(Status stat) {
this.stat = stat;
}
// ν€ κ°μ λ°νν©λλ€.
K getKey() {
return key;
}
// λ°μ΄ν°λ₯Ό λ°νν©λλ€.
V getValue() {
return data;
}
// ν€μ ν΄μ κ°μ λ°νν©λλ€.
public int hashCode() {
return key.hashCode();
}
}
private int size; // ν΄μ ν
μ΄λΈμ ν¬κΈ°
private Bucket<K,V>[] table; // ν΄μ ν
μ΄λΈ
// μμ±μ
public OpenHash(int size) {
try {
table = new Bucket[size];
for (int i = 0; i < size; i++)
table[i] = new Bucket<K,V>();
this.size = size;
} catch (OutOfMemoryError e) { // ν
μ΄λΈμ μμ±ν μ μμ
this.size = 0;
}
}
// ν΄μ κ°μ ꡬν¨
public int hashValue(Object key) {
return key.hashCode() % size;
}
// μ¬ν΄μκ°μ ꡬν¨
public int rehashValue(int hash) {
return (hash + 1) % size;
}
// ν€ κ° keyλ₯Ό κ°λ λ²ν·μ κ²μ
private Bucket<K,V> searchNode(K key) {
int hash = hashValue(key); // κ²μν λ°μ΄ν°μ ν΄μκ°
Bucket<K,V> p = table[hash]; // μ ν λ²ν·
for (int i = 0; p.stat != Status.EMPTY && i < size; i++) {
if (p.stat == Status.OCCUPIED && p.getKey().equals(key))
return p;
hash = rehashValue(hash); // μ¬ν΄μ
p = table[hash];
}
return null;
}
// ν·κ° keyλ₯Ό κ°λ μμμ κ²μ (λ°μ΄ν°λ₯Ό λ°ν)
public V search(K key) {
Bucket<K,V> p = searchNode(key);
if (p != null)
return p.getValue();
else
return null;
}
// ν€ κ° key, λ°μ΄ν° dataλ₯Ό κ°λ μμμ μΆκ°
public int add(K key, V data) {
if (search(key) != null)
return 1; // μ΄ ν€ κ°μ μ΄λ―Έ λ±λ‘λ¨
int hash = hashValue(key); // μΆκ°ν λ°μ΄ν°μ ν΄μ κ°
Bucket<K,V> p = table[hash]; // μ ν λ²ν·
for (int i = 0; i < size; i++) {
if (p.stat == Status.EMPTY || p.stat == Status.DELETED) {
p.set(key, data, Status.OCCUPIED);
return 0;
}
hash = rehashValue(hash); // μ¬ν΄μ
p = table[hash];
}
return 2; // ν΄μ ν
μ΄λΈμ΄ κ°λ μ°Έ
}
// ν€ κ° keyλ₯Ό κ°λ μμμ μμ
public int remove(K key) {
Bucket<K,V> p = searchNode(key); // μ ν λ²ν·
if (p == null)
return 1; // μ΄ ν€ κ°μ λ±λ‘λμ§ μμ
p.setStat(Status.DELETED);
return 0;
}
// ν΄μ ν
μ΄λΈμ λ€ν
public void dump() {
for (int i = 0; i < size; i++) {
System.out.printf("%02d ", i);
switch (table[i].stat) {
case OCCUPIED :
System.out.printf("%s (%s)\n",
table[i].getKey(), table[i].getValue());
break;
case EMPTY :
System.out.println("-- λ―Έλ±λ‘ --"); break;
case DELETED :
System.out.println("-- μμ λ§μΉ¨ --"); break;
}
}
}
}체μΈλ²
Last updated
Was this helpful?