Skip to content

Latest commit

ย 

History

History
416 lines (316 loc) ยท 12 KB

Hash.md

File metadata and controls

416 lines (316 loc) ยท 12 KB

ํ•ด์‹œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (Hash)

written by sohyeon, hyemin ๐Ÿ’ก


1. ํ•ด์‹œ๋ฒ•

1) ํ•ด์‹œ ํ…Œ์ด๋ธ”

ํ•ด์‹œ์— ๋Œ€ํ•ด ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ•ด์‹œ๋ฒ•์— ์‚ฌ์šฉ๋˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ธ ํ•ด์‹œ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•ด ์ดํ•ดํ•ด์•ผ ํ•œ๋‹ค.

ํ•ด์‹œ ํ…Œ์ด๋ธ”์€ ์—ฐ๊ด€๋ฐฐ์—ด ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ํ‚ค(key)์— ๊ฒฐ๊ณผ ๊ฐ’(value)์„ ์ €์žฅํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค.

  • ์—ฐ๊ด€๋ฐฐ์—ด ๊ตฌ์กฐ(associative array)

    ํ‚ค(key) 1๊ฐœ์™€ ๊ฐ’(value) 1๊ฐœ๊ฐ€ 1:1๋กœ ์—ฐ๊ด€๋˜์–ด ์žˆ๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค.
    ๋”ฐ๋ผ์„œ ํ‚ค(key)๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ’(value)์„ ๋„์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

2) ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ

ํ‚ค(Key), ํ•ด์‹œํ•จ์ˆ˜(Hash Function), ํ•ด์‹œ(Hash), ๊ฐ’(value), ๋ฒ„ํ‚ท(Bucket, Slot)๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.

ํ‚ค(key)๋Š” ํ•ด์‹œํ•จ์ˆ˜(hash function)๋ฅผ ํ†ตํ•ด ํ•ด์‹œ(hash)๋กœ ๋ณ€๊ฒฝ์ด ๋˜๋ฉฐ
ํ•ด์‹œ๋Š” ๊ฐ’(value)๊ณผ ๋งค์นญ๋˜์–ด ๋ฒ„ํ‚ท์— ์ €์žฅ์ด ๋œ๋‹ค.

  • ํ‚ค(key)

    ๊ณ ์œ ํ•œ ๊ฐ’์ด๋ฉฐ, ํ•ด์‹œ ํ•จ์ˆ˜์˜ input์ด ๋œ๋‹ค. ๋‹ค์–‘ํ•œ ๊ธธ์ด์˜ ๊ฐ’์ด ์ž…๋ ฅ๋  ์ˆ˜ ์žˆ๋‹ค.
    ์ด ์ƒํƒœ๋กœ ์ตœ์ข… ๋ฒ„ํ‚ท์— ์ €์žฅ์ด ๋˜๋ฉด ๋‹ค์–‘ํ•œ ๊ธธ์ด ๋งŒํผ์˜ ๋ฒ„ํ‚ท๋ฅผ ๊ตฌ์„ฑํ•ด ๋‘์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—
    ํ•ด์‹œ ํ•จ์ˆ˜๋กœ ๊ฐ’์„ ๋ฐ”๊พธ์–ด ์ €์žฅ์ด ๋˜์–ด์•ผ ๊ณต๊ฐ„์˜ ํšจ์œจ์„ฑ์„ ์ถ”๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํ•ด์‹œํ•จ์ˆ˜(Hash Function)

    ํ‚ค๋ฅผ ํ•ด์‹œ๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.
    ๋‹ค์–‘ํ•œ ๊ธธ์ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ‚ค๋ฅผ ์ผ์ •ํ•œ ๊ธธ์ด๋ฅผ ๊ฐ€์ง€๋Š” ํ•ด์‹œ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ
    ๋ฒ„ํ‚ท๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์šด์˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค.

  • ํ•ด์‹œ(Hash)

    ํ•ด์‹œ ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฌผ์ด๋ฉฐ, ๋ฒ„ํ‚ท์—์„œ ๊ฐ’๊ณผ ๋งค์นญ๋˜์–ด ์ €์žฅ๋œ๋‹ค.

  • ๊ฐ’(Value)

    ๋ฒ„ํ‚ท์— ์ตœ์ข…์ ์œผ๋กœ ์ €์žฅ๋˜๋Š” ๊ฐ’์œผ๋กœ ํ‚ค์™€ ๋งค์นญ๋˜์–ด ์ €์žฅ, ์‚ญ์ œ, ๊ฒ€์ƒ‰, ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.

2) ํ•ด์‹œ ์˜ˆ์‹œ

๋ฐฐ์—ด์˜ ํ‚ค ๊ฐ’์„ 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๋ฅผ ์ €์žฅํ•œ๋‹ค.

๊ฐ’์„ ์ถ”๊ฐ€ํ•  ๋•Œ ๋ฐฐ์—ด ์š”์†Œ๋ฅผ ๋ชจ๋‘ ์˜ฎ๊ธฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ํŠน์ง•์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

2. ํ•ด์‹œ ์ถฉ๋Œ(Hash Collision)

์„œ๋กœ ๋‹ค๋ฅธ ํ‚ค๊ฐ€ ๊ฐ™์€ ํ•ด์‹œ๊ฐ€ ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ํ•ด์‹œ ์ถฉ๋Œ(Hash Collision)์ด๋ผ๊ณ  ํ•˜๋Š”๋ฐ,
ํ•ด์‹œ ์ถฉ๋Œ์„ ์ผ์œผํ‚ค๋Š” ํ™•๋ฅ ์„ ์ตœ๋Œ€ํ•œ ์ค„์ด๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.

ํ•ด์‹œ ํ•จ์ˆ˜๋Š” ๊ฐ€๋Šฅํ•˜๋ฉด ํ•ด์‹œ ๊ฐ’์ด ์น˜์šฐ์น˜์ง€ ์•Š๋„๋ก ๊ณ ๋ฅด๊ฒŒ ๋ถ„ํฌ๋œ ๊ฐ’์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
์ถฉ๋Œ์ด ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

1) ์ฒด์ธ๋ฒ•

๊ฐ™์€ ํ•ด์‹œ ๊ฐ’์„ ๊ฐ–๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์‡ ์‚ฌ์Šฌ ๋ชจ์–‘์œผ๋กœ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ด์šฉํ•ด ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
์˜คํ”ˆ ํ•ด์‹œ๋ฒ•์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค.

๋ฐฐ์—ด์˜ ๊ฐ ๋ฒ„ํ‚ท(ํ•ด์‹œ ํ…Œ์ด๋ธ”)์— ์ €์žฅํ•˜๋Š” ๊ฐ’์€
๊ทธ ์ธ๋ฑ์Šค๋ฅผ ํ•ด์‹œ ๊ฐ’์œผ๋กœ ํ•˜๋Š” ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์˜ ์ฒซ๋ฒˆ์งธ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ฐธ์กฐ์ด๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ํ•˜๋‚˜๋„ ์—†๋Š” ๋ฒ„ํ‚ท์˜ ๊ฐ’์€ null์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

- ์žฅ๋‹จ์ 

  • ์žฅ์ 

    • ํ•œ์ •๋œ ์ €์žฅ์†Œ(Bucket)์„ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ํ•ด์‹œ ํ•จ์ˆ˜(Hash Function)์„ ์„ ํƒํ•˜๋Š” ์ค‘์š”์„ฑ์ด ์ƒ๋Œ€์ ์œผ๋กœ ์ ๋‹ค.
    • ์ƒ๋Œ€์ ์œผ๋กœ ์ ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๋ฏธ๋ฆฌ ๊ณต๊ฐ„์„ ์žก์•„ ๋†“์„ ํ•„์š”๊ฐ€ ์—†๋‹ค.
  • ๋‹จ์ 

    • ํ•œ Hash์— ์ž๋ฃŒ๋“ค์ด ๊ณ„์† ์—ฐ๊ฒฐ๋œ๋‹ค๋ฉด(์ ๋ฆผ ํ˜„์ƒ) ๊ฒ€์ƒ‰ ํšจ์œจ์„ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ๋‹ค.
    • ์™ธ๋ถ€ ์ €์žฅ ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•œ๋‹ค.
    • ์™ธ๋ถ€ ์ €์žฅ ๊ณต๊ฐ„ ์ž‘์—…์„ ์ถ”๊ฐ€๋กœ ํ•ด์•ผ ํ•œ๋‹ค.

2) ์ฒด์ธ๋ฒ•์„ ํ™œ์šฉํ•œ ํ•ด์‹œ ๊ตฌํ˜„

  • ์ฒด์ธ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค
// ํ•ด์‹œ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋…ธ๋“œ, ๊ฐœ๋ณ„ ๋ฒ„ํ‚ท์„ ๋‚˜ํƒ€๋ƒ„
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();
		}
	}
}

3) ์˜คํ”ˆ ์ฃผ์†Œ๋ฒ•

์˜คํ”ˆ ์ฃผ์†Œ๋ฒ•์€ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋‹ค์‹œ ํ•ด์‹œ๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ ๋น„์–ด ์žˆ๋Š” ๋ฒ„ํ‚ท์„ ์ฐพ์•„๋‚ด๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ,
๋‹ซํžŒ ํ•ด์‹œ๋ฒ•์ด๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค.

- ์š”์†Œ ์‚ฝ์ž…

์ด๋ ‡๊ฒŒ ์˜คํ”ˆ ์ฃผ์†Œ๋ฒ•์€ ๋นˆ ๋ฒ„ํ‚ท์„ ๋งŒ๋‚  ๋•Œ ๊นŒ์ง€ ์žฌํ•ด์‹œ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜๋ณตํ•˜๋ฏ€๋กœ ์„ ํ˜• ํƒ์‚ฌ๋ฒ•์ด๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค.

- ์š”์†Œ ์‚ญ์ œ

์œ„์™€ ๊ฐ™์ด ์š”์†Œ ์‚ฝ์ž…์ด ์™„๋ฃŒ๋œ ์ƒํƒœ์—์„œ ์ธ๋ฑ์Šค๊ฐ€ 5์ธ ๊ฐ’์„ ์‚ญ์ œํ•˜๋Š” ์ƒํ™ฉ์œผ๋กœ ๊ฐ€์ •ํ–ˆ์„ ๋•Œ,
๋‹จ์ˆœํ•˜๊ฒŒ ์ธ๋ฑ์Šค๊ฐ€ 5์ธ ๋ฒ„ํ‚ท์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋น„์šฐ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค.

์™œ๋ƒํ•˜๋ฉด ๊ฐ™์€ ํ•ด์‹œ ๊ฐ’์„ ๊ฐ–๋Š” 18์„ ๊ฒ€์ƒ‰ํ•  ๋•Œ
'ํ•ด์‹œ ๊ฐ’์ด 5์ธ ๋ฐ์ดํ„ฐ๋Š” ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค'๋ผ๊ณ  ์ƒ๊ฐํ•ด ๊ฒ€์ƒ‰์— ์‹คํŒจํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ทธ๋ž˜์„œ ๊ฐ ๋ฒ„ํ‚ท์— ์†์„ฑ ๊ฐ’์„ ๋ถ€์—ฌํ•œ๋‹ค.

  • ๋ฐ์ดํ„ฐ ์ €์žฅ ์†์„ฑ๊ฐ’
  • ๋น„์–ด ์žˆ์Œ ์†์„ฑ๊ฐ’
  • ์‚ญ์ œ ๋งˆ์นจ ์†์„ฑ ๊ฐ’

- ์š”์†Œ ๊ฒ€์ƒ‰

๋ฒ„ํ‚ท์˜ ์†์„ฑ ๊ฐ’์„ ํ™œ์šฉํ•˜๋ฉด ์š”์†Œ ๊ฒ€์ƒ‰์˜ ๋‘๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ์•Œ๋งž๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ํŠน์ • ๊ฐ’์„ ๊ฒ€์ƒ‰ํ–ˆ์„ ๋•Œ,

  1. ๋ฒ„ํ‚ท ์†์„ฑ ๊ฐ’์ด ๋น„์–ด ์žˆ์Œ -> ๊ฒ€์ƒ‰ ์‹คํŒจ

  2. ๋ฒ„ํ‚ท ์†์„ฑ ๊ฐ’์ด ์‚ญ์ œ ๋งˆ์นจ
    -> ๋™์ผํ•œ ํ•ด์‹œ ๊ฐ’์„ ๊ฐ€์ง„ ์›ํ•˜๋Š” ๊ฐ’์„ ์ฐพ์„ ๋•Œ ๊นŒ์ง€ ์žฌํ•ด์‹œ ๋ฐ˜๋ณต -> ๊ฒ€์ƒ‰ ์„ฑ๊ณต

- ์žฅ๋‹จ์ 

  • ์žฅ์ 

    • ๋˜ ๋‹ค๋ฅธ ์ €์žฅ๊ณต๊ฐ„ ์—†์ด ํ•ด์‹œํ…Œ์ด๋ธ” ๋‚ด์—์„œ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฐ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ๋˜ ๋‹ค๋ฅธ ์ €์žฅ๊ณต๊ฐ„์—์„œ์˜ ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์ด ์—†๋‹ค.
  • ๋‹จ์ 

    • ํ•ด์‹œ ํ•จ์ˆ˜(Hash Function)์˜ ์„ฑ๋Šฅ์— ์ „์ฒด ํ•ด์‹œํ…Œ์ด๋ธ”์˜ ์„ฑ๋Šฅ์ด ์ขŒ์ง€์šฐ์ง€๋œ๋‹ค.
    • ๋ฐ์ดํ„ฐ์˜ ๊ธธ์ด๊ฐ€ ๋Š˜์–ด๋‚˜๋ฉด ๊ทธ์— ํ•ด๋‹นํ•˜๋Š” ์ €์žฅ์†Œ๋ฅผ ๋งˆ๋ จํ•ด ๋‘์–ด์•ผ ํ•œ๋‹ค.

4) ์˜คํ”ˆ ์ฃผ์†Œ๋ฒ•์„ ํ™œ์šฉํ•œ ํ•ด์‹œ ๊ตฌํ˜„

// ์˜คํ”ˆ ์ฃผ์†Œ๋ฒ•์— ์˜ํ•œ ํ•ด์‹œ

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;
			}
		}
	}
}

Reference & Additional Resources

Do it! ์ž๋ฃŒ๊ตฌ์กฐ์™€ ํ•จ๊ป˜ ๋ฐฐ์šฐ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž…๋ฌธ, ์ž๋ฐ” ํŽธ