
- ์ ๋ ฌ๋ ๋ฆฌ์คํธ๋ ์ด๋ป๊ฒ ๊ทธ ์์๋ฅผ ์ ์งํ๋์ง ์ค๋ช
ํ์ค ์ ์๋์?
- ๊ทธ๋ ๋ค๋ฉด, ์ ๋ ฌ๋ ๋ฆฌ์คํธ์์ ํน์ ๋ฒ์๋ฅผ ๊ฒ์ํ๋ ๊ณผ์ ์ ์ค๋ช
ํ์ค ์ ์๋์?
๋ง์ฝ, ์ค๋ช ์ด ํ๋ค๋ค๋ฉด ์ด๋ฒ ๊ธ์ ์ฝ์ผ์๋ฉด ๋์์ด ๋ ๊ฒ๋๋ค.
์ด ๊ธ์์๋ ์ ๋ ฌ๋ ๋ฆฌ์คํธ์์ ๋น ๋ฅธ ๊ฒ์์ ์ํ ์๋ฃ๊ตฌ์กฐ Skip List๋ฅผ ์๊ฐํฉ๋๋ค.
์๋์ ๊ฐ์ ์ ๋ ฌ๋ Linked List๊ฐ ์๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค.

์ ๋ฆฌ์คํธ์์ '10'์ ์ฐพ๋๋ค๊ณ ํ ๋ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ 10์
๋๋ค.
๊ทธ๋ผ ๋น ๋ฅธ ์ด๋์ ํ ์ ์๋ ๊ณ ์๋๋ก(๋ ๋ฒจ)๋ฅผ ์์ ๋ง๋ค์ด ๋ด
์๋ค.

์ด์ '10'์ ์ฐพ์ ๋ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ 5์ ๋๋ค. ํ์ง๋ง ์ ์ฅํ ์ ๋ณด๊ฐ 4๋งํผ ๋์์ต๋๋ค. ์ถ๊ฐ์ ์ธ ๊ณต๊ฐ์ ํ ๋นํจ์ผ๋ก์จ ๋น ๋ฅธ ๊ฒ์์ ์ ๊ณตํ ์ ์์ต๋๋ค.
์ด๋ฌํ ๊ฐ๋ ์ ํ์ฉํ์ฌ, ๋์ ๋ค์ง๊ธฐ(1/2)๋ฅผ ํตํด ๋ ๋ฒจ์ ๋๋ฆด์ง ๊ฒฐ์ ํ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค.

์์ ๊ฐ์ ๊ทธ๋ฆผ์ด ๋์ค๊ฒ ๋ ๊ฑฐ๊ณ , ์ด๋ Skip List๋ผ๊ณ ํ ์ ์์ต๋๋ค.

Skip List์์๋ ์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ ๊ณผ์ ์ผ๋ฌ ๊ฐ์ ์ฐพ๊ฒ ๋ฉ๋๋ค. ์ด๋ ์๊ฐ ๋ณต์ก๋๋ ํ๊ท ์ ์ผ๋ก O(log n)์ด๋ฉฐ ๊ณต๊ฐ๋ณต์ก๋๋ ๋ฌด์์ Skip List์์ ๋์ด๊ฐ log n์ด ๋๊ณ , ๊ฐ ๋ ๋ฒจ์์์ ๋ ธ๋ ์๊ฐ ํ๊ท ์ ์ผ๋ก ์์๋ฐฐ๋ก ์ฆ๊ฐํ๊ธฐ ๋๋ฌธ์ ์ ์ฒด ๊ณต๊ฐ ๋ณต์ก๋๋ O(n log n)์ด ๋ฉ๋๋ค.
์ด์ Skip List์ ์๋ ๋ฐฉ์์ ์ดํด๋ณด์์ผ๋, ๊ตฌํ๋ ์ฝ๋๋ฅผ ๋ณด๋ฉฐ ์ ์ฒด์ ์ธ ๋์์ ํ๋ฆ์ ์ดํด๋ด ๋๋ค.
์ ์ฒด์ ์ธ ์ฝ๋๋ ์ฌ๊ธฐ์ ํ์ธํ ์ ์์ต๋๋ค.
class Node<K extends Comparable<K>, V> {
private int level;
private K key;
private V value;
private Node<K, V> left, right, up, down;
public Node(K key, V value, int level) {
this.key = key;
this.value = value;
this.level = level;
}
/* Getter, Setter... */
}
์ฐ์ ๊ฐ์ ์ ์ฅํ Node๋ฅผ ์์ฑํฉ๋๋ค. Node์๋ ์๊ณผ ๋ค ๋ฟ๋ง ์๋๋ผ ์, ์๋์ ์ฃผ์๋ฅผ ๊ฐ์ง๊ณ ์์ด์ผ ํฉ๋๋ค.

Skip List๋ head์ ์ ์ฐ์ธก์ผ๋ก ํ์์ ํ๋ฉฐ, ์ฐพ๋ ๊ฐ์ด ์ฐ์ธก ๊ฐ๋ณด๋ค ์์ผ๋ฉด ํ๋จ๊ณ ์๋๋ก ๋ด๋ ค ๊ฐ๋๋ค.
private Node<K, V> findNode(K key) {
// head์์ ํ์ ์์
Node<K, V> node = head;
Node<K, V> next;
Node<K, V> down;
K nodeKey;
// ๋ ๋ฒจ ๋ณ ํ์
while (true) {
next = node.getNext();
// ๋ค์ ๋
ธ๋์ ํค ๊ฐ์ด ์ฃผ์ด์ง ํค๋ณด๋ค ํด ๋๊น์ง
while(next != null && lessThanOrEqual(key, next.getKey())) {
node = next;
next = node.getNext();
}
nodeKey = node.getKey();
// ํ์ฌ ๋
ธ๋์ ํค ๊ฐ์ด ์ฃผ์ด์ง ํค์ ๋์ผํ ๊ฒฝ์ฐ ๋ฐ๋ณต๋ฌธ์ ์ข
๋ฃ
if (nodeKey != null && equalTo(key, nodeKey)) {
break;
}
down = node.getDown();
// ์๋ ๋
ธ๋๊ฐ ๋ ์๋ ๊ฒฝ์ฐ ๋
ธ๋๋ฅผ ์๋ ๋
ธ๋๋ก ์
๋ฐ์ดํธ
if (down != null) {
node = down;
} else {
break;
}
}
return node;
}
public void add(K key, V value) {
Node<K, V> node = findNode(key);
if (node.getKey() != null && equalTo(key, node.getKey())) {
node.setValue(value);
return;
}
Node<K, V> prevNode = node;
int currentLevel = 1;
int headLevel = head.getLevel();
Node<K, V> newNode = new Node<>(key, value, currentLevel);
insertAfter(newNode, prevNode);
while (canBuildNextLevel()) {
// ์ต๋ ๋ ๋ฒจ์ ๋๊ธด ๊ฒฝ์ฐ
if (currentLevel >= head.getLevel()) {
Node<K, V> newHead = new Node<>(null, null, headLevel + 1);
linkVertical(newHead, head);
head = newHead;
headLevel = head.getLevel();
}
// ๋์ธ ๋ ๋ฒจ์ ๋
ธ๋์ ์ฐ๊ฒฐ๋ ๋
ธ๋ ํ์
while (prevNode.getUp() == null) {
prevNode = prevNode.getPrevious();
}
prevNode = prevNode.getUp();
// ๋
ธ๋ ์ฐ๊ฒฐ
Node<K, V> upperNode = new Node<>(key, value, prevNode.getLevel());
insertAfter(prevNode, upperNode);
linkVertical(upperNode, newNode);
newNode = upperNode;
currentLevel++;
}
size++;
}
public V remove(K key) {
Node<K, V> node = findNode(key);
if (!equalTo(key, node.getKey())) {
return null;
}
V deletedValue = node.getValue();
while (node != null) {
Node<K, V> downNode = node.getDown();
node.disconnect();
node = downNode;
}
return deletedValue;
}