ํฐ์คํ ๋ฆฌ ๋ทฐ
์ด์ง ํ์ ํธ๋ฆฌ (Binary Search Trees)
yeahajeong 2020. 6. 27. 14:28์ด์ง ํ์ ํธ๋ฆฌ๋ ์ด์ง ํธ๋ฆฌ์ ์ผ์ข ์ผ๋ก ๋ชจ๋ ๋ ธ๋์ ๋ํด์ ์ผ์ชฝ ์๋ธํธ๋ฆฌ์ ์๋ ๋ฐ์ดํฐ๋ ๋ชจ๋ ํ์ฌ ๋ ธ๋์ ๊ฐ๋ณด๋ค ์๊ณ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์ ์๋ ๋ฐ์ดํฐ๋ ๋ชจ๋ ํ์ฌ ๋ ธ๋์ ๊ฐ๋ณด๋ค ํฐ ์ฑ์ง์ ๋ง์กฑํ๋ ์ด์งํธ๋ฆฌ์ด๋ค. ๋จ ์ค๋ณต๋๋ ๋ฐ์ดํฐ๋ ์๋๊ฒ์ผ๋ก ๊ฐ์ ํ๋ค.
์ด์ง ํ์ ํธ๋ฆฌ๋ ๋ฐ์ดํฐ ๊ฒ์์ ํ๋๋ฐ ์ ์ฉํ๊ฒ ์ด์ฉ๋๋ค. ์ด๋ฌํ ํ์๋ฒ์ ์ด์งํ์๊ณผ ๋น์ทํด๋ณด์ธ๋ค,
์ ๋ ฌ๋ ๋ฐฐ์ด์ ์ด์ฉํ ์ด์ง ํ์๊ณผ ๋น๊ต
์ด์ง ํ์ ํธ๋ฆฌ๋ฅผ ์ด์ฉํ์ ๋๋ ๋ฐฐ์ด์ ์ด์ฉํ๋ ๊ฒ ๋ณด๋ค ๋ฐ์ดํฐ์ ์ถ๊ฐ, ์ญ์ ๊ฐ ์ฉ์ดํ๋ค. ํ์ง๋ง ๊ณต๊ฐ์ ๋ง์ด ์ฐจ์งํ๋ค๋ ๋จ์ ์ด ์๋ค. ๋ ํญ์ O(logN)์ ๋ณต์ก๋๋ฅผ ๊ฐ๊ณ ์์ง ์๋๋ค.
์ด์ง ํ์ ํธ๋ฆฌ์ ์ถ์์ ์๋ฃ๊ตฌ์กฐ
๋ฐ์ดํฐ ํํ - ๊ฐ ๋ ธ๋๋ (key, value)์ ์์ผ๋ก ํํํ๋ค. ํค๋ฅผ ์ด์ฉํด์ ๊ฒ์๊ฐ๋ฅ, ๋ณด๋ค ๋ณต์กํ ๋ฐ์ดํฐ ๋ ์ฝ๋๋ก ํ์ฅ ๊ฐ๋ฅํ๋ค. ์ซ์๊ฐ key, ์ด๋ฆ์ด value
์ฐ์ฐ์ ์ ์
- insert(key, data) - ํธ๋ฆฌ์ ์ฃผ์ด์ง ๋ฐ์ดํฐ ์์๋ฅผ ์ถ๊ฐ
- remove(key) - ํน์ ์์๋ฅผ ํธ๋ฆฌ๋ก ๋ถํฐ ์ญ์
- lookup(key) - ํน์ ์์๋ฅผ ๊ฒ์
- inorder() - ํค์ ์์๋๋ก ๋ฐ์ดํฐ ์์๋ฅผ ๋์ด
- min(), max() - ์ต์ ํค, ์ต๋ ํค๋ฅผ ๊ฐ์ง๋ ์์๋ฅผ ๊ฐ๊ฐ ํ์
์ด์ง ํ์ ํธ๋ฆฌ์ ์์ ์ฝ์
์ฝ๋ ๊ตฌํ - ์ด๊ธฐํ
class Node:
# ์ด๊ธฐํ
def __init__(self, key, data):
self.key = key
self.data = data
self.left = None
self.right = None
class BinSearchTree:
# ์ ๋ฒ์๋ ์ธ์๋ฅผ ์ฃผ์๋๋ฐ ์ด๋ฒ์๋ none์ผ๋ก ์ด๊ธฐํ
def __init__(self):
self.root = None
์ฝ๋ ๊ตฌํ - inorder traversal
class Node:
# ์ด๋ฒ์๋ ๋
ธ๋๋ค์ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค์ด์ ๋ฆฌํดํ๋ค.
def inorder(self):
traversal = []
if self.left:
traversal += self.left.inorder()
traversal.append(self)
if self.right:
traversal += self.right.inorder()
return traversal
class BinSearchTree:
def inorder(self):
if self.root:
return self.root.inorder()
else:
return []
์ฝ๋ ๊ตฌํ - min(), max()
# ๋
ธ๋ ํด๋์ค
class Node:
def min(self):
if self.left:
return self.left.min()
else:
return self
def max(self):
if self.right:
return self.right.max()
else:
return self
# ์ด์ง ํ์ ํธ๋ฆฌ ํด๋์ค
class BinSearchTree:
def min(self):
# ๋ฃจํธ ๋
ธ๋๊ฐ ์กด์ฌํ๋ฉด
if self.root:
return self.root.min()
else:
return None
def max(self):
if self.root:
return self.root.max()
else:
return None
์ฝ๋ ๊ตฌํ - lookup()
- ์ ๋ ฅ์ธ์ - ์ฐพ์ผ๋ ค๋ ๋์ ํค
- ๋ฆฌํด - ์ฐพ์ ๋ ธ๋์ ๊ทธ๊ฒ์ ๋ถ๋ชจ ๋ ธ๋(์ญ์ ์ ์ด์ฉ๋จ) ๊ฐ๊ฐ ์์ผ๋ฉด None์ผ๋ก
# ๋
ธ๋ ํด๋์ค
class Node:
# parent ์ธ์๊ฐ ์ฃผ์ด์ง์ง์์ผ๋ฉด None์ผ๋ก ์๊ฐํ๋ผ๋ ๋ง
def lookup(self, key, parent=None):
# ์ง๊ธ ๋ฐฉ๋ฌธ๋ ๋
ธ๋(self.key)๋ณด๋ค ํ์ํ๋ ค๋ ํค๊ฐ ์์ผ๋ฉด ์ผ์ชฝ์ผ๋ก ๊ฐ์ผํจ
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
# ์ด์ง ํ์ ํธ๋ฆฌ ํด๋์ค
class BinSearchTree:
def lookup(self, key):
if self.root:
return self.root.lookup(key)
else:
return None, None
์ฝ๋ ๊ตฌํ - insert()
- ์ ๋ ฅ ์ธ์ - ํค, ๋ฐ์ดํฐ ์์
- ๋ฆฌํด - ์์
class Node:
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:
print("์ค๋ณต๋ ๋
ธ๋๊ฐ ์กด์ฌ")
return True
class BinSearchTree:
# ๋
ธ๋ ์ฝ์
def insert(self, key, data):
# ์กด์ฌํ๋ ํธ๋ฆฌ๋ผ๋ฉด
if self.root:
self.root.insert(key,data)
# ํธ๋ฆฌ๊ฐ ์กด์ฌํ์ง์๋ค๋ฉด ํด๋น ๋
ธ๋๋ฅผ ๋ฃจํธ์ ๋ฃ๋๋ค.
else:
self.root = Node(key, data)
์ด์ง ํ์ ํธ๋ฆฌ์์ ์์ ์ญ์
- ํค(key)๋ฅผ ์ด์ฉํด์ ๋ ธ๋๋ฅผ ์ฐพ๋๋ค. ๋ง์ฝ ํด๋น ํค์ ๋ ธ๋๊ฐ ์์ผ๋ฉด ์ญ์ ํ ๊ฒ์ด ์์, ๋ ธ๋๊ฐ ์์ผ๋ฉด ์ฐพ์ ๋ ธ๋์ ๋ถ๋ชจ ๋ ธ๋๋ ์๊ณ ์์ด์ผํ๋ค.
- ์ฐพ์ ๋ ธ๋๋ฅผ ์ ๊ฑฐํ๊ณ ๋ ์ด์ง ํ์ ํธ๋ฆฌ ์ฑ์ง์ ๋ง์กฑํ๋๋ก ํธ๋ฆฌ์ ๊ตฌ์กฐ๋ฅผ ์ ๋ฆฌํ๋ค (๋ถ๋ชจ๋ ธ๋๋ฅผ ์์์ผํ๋ ์ด์ )
์์ ์ญ์ ์ ์ธํฐํ์ด์ค ์ค๊ณ
- ์ ๋ ฅ - ํค(key)
- ์ถ๋ ฅ - ์ญ์ ํ ๊ฒฝ์ฐ True, ํด๋น ํค์ ๋ ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ False
์ด์ง ํ์ ํธ๋ฆฌ ๊ตฌ์กฐ์ ์ ์ง
์ญ์ ๋๋ ๋ ธ๋๊ฐ
- ๋ง๋จ(leaf)๋ ธ๋์ธ ๊ฒฝ์ฐ -> ๊ทธ๋ฅ ๊ทธ ๋ ธ๋๋ฅผ ์์ ๋ฉด ๋จ ๋ถ๋ชจ ๋ ธ๋์ ๋งํฌ ์กฐ์ (์ข? ์ฐ?)
- ์์์ ํ๋ ๊ฐ์ง๊ณ ์๋ ๊ฒฝ์ฐ -> ์ญ์ ๋๋ ๋ ธ๋ ์๋ฆฌ์ ๊ทธ ์์์ ๋์ ๋ฐฐ์นํ๋ค. ์์์ด ์ผ์ชฝ์ธ์ง ์ค๋ฅธ์ชฝ์ธ์ง, ๋ถ๋ชจ ๋ ธ๋์ ๋งํฌ๋ฅผ ์กฐ์ (์ข? ์ฐ?)
- ์์์ ๋ ๊ฐ์ง๊ณ ์๋ ๊ฒฝ์ฐ -> ์ญ์ ๋๋ ๋ ธ๋๋ณด๋ค ๋ฐ๋ก ๋ค์ (ํฐ) ํค๋ฅผ ๊ฐ์ง๋ ๋ ธ๋๋ฅผ ์ฐพ์ ๊ทธ ๋ ธ๋๋ฅผ ์ญ์ ๋๋ ๋ ธ๋ ์๋ฆฌ์ ๋์ ๋ฐฐ์นํ๊ณ ์ด ๋ ธ๋๋ฅผ ๋์ ์ญ์ ํ๋ค.
์์ ์ญ์ ์ ๊ฒฝ์ฐ 1 - ์ญ์ ํ๋ ค๋ ๋ ธ๋๊ฐ ๋ง๋จ(leaf)๋ ธ๋์ผ ๋
์์ ์ญ์ ์ ๊ฒฝ์ฐ 2 - ์์์ด ํ๋์ธ ๋ ธ๋์ ์ญ์
์์ ์ญ์ ์ ๊ฒฝ์ฐ3 - ์์์ด ๋์ธ ๋ ธ๋์ ์ญ์
์๊ฐ์ ๋ง์ด ํด๋ด์ผํ๋ ๊ฒฝ์ฐ๋ค. ์์ ๋ก ์๊ฐ์ ํด๋ณด์.
๋ ธ๋ 5๋ฅผ ์ญ์ ํ๋ ๊ฒฝ์ฐ
๋ ธ๋ 8์ ์ญ์ ํ๋ ๊ฒฝ์ฐ
class Node:
# ์์์ ์ธ์ด๋ณด์
def countChildren(self):
count = 0
if self.left:
count += 1
if self.right:
count += 1
return count
class BinSearchTree:
# ๋
ธ๋ ์ญ์
def remove(self, key):
# ์ญ์ ํ๋ ค๋ ๋
ธ๋์ p๋ฅผ ๊ฒ์
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
if parent.right == node:
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
์ด๋ป๊ฒ ํ๊ธดํ์ง๋ง ๋๋ฌด ์ด๋ ต๋ค,, ๋ง์ง๋ง์ successor๊ฐ parent์ ์ผ์ชฝ ์์์ธ์ง ์ค๋ฅธ์ชฝ ์์์ธ์ง ํ๋จํ๋ ๋ถ๋ถ์ด ์ ์ดํด๊ฐ ๊ฐ์ง ์๋๋ค. ๊ทธ๋ฆผ ๊ทธ๋ ค์ ๋์๊ฐ๋๊ฑธ ํ์ธํด๋ณด๋ ํด๊ฒฐ๋๋ค. ๋๋ฌด ๋ณต์กํ๊ณ ํท๊ฐ๋ฆฌ๋๊ตฌ๋ง
์ด์งํธ๋ฆฌ๊ฐ ํจ์จ์ ์ด์ง ๋ชปํ ๊ฒฝ์ฐ
์์๋๋ก ์ฝ์ ํ๋ ๊ฒฝ์ฐ์ ํจ์จ์ ์ด์ง ๋ชปํ๋ค. -> ํ์ชฝ์ผ๋ก ์น์ฐ์น ๋ชจ์
๋ณด๋ค ๋์ ์ฑ๋ฅ์ ๋ณด์ด๋ ์ด์ง ํ์ ํธ๋ฆฌ๋ค (์ฐธ๊ณ )
๋์ด์ ๊ท ํ์ ์ ์งํจ์ผ๋ก์จ O(logN)์ ํ์ ๋ณต์ก๋๋ฅผ ๋ณด์ฅํ๋ค. ์ฝ์ , ์ญ์ ์ฐ์ฐ์ด ๋ณด๋ค ๋ณต์กํจ
AVL tree - https://ko.wikipedia.org/wiki/AVL_ํธ๋ฆฌ
Red black tree - https://ko.wikipedia.org/wiki/๋ ๋-๋ธ๋_ํธ๋ฆฌ
'(๊ตฌ)์๋ฃ๊ตฌ์กฐ&์๊ณ ๋ฆฌ์ฆ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ํ๋ก๊ทธ๋๋จธ์ค][Python] ๋ชจ์๊ณ ์ฌ (0) | 2020.06.30 |
---|---|
ํ (Heaps) (0) | 2020.06.29 |
์ด์งํธ๋ฆฌ์ ์ํ (Traversal) - ๋์ด ์ฐ์ ์ํ (BFT) (0) | 2020.06.26 |
์ด์งํธ๋ฆฌ์ ์ํ (Traversal) - ๊น์ด ์ฐ์ ์ํ (DFT) (0) | 2020.06.25 |
์ด์งํธ๋ฆฌ (Binary Trees) (0) | 2020.06.25 |
- Total
- Today
- Yesterday
- ์๋ฃ๊ตฌ์กฐ
- Java
- ์๊ณ ๋ฆฌ์ฆ
- ์๋ฐ
- ์จ๋ฆฌ์์ค
- ๊ฒ์๋ฌผ์กฐํ
- ๊ฐ๋ฐํ๊ฒฝ๊ตฌ์ถ
- typeAliases
- java ํ๊ฒฝ๋ณ์
- ๊ฒ์ํ ์กฐํ
- ๊ฒ์ํ๋ง๋ค๊ธฐ
- ๊ฒ์ํ ์ญ์
- ์คํ๋ง๋ถํธ ์๋์์ฑ
- ๋ถํธ ์๋์์ฑ
- mysql์ค์น
- ์ดํด๋ฆฝ์ค ํ๊ธ ์ธ์ฝ๋ฉ
- ์ ์ฒด๊ฒ์๋ฌผ ์กฐํ
- ์ดํด๋ฆฝ์ค ์ค์น
- ๊ฒ์๋ฌผ ์ญ์
- tomcat์ค์น
- Algorithm
- ๊ฐ๋ฐ
- java jdk ์ค์น
- ๋ณ๋ช ์ฒ๋ฆฌ
์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |