이진탐색트리 Binary Search Tree
-
이진탐색트리의 개념
- 각 노드의 왼쪽 서브트리에는 현재 노드보다 작은 값을 가진 노드만 있다.
- 각 노드의 오른쪽 서브트리에는 현재 노드보다 큰 값을 가진 노드만 있다.
- 중복 노드가 없다.
- inorder traverse를 한다 (왼쪽 - 루트 - 오른쪽) → 오름차순 정렬 가능
class Node:
def __init__(self,value):
self.value = value
self.left = None
self.right = None
class BinarySearchTree:
def __init__(self):
self.root = None
def setRoot(self,value):
self.root = Node(value)
-
탐색 Search
class BinarySearchTree:
...
def search(self, value):
if (self._search(self.root, value) is False):
return False
else:
return True
def _search(self, currentNode, value):
# 재귀 함수의 base condition (더 이상 노드가 없으면 False 반환 후 종료)
if (currentNode is None):
return False
# 일치하는 값을 발견하면 해당 노드 반환
elif (value == currentNode.value):
return currentNode
# 값이 현재 노드보다 작으면 왼쪽으로 순회 시작 (재귀)
# 중복이 없으므로 <,>
elif (value < currentNode.value):
return self._search(currentNode.left, value)
# 값이 현재 노드보다 크면 오른쪽으로 순회 시작
elif (value > currentNode.value):
return self._search(currentNode.right, value)
시간복잡도 : O(h)
최악의 경우 리프 노드까지 탐색하기 때문에 루트 - 리프 길이인 h만큼 소요될 수 있다.
-
삽입 Insert
class BinarySearchTree:
...
def insert(self, value):
# BST의 root이 null인 경우
if(self.root is None):
self.setRoot(value)
else:
self._insert(self.root, value)
def _insert(self, currentNode, value):
if (value <= currentNode.value):
# 현재 노드에 왼쪽 자식이 있다면
if (currentNode.left):
self._insert(currentNode.left, value)
# 더이상 왼쪽 자식이 없다는 것 = 현재 노드가 리프 노드임을 의미
else:
currentNode.left = Node(value)
elif (value > currentNode.value):
if (currentNode.right):
self._insert(currentNode.right, value)
else:
currentNode.right = Node(value)
-
삭제 Delete
case 1) 삭제할 노드에 자식 노드가 없는 경우
→ 그냥 없애면 된다.
case 2) 삭제할 노드에 자식 노드가 하나 있는 경우
→ 해당 노드를 지우고 해당 노드의 자식노드와 부모 노드를 연결한다.
(삭제할 노드의 자식을 부모노드 자식으로 만든다.)
case 3) 삭제할 노드에 자식 노드가 두개 있는 경우
- predecessor : 삭제할 노드의 왼쪽 서브트리 중 최대값
- successor : 삭제할 노드의 오른쪽 서브트리 중 최소값
→ successor을 삭제할 노드 자리에 복사해놓고 기존 successor 위치의 노드를 삭제 (predecessor로도 가능)
case 3-1) successor의 자식 노드가 하나인 경우
case 3-2) successor의 자식 노드가 없는 경우
case 3-3) successor의 자식 노드가 둘인 경우
- 과정
- 삭제할 노드의 오른쪽 서브트리에서 successor을 찾는다.
- successor을 삭제할 노드 위치에 복사한다.
- successor을 삭제한다.
class BinarySearchTree:
...
def delete(self, value):
if (currentNode is None):
return False
elif value < currentNode.value:
currentNode.left = self._delete(currentNode.left, value)
elif value > currentNode.value:
currentNode.right = self._delete(currentNode.right, value)
# 삭제할 노드를 찾으면 _delete 호출
def _delete(self, currentNode, value):
# currentNode = 삭제할 노드가 자식 노드가 없는 경우 그냥 지움
if (not currentNode.left and not currentNode.right):
currentNode = None
# 삭제할 노드가 자식 노드 하나를 가지고 있는 경우
# -> 자식 노드를 삭제할 노드 위치로 복사하고 자식 노드 삭제
elif (not currentNode.left):
currentNode = currentNode.right
elif (not currentNode.right):
currentNode = currentNode.left
# 삭제할 노드가 자식 노드 두개를 가지고 있는 경우
else:
# 삭제할 노드의 오른쪽 서브 트리에서 가장 작은 수를 대체자로 선정
successor = currentNode.right
while successor:
successor = successor.left
currentNode.value, successor.value = successor.value, currentNode.value
currentNode.left = self._delete(currentNode.left, successor.value)
return currentNode
-
순회 Traverse
class BinarySearchTree:
...
def traverse(self):
return self._traverse(self.root)
def _traverse(self, currentNode):
result = []
if (currentNode.left is not None):
result.extend(self._traverse(currentNode.left))
if (currentNode.right is not None):
result.extend(currentNode.value)
if (currentNode.right is not None):
result.extend(self._traverse(currentNode.right))
return result
References
'프로그래밍 언어 > Python3' 카테고리의 다른 글
Python) CSV 파일 한글 깨짐 현상 해결 (0) | 2021.06.15 |
---|---|
[프로그래머스 코딩 테스트 연습] BFS/DFS 4. 여행경로 (0) | 2021.02.28 |
[프로그래머스 코딩테스트 연습] BFS/DFS 3. 단어변환 (0) | 2021.02.03 |
[프로그래머스 코딩테스트 연습] 스택/큐 2. 기능개발 (0) | 2021.01.27 |
[프로그래머스 코딩테스트 연습] 정렬 3. H-index (0) | 2021.01.27 |