-
이진 검색 트리Computer Science/Data Structure 2021. 9. 24. 16:04
이진 검색 트리의 정의
ㆍ 각 노드는 (키, 값)의 쌍을 저장하며, 서로 다른 노드의 키는 다르다.
ㆍ 왼쪽 서브 트리에 저장된 노드의 키보다는 크다.
ㆍ 오른쪽 서브 트리에 저장된 노드의 키보다는 작다.
이진 검색 트리의 장점
ㆍ 심볼 테이블을 정렬된 순서로 유지할 필요 없다.
ㆍ 새로 삽입되는 노드는 항상 리프 노드에 위치한다.
이진 검색 트리의 단점
ㆍ 균형 트리를 보장하지 않는다.
ㆍ 감색 시 많은 시간이 소요된다.
구현 방법
노드의 구성
class Node<K, V> { K key; V value; Node<K, V> left, right; int N; int aux; Node<K, V> parent; public Node(K key, V value) { this.key = key; this.value = value; this.N = 1; } public int getAux() { return this.aux; } public void setAux(int value) { this.aux = value; } }
ㆍ 노드는 키, 값 그리고 자식에 대한 참조 변수인 left, right를 가지고 있다.
ㆍ 자신과 자식 노드의 개수에 대한 변수인 N이 있다.
ㆍ 노드의 높이를 알려주는 변수인 aux, 부모에 대한 참조 변수인 parent를 가지고 있다.treeSearch() 메서드
protected Node<K, V> treeSearch(K key) { Node<K, V> x = root; while (true) { int cmp = key.compareTo(x.key); if (cmp == 0) return x; else if (cmp < 0) { if (x.left == null) return x; else x = x.left; } else { if (x.right == null) return x; else x = x.right; } } }
ㆍ 특정 키를 입력받아, 그 키를 갖는 노드 또는 순회의 마지막 노드를 반환하는 메서드이다.
ㆍ 연산은 루트부터 시작되며, 입력받은 키보다 작을 경우 왼쪽으로 클 경우 오른쪽으로 이동하며 순회한다.
get() 메서드
public V get(K key) { if (root == null) return null; Node<K, V> x = treeSearch(key); if (key.equals(x.key)) return x.value; else return null; }
ㆍ 특정 키가 트리에 있을 경우 키에 대응하는 값을 반환한다.
ㆍ 키가 없을 경우 null을 반환한다.put() 메서드
public void put(K key, V value) { if (root == null) { root = new Node<K, V>(key, value); return; } Node<K, V> x = treeSearch(key); int cmp = key.compareTo(x.key); if (cmp == 0) x.value = value; else { Node<K, V> newNode = new Node<K, V>(key, value); if (cmp < 0) x.left = newNode; else x.right = newNode; newNode.parent = x; rebalanceInsert(newNode); } }
ㆍ 입력받은 키를 검색 후 있으면 값만 바꿔준다.
ㆍ 없을 경우 새로운 노드를 추가한다.resetSize() 메서드
protected void rebalanceInsert(Node<K, V> x) { resetSize(x.parent, 1); } protected void rebalanceDelete(Node<K, V> p, Node<K, V> delete) { resetSize(p, -1); } private void resetSize(Node<K, V> x, int value) { for (; x != null; x = x.parent) x.N += value; }
ㆍ 입력받은 노드부터 루트 노드까지의 N변수를 1씩 증가시켜주는 메서드이다.
keys() 메서드
public Iterable<K> keys() { if (root == null) return null; ArrayList<K> keyList = new ArrayList<K>(size()); inorder(root, keyList); return keyList; }
ㆍ inorder 순회를 이용하여 트리의 모든 키를 ArrayList에 추가한다.
ㆍ ArrayList를 반환 함으로써 키의 정렬된 리스트를 반환한다.inorder() 메서드
private void inorder(Node<K, V> x, ArrayList<K> keyList) { if (x != null) { inorder(x.left, keyList); keyList.add(x.key); inorder(x.right, keyList); } }
ㆍ 입력받은 노드부터 자식 노드까지의 모든 키값을 inorder 순회하여 ArrayList에 추가한다.
ㆍ ArrayList를 반환 함으로써 정렬된 키를 반환한다.delete() 메서드
public void delete(K key) { if (root == null) return; Node<K, V> y, p; Node<K, V> x = treeSearch(key); if (!key.equals(x.key)) return; if (x == root || isTwoNode(x)) { if (isLeaf(x)) { root = null; return; } else if (!isTwoNode(x)) { root = (x.right == null) ? x.left : x.right; root.parent = null; return; } else { y = min(x.right); x.key = y.key; x.value = y.value; p = y.parent; relink(p, y.right, y == p.left); rebalanceDelete(p, y); } } else { p = x.parent; if (x.right == null) relink(p, x.left, x == p.left); else if (x.left == null) relink(p, x.right, x == p.left); rebalanceDelete(p, x); } }
ㆍ 삭제하고자 하는 키가 없는 경우 그냥 반환한다.
ㆍ 삭제하려는 노드가 루트 노드이며 리프 노드인 경우 노드를 null로 만든다.
ㆍ 그냥 루트 노드인 경우 자식 노드를 루트로 만든다.
ㆍ 자식이 둘인 노드일 경우에는 inorder successor로 대체하며, 기존의 inorder successor 위치의 노드는 삭제한다.
ㆍ 자식 노드의 수가 1 이하이고 루트도 아닐 경우에는 자식 노드를 삭제할 노드의 부모의 자식으로 만든다.relink() 메서드
protected void relink(Node<K, V> parent, Node<K, V> child, boolean makeLeft) { if (child != null) child.parent = parent; if (makeLeft) parent.left = child; else parent.right = child; }
ㆍ 특정 노드의 삭제 연산이 이루어질 경우에 호출되는 메서드이다.
ㆍ 삭제할 노드의 자식이 존재한다면 자식을 삭제할 노드의 부모의 자식으로 만든다.
ㆍ makeLeft가 참이라면 부모의 왼쪽 자식으로, 거짓이라면 오른쪽 자식으로 만든다.
참고 문헌 및 자료
ㆍ R.Sedgewick and K. Wayne, Algorithms (4th Ed.), Addison-Wesley.
ㆍ E. Horowitz, S. Sahni, S. Anderson-Freed, Fundamentals of Data Structures in C, Silicon Press, 2nd Edition.
GitHub - qlsdud0604/algorithm-study: 자료구조 및 알고리즘 공부 기록 공간
:books: 자료구조 및 알고리즘 공부 기록 공간. Contribute to qlsdud0604/algorithm-study development by creating an account on GitHub.
github.com
728x90'Computer Science > Data Structure' 카테고리의 다른 글
AVL 트리 (0) 2021.09.24 연결 리스트를 이용한 순차 검색 (0) 2021.09.24 배열을 이용한 이진 검색 (0) 2021.09.24