[Data Structures] Binary Search Trees
Binary Search Tree
์ฉ์ด ์ค๋ช
์ ๋ ฌ๋ ์ด์งํธ๋ฆฌ. ๋น ๋ฅธ ์กฐํ, ์ฝ์ ๋ฐ ์ ๊ฑฐ ์์ ์ ์ฉ์ดํ๊ฒ ํ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ.
** binary search tree ์ฑ๋ฆฝ ์กฐ๊ฑด**
left child์ ๊ฐ์ parent๋ณด๋ค ์์์ผ ํ๋ค. right child์ ๊ฐ์ parent๋ณด๋ค ์ปค์ผ ํ๋ค. subtree๋ก ๋ดค์ ๋๋ ์ ๋ ์กฐ๊ฑด์ ๋ง์กฑํด์ผ ํ๋ค.
array vs Binary Search Tree
Search
์์ ์ด๋ฏธ์ง์ ์๋ binary search tree์ ๋ฐฐ์ด [6, 8, 9, 10, 11, 12, 14] ์์ ๊ฐ์ ์ฐพ๋๋ค๊ณ ๊ฐ์ ํด๋ณด์.
-
array ์ฐ์ ๋ฐฐ์ด์์ ๊ฐ์ ์ฐพ์ ๋๋
contains(:)
๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ O(n)์ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค. (ํ๋์ฉ ํ์ธํด๋ด์ผ ํ๋๊น) -
binary search tree ํ์ง๋ง binary search tree๋ผ๋ฉด? ์์ ์ ์ด๋ ์ฑ๋ฆฝ ์กฐ๊ฑด์ ๋ง์กฑํ๋ค๋ ๊ฐ์ ํ์ ํธ๋ฆฌ๋ฅผ ํ์ํด์ ๊ฐ์ ์ฐพ๊ธฐ ๋๋ฌธ์ ํธ๋ฆฌ์ ๋ถ๊ธฐ์ ์์ ์ ํํ๋ ์๊ฐ๋ง๋ค ๊ฒ์ํด์ผ ํ๋ ๊ณต๊ฐ์ ์ ๋ฐ์ผ๋ก ์ค์ผ ์ ์๋ค. ๊ทธ๋์ O(log n)์ด๋ผ๋ ์๊ฐ ๋ณต์ก๋๊ฐ ๋์จ๋ค.
Insertion
[6, 8, 9, 10, 11, 12, 14] ์ 1์ ์ถ๊ฐํ๋ค๊ณ ์๊ฐํด๋ณด์.
-
array ๋ฐฐ์ด์ ๊ฐ์ฅ ์์ ๊ฐ์ด ์ถ๊ฐ๋๋ค๋ฉด ๊ธฐ์กด ๋ฐฐ์ด ์์๋ค์ด ํ์นธ์ฉ ๋ค๋ก ๋ฐ๋ฆฌ๊ฒ ๋๋ฏ๋ก ๋ฐฐ์ด์ insertion ์๊ฐ ๋ณต์ก๋๋ O(n)์ด ๋๋ค.
-
binary search tree binary search tree๋ search์ ๋์ผํ๊ฒ ํธ๋ฆฌ์ ๋ถ๊ธฐ์ ์์ ํ ๋ฒ ์ ํ ํ ๋๋ง๋ค ๊ฒ์ ๊ณต๊ฐ์ด ์ ๋ฐ์ผ๋ก ์ค์ด๋๋ฏ๋ก O(log n).
Removal
-
array [6, 8, 9, 10, 11, 12, 14]์์ 9๋ฅผ ์ ๊ฑฐํ๋ค๊ณ ์๊ฐํด๋ณด์. ์ค๊ฐ ๊ฐ์ ์ง์ฐ๋ฏ๋ก ๋ค์ ์๋ ๊ฐ๋ค์ด ํ์นธ์ฉ ์์ผ๋ก ๋น๊ฒจ์ง๋ค. (O(n)).
-
binary search tree Insertion, Search์ ๋์ผํ๊ฒ O(log n).
Binary Search Tree ๊ตฌํํด๋ณด๊ธฐ
์์์ ์์ฑํด๋ BinaryNode๋ฅผ ํ์ฉํด์ Binary Search Tree๋ฅผ ๊ตฌํํ๋ค.
struct BinarySearchTree<Element: Comparable> {
private(set) var root: BinaryNode<Element>?
}
Insert
๊ฐ์ ์ถ๊ฐํ ๋ ์ ์ํด์ผ ํ ์ ์ right child๋ ๋ ํฐ ๊ฐ, left child๋ ๋ ์์ ๊ฐ ์ด๋ผ๋ ๋ถ๋ถ์ด๋ค.
private func insert(from node: BinaryNode<Element>?, value: Element) -> BinaryNode<Element> {
// terminating recursion
guard let node = node else {
return BinaryNode(value: value)
}
// ๋ค์ด๊ฐ ๊ฐ์ ๋ฐ๋ผ left๋ก ๊ฐ์ผ ํ๋์ง right๋ก ๊ฐ์ผ ํ๋์ง ์ฒดํฌ
if value < node.value {
node.leftChild = insert(from: node.leftChild, value: value)
} else {
node.rightChild = insert(from: node.rightChild, value: value)
}
return node
}
Find
func contains(_ value: Element) -> Bool {
guard let root = root else {
return false
}
var found = false
root.traverseInOrder {
if $0 == value {
found = true
}
}
return found
}
in-order traversal์ด O(n)์ด๋ฏ๋ก contains ๋ํ O(n)
func contains(_ value: Element) -> Bool {
// ์์ ๋
ธ๋๋ root๋ถํฐ ์์
var current = root
// node๊ฐ nil์ด ์๋ ๊ฒฝ์ฐ ๊ณ์ ๋ฐ๋ณต
while let node = current {
// ๋ง์ฝ node ๊ฐ์ด ์ฐพ๋ ๊ฐ์ด๋ผ๋ฉด true
if node.value == value {
return true
}
// current๋ณด๋ค value๊ฐ ์์ผ๋ฉด left, ํฌ๋ฉด right๋ก ์ด๋ํด์ ์ฐพ์
if value < node.value {
current = node.leftChild
} else {
current = node.rightChild
}
}
return false
}
์ด๋ ๊ฒ ์ฐพ์ผ๋ฉด O(log n)
Remove
- Leaf Node ์์์ด ์๋ ๊ฐ์ฅ ๋์ ๋ ธ๋์ด๋ฏ๋ก ๊ทธ๋ฅ ์ ๊ฑฐ
- Nodes with one child ์ง์์ผ ํ๋ ๋ ธ๋๊ฐ ์์์ด ํ๋ ์๋ค๋ฉด ๋ ธ๋๋ฅผ ์ง์ฐ๊ณ ์์ ๋ ธ๋๋ฅผ ๊ทธ ์์ ๋ถ๋ชจ(์กฐ๋ถ๋ชจโฆ?)์ ์ฐ๊ฒฐํด์ค๋ค.
- Nodes with two children ์ง์ฐ๊ณ ์ถ์ ๋ ธ๋๊ฐ ์์์ด ์๋ ๊ฒฝ์ฐ๋ ์ง์ฐ๊ธฐ๊ฐ ์ฝ์ง ์๋ค.
๊ทธ๋ฅ ๋ฌด์์ ์ง์ฐ๊ณ ์๋ ์์๋ค์ ์ฐ๊ฒฐํ๊ณ ์ถ์ด๋ binary search tree์ด๋ฏ๋ก ๋ ธ๋์ children์ด ์ธ๊ฐ๊ฐ ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋ผ ์ด๋ป๊ฒ ์ญ์ ๋ฅผ ํด์ผํ ๊น?
๋ ์์์ผ๋ก ๋ ธ๋๋ฅผ ์ ๊ฑฐํ ๋, ์ ๊ฑฐํ ๋ ธ๋๋ฅผ ์ค๋ฅธ์ชฝ ์๋ธ ํธ๋ฆฌ์์ ๊ฐ์ฅ ์์ ๋ ธ๋๋ก ๋ฐ๊พผ๋ค. BST์ ๊ท์น์ ๋ฐ๋ผ, ์์ ๋ ธ๋๋ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์ ๊ฐ์ฅ ์ผ์ชฝ ๋ ธ๋์ด๋ค.
์ด๊ฒ ๋ฌด์จ๋ง์ด๋ ํ๋ฉด, ์ ํธ๋ฆฌ์์ ๋ดค์ ๋ ์ ๊ฑฐํด์ผํ๋ ๋ ธ๋์ธ 25์ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์์ ๊ฐ์ฅ ์์ ๊ฐ์ ๊ฐ์ง ๋ ธ๋, 27์ 25 ์๋ฆฌ์ ๊ฐ๋ค ๋ฃ์ผ๋ผ๋ ์๋ฆฌ๋ค.
์๋ ๊ฒ ํ๋ฉด ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์์ ๊ฐ์ฅ ์์ ๊ฐ์ ๊ฐ์ ธ์๊ธฐ ๋๋ฌธ์ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์ ๋ชจ๋ ๋ ธ๋๊ฐ 27๋ณด๋ค ํด ๊ฒ์ด๊ณ , ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์์ ๊ฐ์ ธ์๊ธฐ ๋๋ฌธ์ ๋น์ฐํ ์ผ์ชฝ ์๋ธํธ๋ฆฌ์ ๋ชจ๋ ๋ ธ๋๋ 27๋ณด๋ค ์์ ๊ฐ์์ ๋ณด์ฅํ ์ ์๋ค. (BST์ ์์ฑ ์กฐ๊ฑด์ด ๊ทธ๋ฌ๋ฏ๋ก..!)
์๊ฑธ ์ฝ๋๋ก ํํํ๋ฉด ์๋์ ๊ฐ๋ค.
private func remove(node: BinaryNode<Element>?, value: Element) -> BinaryNode<Element>? {
guard let node = node else {
return nil
}
// leaf ๋
ธ๋๋ฅผ ์ ๊ฑฐํ๋ ๊ฒฝ์ฐ
if node.leftChild == nil && node.rightChild == nil {
return nil
}
// left child๊ฐ ์๋ ๊ฒฝ์ฐ
if node.leftChild == nil {
return node.rightChild
}
// right child๊ฐ ์๋ ๊ฒฝ์ฐ
if node.rightChild == nil {
return node.leftChild
}
// ์์ชฝ ๋ค ์์์ด ์๋ ๊ฒฝ์ฐ
node.value = node.rightChild!.min.value
node.rightChild = remove(node: node.rightChild, value: node.value)
return node
}
Leave a comment