written by sohyeon, hyemin ๐ก
ํด์
์ ๋ํด ์ดํดํ๊ธฐ ์ํด์ ํด์๋ฒ์ ์ฌ์ฉ๋๋ ์๋ฃ๊ตฌ์กฐ์ธ ํด์ ํ
์ด๋ธ
์ ๋ํด ์ดํดํด์ผ ํ๋ค.
ํด์ ํ
์ด๋ธ
์ ์ฐ๊ด๋ฐฐ์ด ๊ตฌ์กฐ๋ฅผ ์ด์ฉํ์ฌ ํค(key)์ ๊ฒฐ๊ณผ ๊ฐ(value)์ ์ ์ฅํ๋ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
-
์ฐ๊ด๋ฐฐ์ด ๊ตฌ์กฐ(associative array)
ํค(key) 1๊ฐ์ ๊ฐ(value) 1๊ฐ๊ฐ 1:1๋ก ์ฐ๊ด๋์ด ์๋ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
๋ฐ๋ผ์ ํค(key)๋ฅผ ์ด์ฉํ์ฌ ๊ฐ(value)์ ๋์ถํ ์ ์๋ค.
ํค(Key), ํด์ํจ์(Hash Function), ํด์(Hash), ๊ฐ(value), ๋ฒํท(Bucket, Slot)๋ก ์ด๋ฃจ์ด์ ธ ์๋ค.
ํค(key)๋ ํด์ํจ์(hash function)๋ฅผ ํตํด ํด์(hash)๋ก ๋ณ๊ฒฝ์ด ๋๋ฉฐ
ํด์๋ ๊ฐ(value)๊ณผ ๋งค์นญ๋์ด ๋ฒํท์ ์ ์ฅ์ด ๋๋ค.
-
ํค(key)
๊ณ ์ ํ ๊ฐ์ด๋ฉฐ, ํด์ ํจ์์ input์ด ๋๋ค. ๋ค์ํ ๊ธธ์ด์ ๊ฐ์ด ์ ๋ ฅ๋ ์ ์๋ค.
์ด ์ํ๋ก ์ต์ข ๋ฒํท์ ์ ์ฅ์ด ๋๋ฉด ๋ค์ํ ๊ธธ์ด ๋งํผ์ ๋ฒํท๋ฅผ ๊ตฌ์ฑํด ๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์
ํด์ ํจ์๋ก ๊ฐ์ ๋ฐ๊พธ์ด ์ ์ฅ์ด ๋์ด์ผ ๊ณต๊ฐ์ ํจ์จ์ฑ์ ์ถ๊ตฌํ ์ ์๋ค. -
ํด์ํจ์(Hash Function)
ํค๋ฅผ ํด์๋ก ๋ฐ๊ฟ์ฃผ๋ ์ญํ ์ ํ๋ค.
๋ค์ํ ๊ธธ์ด๋ฅผ ๊ฐ์ง๊ณ ์๋ ํค๋ฅผ ์ผ์ ํ ๊ธธ์ด๋ฅผ ๊ฐ์ง๋ ํด์๋ก ๋ณ๊ฒฝํ์ฌ
๋ฒํท๋ฅผ ํจ์จ์ ์ผ๋ก ์ด์ํ ์ ์๋๋ก ๋์์ค๋ค. -
ํด์(Hash)
ํด์ ํจ์์ ๊ฒฐ๊ณผ๋ฌผ์ด๋ฉฐ, ๋ฒํท์์ ๊ฐ๊ณผ ๋งค์นญ๋์ด ์ ์ฅ๋๋ค.
-
๊ฐ(Value)
๋ฒํท์ ์ต์ข ์ ์ผ๋ก ์ ์ฅ๋๋ ๊ฐ์ผ๋ก ํค์ ๋งค์นญ๋์ด ์ ์ฅ, ์ญ์ , ๊ฒ์, ์ ๊ทผ์ด ๊ฐ๋ฅํด์ผ ํ๋ค.
๋ฐฐ์ด์ ํค ๊ฐ์ 13์ผ๋ก ๋๋ ๋๋จธ์ง๋ฅผ ์๋ ํ์ ๊ฐ์ด ๋ํ๋ผ ์ ์๋ค.
์ด๋ ๊ฒ ํ์ ์ ๋ฆฌํ ๊ฐ์ ํด์ ๊ฐ
์ด๋ผ๊ณ ํ๋ค.
ํค ๊ฐ(์๋ ๊ฐ) | 5 | 6 | 14 | 20 | 29 | 34 | 37 | 51 | 69 | 75 |
---|---|---|---|---|---|---|---|---|---|---|
ํด์ ๊ฐ(13์ผ๋ก ๋๋ ๋๋จธ์ง) | 5 | 6 | 1 | 7 | 3 | 8 | 11 | 12 | 4 | 10 |
ํด์ ๊ฐ์ด ์ธ๋ฑ์ค๊ฐ ๋๋๋ก ์๋์ ํค ๊ฐ์ ์ ์ฅํ ๋ฐฐ์ด์ด ํด์ ํ
์ด๋ธ
์ด๋ค.
์๋ก์ด ๊ฐ์ด ์ถ๊ฐ๋๋ ๊ฒฝ์ฐ์๋ ๋์ผํ๊ฒ ํด์๊ฐ์ ๊ตฌํ๊ณ ํด์ํ
์ด๋ธ์ ์ถ๊ฐํ๋ฉด ๋๋ค.
35๋ฅผ ์ถ๊ฐํ๋ค๊ณ ๊ฐ์ ํ๋ฉด, 35%19=9 ์ด๋ฏ๋ก ๋ฐฐ์ด[9]์ ๊ฐ 35๋ฅผ ์ ์ฅํ๋ค.
๊ฐ์ ์ถ๊ฐํ ๋ ๋ฐฐ์ด ์์๋ฅผ ๋ชจ๋ ์ฎ๊ธฐ์ง ์์๋ ๋๋ค๋ ํน์ง์ ๋ณผ ์ ์๋ค.
์๋ก ๋ค๋ฅธ ํค๊ฐ ๊ฐ์ ํด์๊ฐ ๋๋ ๊ฒฝ์ฐ๋ฅผ ํด์ ์ถฉ๋(Hash Collision)
์ด๋ผ๊ณ ํ๋๋ฐ,
ํด์ ์ถฉ๋์ ์ผ์ผํค๋ ํ๋ฅ ์ ์ต๋ํ ์ค์ด๋ ํจ์๋ฅผ ๋ง๋๋ ๊ฒ์ด ์ค์ํ๋ค.
ํด์ ํจ์๋ ๊ฐ๋ฅํ๋ฉด ํด์ ๊ฐ์ด ์น์ฐ์น์ง ์๋๋ก ๊ณ ๋ฅด๊ฒ ๋ถํฌ๋ ๊ฐ์ ๋ง๋ค์ด์ผ ํ๋ค.
์ถฉ๋์ด ๋ฐ์ํ ๊ฒฝ์ฐ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๋์ฒํ ์ ์๋ค.
๊ฐ์ ํด์ ๊ฐ์ ๊ฐ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฌ์ฌ ๋ชจ์์ผ๋ก ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ์ด์ฉํด ์ฐ๊ฒฐํ๋ ๋ฐฉ๋ฒ์ด๋ค.
์คํ ํด์๋ฒ์ด๋ผ๊ณ ๋ ํ๋ค.
๋ฐฐ์ด์ ๊ฐ ๋ฒํท(ํด์ ํ
์ด๋ธ)์ ์ ์ฅํ๋ ๊ฐ์
๊ทธ ์ธ๋ฑ์ค๋ฅผ ํด์ ๊ฐ์ผ๋ก ํ๋ ์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ์ฒซ๋ฒ์งธ ๋
ธ๋์ ๋ํ ์ฐธ์กฐ์ด๋ค.
๋ฐ์ดํฐ๊ฐ ํ๋๋ ์๋ ๋ฒํท์ ๊ฐ์ null์ ๊ฐ๋ฆฌํจ๋ค.
-
์ฅ์
- ํ์ ๋ ์ ์ฅ์(Bucket)์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
- ํด์ ํจ์(Hash Function)์ ์ ํํ๋ ์ค์์ฑ์ด ์๋์ ์ผ๋ก ์ ๋ค.
- ์๋์ ์ผ๋ก ์ ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค. ๋ฏธ๋ฆฌ ๊ณต๊ฐ์ ์ก์ ๋์ ํ์๊ฐ ์๋ค.
-
๋จ์
- ํ Hash์ ์๋ฃ๋ค์ด ๊ณ์ ์ฐ๊ฒฐ๋๋ค๋ฉด(์ ๋ฆผ ํ์) ๊ฒ์ ํจ์จ์ ๋ฎ์ถ ์ ์๋ค.
- ์ธ๋ถ ์ ์ฅ ๊ณต๊ฐ์ ์ฌ์ฉํ๋ค.
- ์ธ๋ถ ์ ์ฅ ๊ณต๊ฐ ์์ ์ ์ถ๊ฐ๋ก ํด์ผ ํ๋ค.
- ์ฒด์ธ๋ฒ์ผ๋ก ๊ตฌํํ ํด๋์ค
// ํด์๋ฅผ ๊ตฌ์ฑํ๋ ๋
ธ๋, ๊ฐ๋ณ ๋ฒํท์ ๋ํ๋
class Node<K,V>{
K key // ํค ๊ฐ
V data // ๋ฐ์ดํฐ
Node<K,V> next; // ๋ค์ ๋
ธ๋์ ๋ํ ์ฐธ์กฐ
// ์์ฑ์
Node(K key, V data, Node<K,V> next) {
this.key = key;
this.data = data;
this.next = next;
}
// ํค ๊ฐ์ ๋ฐํํฉ๋๋ค.
K getKey() {
return key;
}
// ๋ฐ์ดํฐ๋ฅผ ๋ฐํํฉ๋๋ค.
V getValue() {
return data;
}
// ํค์ ํด์๊ฐ์ ๋ฐํํฉ๋๋ค.
public int hashCode() {
return key.hashCode();
}
}
- ๋ฉ์๋
public class ChainHash<K,V> {
private int size; // ํด์ ํ
์ด๋ธ์ ํฌ๊ธฐ
private Node<K,V>[] table; // ํด์ ํ
์ด๋ธ
// ์์ฑ์
public ChainHash(int capacity) {
try {
table = new Node[capacity];
this.size = capacity;
} catch (OutOfMemoryError e) { // ํ
์ด๋ธ์ ์์ฑํ ์ ์์
this.size = 0;
}
}
// ํด์๊ฐ์ ๊ตฌํจ
public int hashValue(Object key) {
return key.hashCode() % size;
}
// ํค ๊ฐ key๋ฅผ ๊ฐ๋ ์์์ ๊ฒ์ (๋ฐ์ดํฐ๋ฅผ ๋ฐํ)
public V search(K key) {
int hash = hashValue(key); // ๊ฒ์ํ ๋ฐ์ดํฐ์ ํด์๊ฐ
Node<K,V> p = table[hash]; // ์ ํ ๋
ธ๋
while (p != null) {
if (p.getKey().equals(key))
return p.getValue(); // ๊ฒ์ ์ฑ๊ณต
p = p.next; // ๋ค์ ๋
ธ๋์ ์ฃผ๋ชฉ
}
return null; // ๊ฒ์ ์คํจ
}
// ํค ๊ฐ key, ๋ฐ์ดํฐ data๋ฅผ ๊ฐ๋ ์์์ ์ถ๊ฐ
public int add(K key, V data) {
int hash = hashValue(key); // ์ถ๊ฐํ ๋ฐ์ดํฐ์ ํด์๊ฐ
Node<K,V> p = table[hash]; // ์ ํ ๋
ธ๋
while (p != null) {
if (p.getKey().equals(key)) // ์ด ํค ๊ฐ์ ์ด๋ฏธ ๋ฑ๋ก๋จ
return 1;
p = p.next; // ๋ค์ ๋
ธ๋์ ์ฃผ๋ชฉ
}
Node<K,V> temp = new Node<K,V>(key, data, table[hash]);
table[hash] = temp; // ๋
ธ๋๋ฅผ ์ฝ์
return 0;
}
// ํค ๊ฐ key๋ฅผ ๊ฐ๋ ์์์ ์ญ์
public int remove(K key) {
int hash = hashValue(key); // ์ญ์ ํ ๋ฐ์ดํฐ์ ํด์ ๊ฐ
Node<K,V> p = table[hash]; // ์ ํ ๋
ธ๋
Node<K,V> pp = null; // ๋ฐ๋ก ์์ ์ ํ ๋
ธ๋
while (p != null) {
if (p.getKey().equals(key)) { // ์ฐพ์ผ๋ฉด
if (pp == null)
table[hash] = p.next;
else
pp.next = p.next;
return 0;
}
pp = p;
p = p.next; // ๋ค์ ๋
ธ๋๋ฅผ ๊ฐ๋ฆฌํด
}
return 1; // ๊ทธ ํค ๊ฐ์ ์์ต๋๋ค.
}
// ํด์ ํ
์ด๋ธ์ ๋คํ
public void dump() {
for (int i = 0; i < size; i++) {
Node<K,V> p = table[i];
System.out.printf("%02d ", i);
while (p != null) {
System.out.printf("โ %s (%s) ", p.getKey(), p.getValue());
p = p.next;
}
System.out.println();
}
}
}
์คํ ์ฃผ์๋ฒ
์ ์ถฉ๋์ด ๋ฐ์ํ์ ๋ ๋ค์ ํด์๋ฅผ ์ํํ์ฌ ๋น์ด ์๋ ๋ฒํท์ ์ฐพ์๋ด๋ ๋ฐฉ๋ฒ์ผ๋ก,
๋ซํ ํด์๋ฒ์ด๋ผ๊ณ ๋ ํฉ๋๋ค.
์ด๋ ๊ฒ ์คํ ์ฃผ์๋ฒ์ ๋น ๋ฒํท์ ๋ง๋ ๋ ๊น์ง ์ฌํด์
๋ฅผ ์ฌ๋ฌ ๋ฒ ๋ฐ๋ณตํ๋ฏ๋ก ์ ํ ํ์ฌ๋ฒ์ด๋ผ๊ณ ๋ ํฉ๋๋ค.
์์ ๊ฐ์ด ์์ ์ฝ์
์ด ์๋ฃ๋ ์ํ์์ ์ธ๋ฑ์ค๊ฐ 5์ธ ๊ฐ์ ์ญ์ ํ๋ ์ํฉ์ผ๋ก ๊ฐ์ ํ์ ๋,
๋จ์ํ๊ฒ ์ธ๋ฑ์ค๊ฐ 5์ธ ๋ฒํท์ ๋ฐ์ดํฐ๋ฅผ ๋น์ฐ๋ ๊ฒ์ด ์๋๋ค.
์๋ํ๋ฉด ๊ฐ์ ํด์ ๊ฐ์ ๊ฐ๋ 18์ ๊ฒ์ํ ๋
'ํด์ ๊ฐ์ด 5์ธ ๋ฐ์ดํฐ๋ ์กด์ฌํ์ง ์๋๋ค'๋ผ๊ณ ์๊ฐํด ๊ฒ์์ ์คํจํ๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋์ ๊ฐ ๋ฒํท์ ์์ฑ ๊ฐ์ ๋ถ์ฌํ๋ค.
- ๋ฐ์ดํฐ ์ ์ฅ ์์ฑ๊ฐ
- ๋น์ด ์์ ์์ฑ๊ฐ
- ์ญ์ ๋ง์นจ ์์ฑ ๊ฐ
๋ฒํท์ ์์ฑ ๊ฐ์ ํ์ฉํ๋ฉด ์์ ๊ฒ์์ ๋๊ฐ์ง ๊ฒฝ์ฐ๋ฅผ ์๋ง๊ฒ ์ํํ ์ ์๋ค. ํน์ ๊ฐ์ ๊ฒ์ํ์ ๋,
-
๋ฒํท ์์ฑ ๊ฐ์ด ๋น์ด ์์ -> ๊ฒ์ ์คํจ
-
๋ฒํท ์์ฑ ๊ฐ์ด ์ญ์ ๋ง์นจ
-> ๋์ผํ ํด์ ๊ฐ์ ๊ฐ์ง ์ํ๋ ๊ฐ์ ์ฐพ์ ๋ ๊น์ง ์ฌํด์ ๋ฐ๋ณต -> ๊ฒ์ ์ฑ๊ณต
-
์ฅ์
- ๋ ๋ค๋ฅธ ์ ์ฅ๊ณต๊ฐ ์์ด ํด์ํ ์ด๋ธ ๋ด์์ ๋ฐ์ดํฐ ์ ์ฅ ๋ฐ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค.
- ๋ ๋ค๋ฅธ ์ ์ฅ๊ณต๊ฐ์์์ ์ถ๊ฐ์ ์ธ ์์ ์ด ์๋ค.
-
๋จ์
- ํด์ ํจ์(Hash Function)์ ์ฑ๋ฅ์ ์ ์ฒด ํด์ํ ์ด๋ธ์ ์ฑ๋ฅ์ด ์ข์ง์ฐ์ง๋๋ค.
- ๋ฐ์ดํฐ์ ๊ธธ์ด๊ฐ ๋์ด๋๋ฉด ๊ทธ์ ํด๋นํ๋ ์ ์ฅ์๋ฅผ ๋ง๋ จํด ๋์ด์ผ ํ๋ค.
// ์คํ ์ฃผ์๋ฒ์ ์ํ ํด์
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;
}
}
}
}
Do it! ์๋ฃ๊ตฌ์กฐ์ ํจ๊ป ๋ฐฐ์ฐ๋ ์๊ณ ๋ฆฌ์ฆ ์ ๋ฌธ, ์๋ฐ ํธ