티스토리 뷰
이진탐색트리(Binary Search Tree)
이진탐색 트리에서 원소 삭제
1. 키(Key)를 이용해서 노드를 찾는다.
- 해당 키의 노드가 없으면, 삭제할 것도 없다.
- 찾은 노드의 부모 노드도 알고 있어야 한다.
2. 찾은 노드를 제거하고도 이진탐색 트리 성질을 만족하도록 트리의 구조를 정리한다.
인터페이스의 설계
✔ 입력 : 키(Key)
✔ 출력: 삭제한 경우 True, 해당 키의 노드가 없는 경우 False
class BinarySearchTree:
def remove(self, key):
node, parent = self.lookup(key)
if node:
...
return True
else:
return False
이진탐색 트리 구조의 유지
삭제되는 노드가,
1. 말단(leaf) 노드인 경우
2. 자식 노드를 하나 가지고 있는 경우
3. 자식 노드를 둘 가지고 있는 경우
[ 말단(leaf) 노드인 경우 ]
해당 노드를 없애면 된다.
→ 부모 노드의 링크를 조정한다
[ 자식 노드를 하나 가지고 있는 경우 ]
삭제되는 노드 자리에 해당 노드의 자식 노드를 대신 배치한다.
→ 자식노드가 왼쪽에 존재하는지/오른쪽에 존재하는지.
→ 부모 노드의 링크를 조정한다.
[ 자식 노드를 둘 가지고 있는 경우 ]
삭제되는 노드보다 바로 다음 (큰) 키를 가지는 노드를 찾아 그 노드를 삭제되는 노드 자리에 대신 배치하고 해당 노드를 삭제한다.
이진 탐색 트리가 효율적이지 못한 경우
한쪽으로 치우치는 경우 효율적이지 못하다.
보다 나은 성능을 보이는 이진탐색 트리들
높이의 균형을 유지함으로써 O(logn)의 탐색 복잡도를 보장한다.
삽입, 삭제 연산이 보다 복잡해질 수 있다.
- AVL Tree
- Red-black Tree
문1. 이진탐색트리에서 노드의 삭제 연산 구현
class Node:
def __init__(self, key, data):
self.key = key
self.data = data
self.left = None
self.right = None
def insert(self, key, data):
if key < self.key:
if self.left:
self.left.insert(key, data)
else:
self.left = Node(key, data)
elif key > self.key:
if self.right:
self.right.insert(key, data)
else:
self.right = Node(key, data)
else:
raise KeyError('Key %s already exists.' % key)
def lookup(self, key, parent=None):
if key < self.key:
if self.left:
return self.left.lookup(key, self)
else:
return None, None
elif key > self.key:
if self.right:
return self.right.lookup(key, self)
else:
return None, None
else:
return self, parent
def inorder(self):
traversal = []
if self.left:
traversal += self.left.inorder()
traversal.append(self)
if self.right:
traversal += self.right.inorder()
return traversal
def countChildren(self):
count = 0
if self.left:
count += 1
if self.right:
count += 1
return count
class BinSearchTree:
def __init__(self):
self.root = None
def insert(self, key, data):
if self.root:
self.root.insert(key, data)
else:
self.root = Node(key, data)
def lookup(self, key):
if self.root:
return self.root.lookup(key)
else:
return None, None
def remove(self, key):
node, parent = self.lookup(key)
if node:
nChildren = node.countChildren()
# The simplest case of no children
if nChildren == 0:
# 만약 parent 가 있으면
# node 가 왼쪽 자식인지 오른쪽 자식인지 판단하여
# parent.left 또는 parent.right 를 None 으로 하여
# leaf node 였던 자식을 트리에서 끊어내어 없앱니다.
if parent:
if parent.left == node:
parent.left = None
else:
parent.right = None
# 만약 parent 가 없으면 (node 는 root 인 경우)
# self.root 를 None 으로 하여 빈 트리로 만듭니다.
else:
self.root = None
# When the node has only one child
elif nChildren == 1:
# 하나 있는 자식이 왼쪽인지 오른쪽인지를 판단하여
# 그 자식을 어떤 변수가 가리키도록 합니다.
if node.left:
temp = node.left
else:
temp = node.right
# 만약 parent 가 있으면
# node 가 왼쪽 자식인지 오른쪽 자식인지 판단하여
# 위에서 가리킨 자식을 대신 node 의 자리에 넣습니다.
if parent:
if parent.left == node:
parent.left = temp
else:
parent.right = temp
# 만약 parent 가 없으면 (node 는 root 인 경우)
# self.root 에 위에서 가리킨 자식을 대신 넣습니다.
else:
self.root = temp
# When the node has both left and right children
else:
parent = node
successor = node.right
# parent 는 node 를 가리키고 있고,
# successor 는 node 의 오른쪽 자식을 가리키고 있으므로
# successor 로부터 왼쪽 자식의 링크를 반복하여 따라감으로써
# 순환문이 종료할 때 successor 는 바로 다음 키를 가진 노드를,
# 그리고 parent 는 그 노드의 부모 노드를 가리키도록 찾아냅니다.
while successor.left:
parent = successor
successor = successor.left
# 삭제하려는 노드인 node 에 successor 의 key 와 data 를 대입합니다.
node.key = successor.key
node.data = successor.data
# 이제, successor 가 parent 의 왼쪽 자식인지 오른쪽 자식인지를 판단하여
# 그에 따라 parent.left 또는 parent.right 를
# successor 가 가지고 있던 (없을 수도 있지만) 자식을 가리키도록 합니다.
if parent.left == successor:
parent.left = successor.right
else:
parent.right = successor.right
return True
else:
return False
def inorder(self):
if self.root:
return self.root.inorder()
else:
return []
def solution(x):
return 0
'Algorithm > 알고리즘' 카테고리의 다른 글
[프로그래머스 강의] 23강 힙(Heaps)(2) (0) | 2022.09.06 |
---|---|
[프로그래머스 강의] 22강 힙(Heaps)(1) (0) | 2022.08.12 |
[프로그래머스 강의] 20강 이진탐색트리(1) (0) | 2022.06.29 |
[프로그래머스 강의] 19강 이진 트리(Binary Tree) - BFS (0) | 2022.05.23 |
[프로그래머스 강의] 18강 이진 트리(Binary Tree) (0) | 2022.05.17 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 연결리스트활용
- 이진탐색
- 코드업 기초
- CS
- 완전탐색
- 데이터베이스
- 자료구조와알고리즘 23강
- 리스트 복사
- 자바
- 네트워크
- 리스트함축
- 프로그래머스
- https
- It
- SW
- 리스트2
- CS.
- 프로세스 주소공간
- Greedy sort
- 스터디
- 프로그래머스강의
- 운영체제
- CS 스터디
- 알고리즘
- 정렬
- 보험
- 파이썬
- 자료구조
- 이차 리스트
- 리스트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함