μ΄μ§ νμ νΈλ¦¬ (Binary Search Tree)
μ΄μ§ νμ μκ³ λ¦¬μ¦
- μ λ ¬λ λ°μ΄ν°λ‘ λ 리μ€νΈ(λ°°μ΄μ΄λ μ°κ²° 리μ€νΈ)κ° μΈμλ‘ λ€μ΄μμ λ, μμ μ€μ μ°Ύκ³ μ νλ λ°μ΄ν°κ° μλμ§ μμ보λ μκ³ λ¦¬μ¦
λμ λ리μ λ΄λΆ ꡬν
- λμ λ리λ <key, item>μ μμΌλ‘ λ μ§ν©
- λ΄λΆμ μΌλ‘ BST, ν΄μ ν μ΄λΈ λ κ°μ§ μλ£ κ΅¬μ‘°λ‘ κ΅¬ν κ°λ₯
- C++μ mapμ BSTμ λ³νμΈ κ· ν μ΄μ§ νΈλ¦¬, κ·Έ μ€μμλ λ λ λΈλ νΈλ¦¬λ₯Ό μ΄μ©ν΄μ ꡬν
- μλ°μμλ HashMapκ³Ό TreeMapμ λͺ¨λ μ μ νλ‘κ·Έλλ¨Έκ° λ΄λΆ ꡬνμ μ νν μ μλλ‘ ν¨
- μλ°λ λ λ λΈλ νΈλ¦¬λ₯Ό μ¬μ©νμ¬ κ΅¬νν¨
μ΄μ§ νμ νΈλ¦¬
- κ²μ ν¨μ¨μ λμ΄κΈ° μν΄ λ§λ μ΄μ§ νΈλ¦¬
- λ Έλμ λ°μ΄ν°λ₯Ό μ§μ μ μ₯νμ§ μλλ€
- λ°μ΄ν°μ λν μ°Έμ‘°λ§ μ μ₯
- λ°μ΄ν°μ μ°Έμ‘°λ₯Ό μ μ₯νκ³ μλ λ Έλλ₯Ό λνλ΄λ ν€κ° μ€μ
- ν€λ§ λΉ λ₯΄κ² κ²μ ν μ μλ€λ©΄ λ°μ΄ν°λ μ°Έμ‘°λ₯Ό μ΄μ©ν΄μ λ°λ‘ μ κ·Ό ν μ μλ€
- μ΄μ§ νμ νΈλ¦¬μ μ μ
- λͺ¨λ ν€λ μ μΌν©λλ€.
- μ΄λ€ λ Έλλ₯Ό νΉμ νμ λ μ΄ λ Έλμ ν€ κ°μ μΌμͺ½ μλΈ νΈλ¦¬μ κ·Έ μ΄λ€ ν€λ³΄λ€ ν½λλ€.
- μ΄λ€ λ Έλλ₯Ό νΉμ νμ λ μ΄ λ Έλμ ν€ κ°μ μ€λ₯Έμͺ½ μλΈ νΈλ¦¬μ κ·Έ μ΄λ€ ν€ κ°λ³΄λ€ μμ΅λλ€.
- (μ¬κ·μ μ μ) λ Έλμ μλΈ νΈλ¦¬λ μ΄μ§ νμ νΈλ¦¬μ λλ€.
μ΄μ§ νμ νΈλ¦¬μ ꡬν
class TreeNode:
def __init__(self, key):
self.__key=key
self.__left=None
self.__right=None
self.__parent=None
def __del__(self):
print('key {} is deleted'.format(self.__key))
@property
def key(self):
return self.__key
@key.setter
def key(self, key):
self.__key=key
@property
def left(self):
return self.__left
@left.setter
def left(self, left):
self.__left=left
@property
def right(self):
return self.__right
@right.setter
def right(self, right):
self.__right=right
@property
def parent(self):
return self.__parent
@parent.setter
def parent(self, p):
self.__parent=p
class BST:
def __init__(self):
self.root=None
def get_root(self):
return self.root
def preorder_traverse(self, cur, func):
if not cur:
return
func(cur)
self.preorder_traverse(cur.left, func)
self.preorder_traverse(cur.right, func)
# keyκ° μ λ ¬λ μνλ‘ μΆλ ₯
def inorder_traverse(self, cur, func):
if not cur:
return
self.inorder_traverse(cur.left, func)
func(cur)
self.inorder_traverse(cur.right, func)
# νΈμ ν¨μ
# curμ μΌμͺ½ μμμ leftλ‘ λ§λ λ€.
def __make_left(self, cur, left):
cur.left=left
if left:
left.parent=cur
# νΈμ ν¨μ
# curμ μ€λ₯Έμͺ½ μμμ rightλ‘ λ§λ λ€.
def __make_right(self, cur, right):
cur.right=right
if right:
right.parent=cur
def insert(self, key):
new_node=TreeNode(key)
cur=self.root
if not cur:
self.root=new_node
return
while True:
parent=cur
if key < cur.key:
cur=cur.left
if not cur:
self.__make_left(parent, new_node)
return
else:
cur=cur.right
if not cur:
self.__make_right(parent, new_node)
return
def search(self, target):
cur=self.root
while cur:
if cur.key==target:
return cur
elif cur.key > target:
cur=cur.left
elif cur.key < target:
cur=cur.right
return cur
def __delete_recursion(self, cur, target):
if not cur:
return None
elif target < cur.key:
new_left=self.__delete_recursion(cur.left, target)
self.__make_left(cur, new_left)
elif target > cur.key:
new_right=self.__delete_recursion(cur.right, target)
self.__make_right(cur, new_right)
else:
if not cur.left and not cur.right:
cur=None
elif not cur.right:
cur=cur.left
elif not cur.left:
cur=cur.right
else:
replace=cur.left
replace=self.max(replace)
cur.key, replace.key=replace.key, cur.key
new_left=self.__delete_recursion(cur.left, replace.key)
self.__make_left(cur, new_left)
return cur
def delete(self, target):
new_root=self.__delete_recursion(self.root, target)
self.root=new_root
def min(self, cur):
while cur.left != None:
cur=cur.left
return cur
def max(self, cur):
while cur.right != None:
cur=cur.right
return cur
def prev(self, cur):
# μΌμͺ½ μμμ΄ μλ€λ©΄
# μΌμͺ½ μμμμ κ°μ₯ ν° λ
Έλ
if cur.left:
return self.max(cur.left)
# λΆλͺ¨ λ
Έλλ₯Ό λ°μμ¨λ€
parent = cur.parent
# νμ¬ λ
Έλκ° λΆλͺ¨ λ
Έλμ μΌμͺ½ μμμ΄λ©΄
while parent and cur==parent.left:
cur=parent
parent=parent.parent
return parent
def next(self, cur):
# μ€λ₯Έμͺ½ μμμ΄ μλ€λ©΄
# μ€λ₯Έμͺ½ μμμμ κ°μ₯ μμ λ
Έλ
if cur.right:
return self.min(cur.right)
# λΆλͺ¨ λ
Έλλ₯Ό λ°μμ¨λ€
parent = cur.parent
# νμ¬ λ
Έλκ° λΆλͺ¨ λ
Έλμ μ€λ₯Έμͺ½ μμμ΄λ©΄
# 루νΈμ λλ¬νκ±°λ
# νμ¬ λ
Έλκ° λΆλͺ¨ λ
Έλμ μΌμͺ½ μμμ΄ λ λκΉμ§
# κ³μ λΆλͺ¨ λ
Έλλ‘ μ΄λ
while parent and cur==parent.right:
cur=parent
parent=parent.parent
return parent
if __name__=="__main__":
print('*'*100)
bst=BST()
bst.insert(6)
bst.insert(3)
bst.insert(2)
bst.insert(4)
bst.insert(5)
bst.insert(8)
bst.insert(10)
bst.insert(9)
bst.insert(11)
f=lambda x: print(x.key, end=' ')
#bst.preorder_traverse(bst.get_root(), f)
bst.inorder_traverse(bst.get_root(), f)
print()
searched_node = bst.search(8)
if searched_node:
print(f'searched key : {searched_node.key}')
prev_node = bst.prev(searched_node)
if prev_node:
print(f'prev key : {prev_node.key}')
else:
print(f'this is the first key of the BST')
next_node = bst.next(searched_node)
if next_node:
print(f'next key : {next_node.key}')
else:
print(f'this is the last key of the BST')
else:
print('there is no such key')
print()
print (f'MIN(bst) : {bst.min(bst.get_root()).key}')
print(f'MAX(bst) : {bst.max(bst.get_root()).key}')
#bst.delete(9)
#bst.delete(8)
bst.delete(6)
#print(bst.delete(15))
bst.preorder_traverse(bst.get_root(), f)
# bst.inorder_traverse(bst.get_root(), f)
print()
print('*'*100)
μ΄μ§ νμ νΈλ¦¬μ λ¨μ
- μ λ ¬λ λ°μ΄ν°κ° μ½μ λλ©΄ κ° λ 벨λ§λ€ λ Έλκ° νλμ©λ§ μλ νΈν μ΄μ§ νΈλ¦¬κ° λ¨
- μ°κ²° 리μ€νΈμ κ°μ
- μ½μ , μμ , νμ λͺ¨λ O(n)
=> μ΄λ₯Ό 보μν μ΄μ§ νμ νΈλ¦¬κ° λ λ λΈλ νΈλ¦¬κ° ν¬ν¨λλ κ· ν μ΄μ§ νΈλ¦¬