written by sohyeon, hyemin ๐ก
์ด์งํธ๋ฆฌ
๊ฐ ๋ค์ ์กฐ๊ฑด์ ๋ง์กฑํ ๋ ์ด์งํ์ํธ๋ฆฌ
๋ผ๊ณ ํ๋ค.
- ์ด๋ค ๋ ธ๋ N์ ๊ธฐ์ค์ผ๋ก ์ผ์ชฝ ์๋ธ ํธ๋ฆฌ ๋ ธ๋์ ๋ชจ๋ ํค ๊ฐ์ ๋ ธ๋ N์ ํค ๊ฐ๋ณด๋ค ์์์ผ ํ๋ค.
- ์ค๋ฅธ์ชฝ ์๋ธ ํธ๋ฆฌ ๋ ธ๋์ ํค ๊ฐ์ ๋ ธ๋N์ ํค ๊ฐ๋ณด๋ค ์ปค์ผ ํ๋ค.
- ๊ฐ์ ํค ๊ฐ์ ๊ฐ๋ ๋ ธ๋๋ ์๋ค.
๊ฐ ๋
ธ๋์ ๊ฐ์ด ์กด์ฌํ ๋, ๋
ธ๋์ ์ผ์ชฝ ์๋ธํธ๋ฆฌ์๋ ๊ทธ ๋
ธ๋์ ๊ฐ๋ณด๋ค ์์ ๊ฐ๋ค์ ์ง๋ ๋
ธ๋๋ค๋ก ์ด๋ฃจ์ด์ ธ์๋ค.
๋
ธ๋์ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์๋ ๊ทธ ๋
ธ๋์ ๊ฐ๊ณผ ๊ฐ๊ฑฐ๋ ํฐ ๊ฐ๋ค์ ์ง๋ ๋
ธ๋๋ค๋ก ์ด๋ฃจ์ด์ ธ์๋ค.
์ข์ฐ ํ์ํธ๋ฆฌ๋ ๊ฐ๊ฐ์ด ๋ค์ ์ด์งํ์ํธ๋ฆฌ์ด๋ค.
์ด์งํ์ํธ๋ฆฌ๋ฅผ ์ค์ ์ํํ๋ฉด
1 -> 4 -> 5 -> 6 -> 7 -> 9 -> 11 -> 12 -> 13 -> 14 -> 15 -> 18
์ค๋ฆ์ฐจ์์ผ๋ก ๋
ธ๋๋ฅผ ์ป์ ์ ์์ผ๋ฉฐ, ๊ตฌ์กฐ๊ฐ ๋จ์ํ๋ค.
์ด์ง๊ฒ์๊ณผ ๋น์ทํ ๋ฐฉ์์ผ๋ก ๊ฒ์์ด ๊ฐ๋ฅํ๋ฉฐ ๋
ธ๋์ ์ฝ์
์ด ์ฝ๋ค๋ ํน์ง์ด ์๋ค.
์ด์งํ์ํธ๋ฆฌ์ ํน์ฑ์ ์ํด
-
์ต์๊ฐ
์ผ์ชฝ ์์ ๋ ธ๋๊ฐ ์์ ๋๊น์ง ์ผ์ชฝ ์์๋ ธ๋๋ฅผ ํ์ ํ์ ๋ ๋์ค๋ ํค ๊ฐ์ด๋ค. -
์ต๋๊ฐ
์ค๋ฅธ์ชฝ ์์ ๋ ธ๋๊ฐ ์์ ๋๊น์ง ์ค๋ฅธ์ชฝ ์์๋ ธ๋๋ฅผ ํ์ ํ์ ๋ ๋์ค๋ ํค ๊ฐ์ด๋ค.
-
Successor
์์์ ๋ฃจํธ๋ ธ๋ x๊ฐ ์กด์ฌํ ๋ x๋ณด๋ค ํฐ ๊ฐ์ผ๋ก ์ด๋ฃจ์ด์ง ์๋ธํธ๋ฆฌ์ ๊ฐ ์ค ๊ฐ์ฅ ์์ ํค ๊ฐ์ ์๋ฏธํ๋ค. -
Predecessor
์์์ ๋ฃจํธ๋ ธ๋ x๊ฐ ์กด์ฌํ ๋ x๋ณด๋ค ์์ ๊ฐ์ผ๋ก ์ด๋ฃจ์ด์ง ์๋ธํธ๋ฆฌ์ ๊ฐ ์ค ๊ฐ์ฅ ํฐ ํค ๊ฐ์ ์๋ฏธํ๋ค.
์ด์งํ์ํธ๋ฆฌ์ ๊ฐ๋ณ ๋ ธ๋๋ฅผ ๋ํ๋ด๋ ๊ฒ, 4๊ฐ์ ํ๋๋ก ๊ตฌ์ฑ ๋๋ค.
- key : ํค ๊ฐ
- data : ๋ฐ์ดํฐ
- left : ์ผ์ชฝ ์์ ๋ ธ๋์ ๋ํ ์ฐธ์กฐ(์ผ์ชฝ ํฌ์ธํฐ)
- right : ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋์ ๋ํ ์ฐธ์กฐ(์ค๋ฅธ์ชฝ ํฌ์ธํฐ)
class Node<K,V>{
K key;
V data;
Node<K, V> left;
Node<K, V> right;
// ์์ฑ์
Node(K key, V data, Node<K,V> left, Node<K,V> right){
this.key = key;
this.data = data;
this.left = left;
this.right = right;
}
// ํค ๊ฐ์ ๋ฐํ
K getKey(){
return key;
}
// ๋ฐ์ดํฐ๋ฅผ ๋ฐํ
V getValue(){
return data;
}
// ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅ
void print(){
System.out.println(data);
}
}
private Node<K,V> root;
private Comparator<? Super K> comparator = null; // ๋น๊ต์
2๊ฐ์ ํ๋๋ก ๊ตฌ์ฑ๋๋ค.
- root : ๋ฃจํธ์ ๋ํ ์ฐธ์กฐ๋ฅผ ๋ณด์กด, ์ ์งํ๋ ํ๋
- comparator : ํค ๊ฐ์ ๋์ ๊ด๊ณ๋ฅผ ๋น๊ตํ๋ ๋น๊ต์
// ์์ฑ์
public BinTree(){
root = null; // ๋
ธ๋๊ฐ ํ๋๋ ์๋ ์ด์งํ์ํธ๋ฆฌ๋ฅผ ์์ฑ
}
//์์ฑ์
public BinTree(Comparator<? super K> c){
this();
comparator = c;
}
BinTree()
์์ฑ์๋ก ์์ฑํ ์ด์งํ์ํธ๋ฆฌ์์๋ ๋
ธ๋ ํค ๊ฐ์ ๋์๊ด๊ณ๋ฅผ ํ๋จํ ๋ ์์ฐ ์์์ ๋ฐ๋ผ ์ํ๋๋ค.
๋ฐ๋ผ์ ํค๋ฅผ ๋ํ๋ด๋ K์ ํ์ด Comparable ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ์๋ Integerํด๋์ค๋ Stringํด๋์ค๋ฑ์ ์๋ง๋ค.
๋ค๋ฅธ ์์ฑ์ BinTree(Comparator<? super K>c)
์ ๋ฌ๋ฆฌ ๋น๊ต์๋ฅผ ์ค์ ํ์ง ์์ผ๋ฏ๋ก ํ๋ comparator์ ๊ฐ์ ๋์ด ๋๋ค.
BinTree(Comparator<? super K> c)
์์ฑ์๋ ์ธ์๋ก ๋น๊ต์๋ฅผ ์ ๋ฌ๋ฐ๋ ์์ฑ์์ด๋ค.
์ด ์์ฑ์๋ก ์์ฑํ ์ด์งํ์ํธ๋ฆฌ๋ ๋
ธ๋์ ๋์ ๊ด๊ณ๋ฅผ ํ๋จํ ๋ ์ ๋ฌ๋ฐ์ ๋น๊ต์์ ์ํด ์ํ๋๋ค.
-
this()์ ์ํด ์ธ์๋ฅผ ์ ๋ฌ๋ฐ์ง ์๋ ์์ฑ์ BinTree()๋ฅผ ํธ์ถ. root๊ฐ null์ธ ์ด์ง๊ฒ์ํธ๋ฆฌ๋ฅผ ์์ฑํ๋ค.
-
ํ๋ comparator์ ์ ๋ฌ๋ฐ์ c๋ฅผ ์ค์ ํ๋ค.
2๊ฐ์ ํค ๊ฐ์ ๋น๊ตํ๋ ๋ฉ์๋์ด๋ค. ๊ฒ์, ์ฝ์ , ์ญ์ ์ ๊ฐ ๋ฉ์๋์์ ํธ์ถํ๋ ๋น๊ณต๊ฐ ๋ฉ์๋์ด๋ค.
private int comp(K key1, K key2){
return (comparator == null) ? ((Comparable<K>)key1).compareTo(key2) : comparator.compare(key1, key2);
}
- key1 > key2๋ฉด ์์
- key1 < key2๋ฉด ์์
- key1 == key2๋ฉด 0
์ด์ง ๊ฒ์ํธ๋ฆฌ์ ๋น๊ต์ comparator๊ฐ ์ค์ ๋์ด ์๋์ง์ ๋ฐ๋ผ 2๊ฐ์ ํค๊ฐ์ ๋น๊ตํ๋ ๋ฐฉ๋ฒ์ด ๋ค๋ฅด๋ค.
((Comparable<K>)key1).compareTo(key2)
key1์ Comparable ์ธํฐํ์ด์คํ์ผ๋ก ํ๋ณํํ๊ณ compareTo๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ key2์ ๋น๊ต
comparator.compare(key1, key2)
์ค์ ๋ ๋น๊ต์ comparator์ compare๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋ ํค๊ฐ key1, key2๋ฅผ ๋น๊ต
์ด์งํ์ํธ๋ฆฌ์์ ์ํ๋ ๊ฐ์ ์ฐพ์ผ๋ ค๋ฉด
๋ฃจํธ๋ถํฐ ์์ํด ํ์ฌ ์ ํํ ๋
ธ๋์ ํค ๊ฐ๊ณผ ๋น๊ตํ๋ฉด์ ์ผ์ชฝ, ์ค๋ฅธ์ชฝ์ผ๋ก ๊ฒ์์ ์งํํ๋ค.
- ๋ฃจํธ๋ถํฐ ์ ํํ์ฌ ๊ฒ์์ ์งํํ๋ค. ์ฌ๊ธฐ์ ์ ํํ๋ ๋ ธ๋๋ฅผ p๋ผ๊ณ ํ๋ค.
- p๊ฐ Null์ด๋ฉด ๊ฒ์์ ์คํจํ๋ค.
- ๊ฒ์ํ๋ ๊ฐ key์ ์ ํํ ๋
ธ๋ p์ ํค ๊ฐ์ ๋น๊ตํ์ฌ
- ๊ฐ์ด ๊ฐ์ผ๋ฉด ๊ฒ์์ ์ฑ๊ณต(๊ฒ์ ์ข ๋ฅ)ํ๋ค.
- key๊ฐ ์์ผ๋ฉด ์ ํํ ๋ ธ๋์ ์ผ์ชฝ ์์ ๋ ธ๋๋ฅผ ๋์ ํ๋ค(์ผ์ชฝ์ผ๋ก ๊ฒ์ ์งํ).
- key๊ฐ ํฌ๋ฉด ์ ํํ ๋ ธ๋์ ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋๋ฅผ ๋์ ํ๋ค(์ค๋ฅธ์ชฝ์ผ๋ก ๊ฒ์ ์งํ).
- 2๋ฒ ๊ณผ์ ์ผ๋ก ๋๋์๊ฐ๋ค.
public V search(K key){
Node<K,V> p = root;
while(true){
if(p==null)
return null;
int cond = comp(key, p.getKey());
if(cond==0)
return p.getValue(); // ๊ฒ์ ์ฑ๊ณต
else if(cond<0)
p = p.left;
else
p = p.right;
}
}
ํค ๊ฐ์ด key์ธ ๋ ธ๋๋ฅผ ๊ฒ์ํ๊ณ ๊ฒ์์ ์ฑ๊ณตํ๋ฉด ๊ทธ ๋ ธ๋์ ๋ฐ์ดํฐ์ ๋ํ ์ฐธ์กฐ๋ฅผ ๋ฐํํ๋ค.
์ด์งํ์ํธ๋ฆฌ์ ์กฐ๊ฑด์ ์ ์งํ๋๋ก ๋
ธ๋๋ฅผ ์ฝ์
ํ๋ค.
์ฝ์
ํ ๋
ธ๋์ ํค์ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๋ ๋
ธ๋๊ฐ ์๋ค๋ฉด ๋
ธ๋๋ฅผ ์ฝ์
ํด์๋ ์๋๋ค.
- ๋ฃจํธ๋ฅผ ์ ํํ๋ค. ์ฌ๊ธฐ์ ์ ํํ๋ ๋ ธ๋๋ฅผ node๋ก ํ๋ค.
- ์ฝ์
ํ ํค key์ ์ ํ๋
ธ๋ node์ ํค ๊ฐ์ ๋น๊ตํ๋ค. ๊ฐ์ด ๊ฐ๋ค๋ฉด ์ฝ์
์ ์คํจํ๋ค(์ข
๋ฃ).
- ๊ฐ์ด ๊ฐ์ง ์์ ๊ฒฝ์ฐ key๊ฐ์ด ์ฝ์
ํ ๊ฐ๋ณด๋ค ์์ผ๋ฉด,
์ผ์ชฝ ์์ ๋ ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ๋ ธ๋๋ฅผ ์ฝ์ (์ข ๋ฃ)
์ผ์ชฝ ์์ ๋ ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ์ ํํ ๋ ธ๋๋ฅผ ์ผ์ชฝ ์์ ๋ ธ๋๋ก ์ฎ๊ธด๋ค. - key๊ฐ์ด ์ฝ์
ํ ๊ฐ๋ณด๋ค ํฌ๋ฉด,
์ค๋ฅธ์ชฝ ์์ ๋ ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ๋ ธ๋๋ฅผ ์ฝ์ (์ข ๋ฃ)
์ค๋ฅธ์ชฝ ์์ ๋ ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ์ ํํ ๋ ธ๋๋ฅผ ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋๋ก ์ฎ๊ธด๋ค.
- ๊ฐ์ด ๊ฐ์ง ์์ ๊ฒฝ์ฐ key๊ฐ์ด ์ฝ์
ํ ๊ฐ๋ณด๋ค ์์ผ๋ฉด,
- 2๋ก ๋๋์ ๊ฐ๋ค.
private void addNode(Node<K,V> node, K key, V data){
int cond = comp(key, node.getKey());
if(cond == 0)
return;
else if(cond<0){
if(node.left == null)
node.left = new Node<K,V>(key, data, null, null);
else
addNode(node.left, key, data);
} else{
if(node.right == null)
node.right = new Node<K,V>(key, data, null, null);
else
addNode(node.right, key, data);
}
}
public void add(K key, V data){
if(root == null)
root = new Node<K,V>(kdy, data, null, null);
else
addNode(root, key, data);
}
๋ ธ๋๋ฅผ ์ญ์ ํ ๋๋ ์ธ๊ฐ์ง ์๋ก ๋ค๋ฅธ ์ํฉ์ ์๋ง์ ์ฒ๋ฆฌ๋ฅผ ํด์ผํ๋ค.
- ์ญ์ ํ ๋ ธ๋๊ฐ ๋ถ๋ชจ ๋ ธ๋์ ์ผ์ชฝ ์์์ด๋ฉด ๋ถ๋ชจ์ ์ผ์ชฝ ํฌ์ธํฐ๋ฅผ null๋ก ํ๋ค.
- ์ญ์ ํ ๋ ธ๋๊ฐ ๋ถ๋ชจ ๋ ธ๋์ ์ค๋ฅธ์ชฝ ์์์ด๋ฉด ๋ถ๋ชจ์ ์ค๋ฅธ์ชฝ ํฌ์ธํฐ๋ฅผ null๋ก ํ๋ค.
- ์ญ์ ๋์ ๋ ธ๋๊ฐ ๋ถ๋ชจ ๋ ธ๋์ ์ผ์ชฝ ์์์ด๋ฉด ๋ถ๋ชจ์ ์ผ์ชฝ ํฌ์ธํฐ๊ฐ ์ญ์ ๋์ ๋ ธ๋์ ์์์ ๊ฐ๋ฆฌํค๋๋ก ํ๋ค.
- ์ญ์ ๋์ ๋ ธ๋๊ฐ ๋ถ๋ชจ ๋ ธ๋์ ์ค๋ฅธ์ชฝ ์์์ด๋ฉด ๋ถ๋ชจ์ ์ค๋ฅธ์ชฝ ํฌ์ธํฐ๊ฐ ์ญ์ ๋์ ๋ ธ๋์ ์์์ ๊ฐ๋ฆฌํค๋๋ก ํ๋ค.
-
์ญ์ ํ ๋ ธ๋์ ์ผ์ชฝ ์๋ธ ํธ๋ฆฌ์์ ํค ๊ฐ์ด ๊ฐ์ฅ ํฐ ๋ ธ๋๋ฅผ ๊ฒ์ํ๋ค.
(Predecessor, ์์๋ ธ๋๊ฐ ํ๋์ด๊ฑฐ๋ ํ๋๋ ์กด์ฌํ์ง ์๋ ํน์ง์ด ์๋ค.) -
๊ฒ์ํ ๋ ธ๋๋ฅผ ์ญ์ ์์น๋ก ์ฎ๊ธด๋ค.
-
์ฎ๊ธด ๋ ธ๋๋ฅผ ์ญ์ ํ๋ค.
- ์ฎ๊ธด ๋ ธ๋์ ์์์ด ์์ผ๋ฉด, ์์ ๋ ธ๋๊ฐ ์๋ ๋ ธ๋์ ์ญ์ ์์์ ๋ฐ๋ผ ๋ ธ๋๋ฅผ ์ญ์
- ์ฎ๊ธด ๋ ธ๋์ ์์์ด ์์ผ๋ฉด, ์์ ๋ ธ๋๊ฐ 1๊ฐ ์๋ ๋ ธ๋์ ์ญ์ ์์์ ๋ฐ๋ผ ๋ ธ๋๋ฅผ ์ญ์
public boolean remov(K key){
Node<K,V> p = root;
Node<K,V> parent = null;
boolean isLeftChild = true;
// ์ญ์ ํ ํค ๊ฒ์
while(true){
if(p == null)
return false;
int cond = comp(key, p.getKey()); // key์ ๋
ธ๋p์ ํค ๊ฐ์ ๋น๊ต
if(cond == 0) // ๊ฐ์ผ๋ฉด ๊ฒ์ ์ฑ๊ณต
break;
else{
parent = p;
if(cond < 0){ // key์ชฝ์ด ์์ผ๋ฉด ์ผ์ชฝ ์์์ผ๋ก ๋ด๋ ค๊ฐ๊ณ ์ผ์ชฝ์๋ธํธ๋ฆฌ์์ ๊ฒ์
ifLeftChild = true;
p = p.left;
}
else{ // key์ชฝ์ด ํฌ๋ฉด ์ค๋ฅธ์ชฝ ์์์ผ๋ก ๋ด๋ ค๊ฐ๊ณ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์์ ๊ฒ์
isLeftChild = false;
p = p.right;
}
}
}
/*
์์๋
ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ, ์์๋
ธ๋๊ฐ 1๊ฐ์ธ ๊ฒฝ์ฐ์ ๊ณผ์ ์ํ
์ญ์ ๋
ธ๋์ ์ผ์ชฝ ์์์ด ์์ผ๋ฉด ์ผ์ชฝ ํฌ์ธํฐ๊ฐ null,
์ค๋ฅธ์ชฝ ์์์ด ์์ผ๋ฉด ์ค๋ฅธ์ชฝ ํฌ์ธํฐ๊ฐ null์ด ๋๋ ๋ฐฉ๋ฒ ์ด์ฉ
*/
if(p.left == null){ // p์ ์ผ์ชฝ ์์์ด ์์
if(p == root)
root = p.right;
else if(isLeftChild)
parent.left = p.right;
else
parent.right = p.right;
}
else if(p.right == null){ // p์ ์ค๋ฅธ์ชฝ ์์์ด ์์
if(p == root)
root = p.left;
else if(isLeftChild)
parent.left = p.left;
else
parent.right = p.left;
}
// ์์ ๋
ธ๋๊ฐ 2๊ฐ์ธ ๋
ธ๋๋ฅผ ์ญ์ ํ๋ ๊ฒฝ์ฐ ์ํ
else{
parent = p;
Node<K,V> left = p.left; // ์๋ธ ํธ๋ฆฌ ๊ฐ์ด๋ฐ ๊ฐ์ฅ ํฐ ๋
ธ๋
isLeftChild = true;
while(left.right != null){ // ๊ฐ์ฅ ํฐ ๋
ธ๋ left๋ฅผ ๊ฒ์
parent = left;
left = left.right;
isLeftChild = false;
}
p.key = left.key; // left์ ํค ๊ฐ์ p๋ก ์ฎ๊น
p.data = left.data; // left์ ๋ฐ์ดํฐ๋ฅผ p๋ก ์ฎ๊น
if(isLeftChild)
parent.left = left.left; // left๋ฅผ ์ญ์
else
parent.right = left.left; // left๋ฅผ ์ญ์
}
return true;
}