์ค์ํํธ๋ก ๊ตฌํํ๋ ์๋ฃ๊ตฌ์กฐ 8: ์ด์ง ํ์ ํธ๋ฆฌ(Binary Search Tree)
์ด์ง ํ์ ํธ๋ฆฌ (BST)
์ด์ง ํ์ ํธ๋ฆฌ๋ ์ด์ง ํธ๋ฆฌ์ ๋ช๊ฐ์ง ์กฐ๊ฑด์ด ๋ ์ถ๊ฐ๋ ํธ๋ฆฌ์ ๋๋ค. ์ด์ง ํ์ ํธ๋ฆฌ๋ ๋ค์ ์กฐ๊ฑด์ ๋ง์กฑํด์ผํฉ๋๋ค.
1) ์ด๋ค ๋ฃจํธ๋ ธ๋(์๋ธํธ๋ฆฌ์ ๋ฃจํธ ํฌํจ)์ ์ผ์ชฝ ์๋ธํธ๋ฆฌ์ ๋ ธ๋๋ค์ด ๊ฐ์ง ๊ฐ์ ๋ฃจํธ ๋ ธ๋๊ฐ ๊ฐ์ง ๊ฐ๋ณด๋ค ์์์ผํฉ๋๋ค.
2) ์ด๋ค ๋ฃจํธ๋ ธ๋์ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์ ๋ ธ๋๋ค์ด ๊ฐ์ง ๊ฐ์ ๋ฃจํธ ๋ ธ๋๊ฐ ๊ฐ์ง ๊ฐ๋ณด๋ค ์ปค์ผํฉ๋๋ค.
3) ๋ ธ๋์ ๊ฐ์ผ๋ก ํธ๋ฆฌ ์ฐ์ฐ์ด ์ด๋ฃจ์ด์ง๊ธฐ ๋๋ฌธ์ ์ค๋ณต๋ ๋ ธ๋ ๊ฐ์ ํ์ฉํ์ง ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ์ด๋ฐ ํธ๋ฆฌ๋ ์ด์ง ํ์ ํธ๋ฆฌ๊ฐ ๋ ์ ์์ต๋๋ค. ๋ฃจํธ ๋ ธ๋์ธ 1๋ณด๋ค ํฐ ๊ฐ์ธ 2๊ฐ ์ผ์ชฝ ์์ ๋ ธ๋์ ์์นํด์๊ณ ์ผ์ชฝ ์์ ๋ ธ๋์ธ 4, 6๋ ๋ชจ๋ ์์ ์ ๋ถ๋ชจ ๋ ธ๋์ ๊ฐ๋ณด๋ค ํฌ๊ธฐ ๋๋ฌธ์ ๋๋ค
๋ฐ๋ฉด์ ์ด๋ฐ ํธ๋ฆฌ๋ ์ด์ง ํ์ ํธ๋ฆฌ๊ฐ ๋ ์ ์์ต๋๋ค. ๋ฃจํธ๋ ธ๋์ธ 4์ ์ผ์ชฝ ์๋ธํธ๋ฆฌ์ ๋ชจ๋ ๋ ธ๋๋ค์ 4๋ณด๋ค ์๊ณ , ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์ ๋ชจ๋ ๋ ธ๋๋ค์ 4๋ณด๋ค ํฝ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ ธ๋ 2์ 6 ์ญ์๋ ์ผ์ชฝ์๋ ์์ ๋ณด๋ค ์์ ๊ฐ, ์ค๋ฅธ์ชฝ์๋ ์์ ๋ณด๋ค ํฐ ๊ฐ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
๋ผ๋ ๋ง๋ค๊ธฐ
TreeNode
import Foundation
final class TreeNode<T: Comparable> {
private(set) var data: T
var leftChild: TreeNode?
var rightChild: TreeNode?
var isLeafNode: Bool {
return self.leftChild == nil && self.rightChild == nil
}
var hasSingleChild: Bool {
return (self.leftChild != nil && self.rightChild == nil)
|| (self.leftChild == nil && self.rightChild != nil)
}
var hasTwoChild: Bool {
return self.leftChild != nil && self.rightChild != nil
}
init(data: T) {
self.data = data
}
func update(data: T) {
self.data = data
}
var asString:String { return treeString(self){("\($0.data)",$0.leftChild,$0.rightChild)} }
}
๋จผ์ ํธ๋ฆฌ์ ์ฌ์ฉ๋ ๋ ธ๋๋ฅผ ๋ง๋ค์ด์ฃผ์์ต๋๋ค. ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๋ณ์, ์ผ์ชฝ ์์ ๋ ธ๋์ ๋ํ ํฌ์ธํฐ, ๊ทธ๋ฆฌ๊ณ ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋์ ๋ํ ํฌ์ธํฐ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ ธ๋์ ์ํ๋ฅผ ์ฒดํฌํ ์ ์๋ ์ธ ๊ฐ์ง ํ๋กํผํฐ๋ฅผ ๋ง๋ค์์ต๋๋ค. ๋ ธ๋์ ์์๋ ธ๋ ์ ๋ฌด์ ๋ฐ๋ผ์ ์์ ๋ ธ๋๊ฐ ์๋ ๋ฆฌํ ๋ ธ๋์ธ์ง, ์์ ๋ ธ๋๊ฐ ํ๋์ธ์ง, ๋ ๊ฐ์ธ์ง ํ์ธํด์ฃผ๊ฒ ๋ฉ๋๋ค. ์ด๋ฐ ํ๋กํผํฐ๊ฐ ์ ํ์ํ์ง๋ ์ ์ํ์ ๋ค์ ์ค๋ช ํ๋๋ก ํ๊ฒ ์ต๋๋ค.
์ถ๊ฐ์ ์ผ๋ก ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์๋ก์ด ๋ฐ์ดํฐ๋ก ์ ๋ฐ์ดํธํ๋ ๋ฉ์๋๋ ๋ง๋ค์ด์ฃผ์๋๋ฐ์, ์ด ๋ฉ์๋ ์ญ์ ์ด๋ป๊ฒ ์ฌ์ฉ๋๋์ง ์ ์ํ์ ์ค๋ช ํ ๊ฒ์!
asString ํ๋กํผํฐ๋ ํธ๋ฆฌ๋ฅผ ์์ฒญ ์์๊ฒ ์ถ๋ ฅํด์ฃผ๋ treeString ๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ฐ ์ด๊ฑด ์คํ ์ค๋ฒํ๋ก์ฐ์์ ์ง์ง ์ ๋ง๋ค์ด์ฃผ์ ๋ถ์ด ๊ณ์ ์ ๊ทธ๋๋ก ์ฌ์ฉํ์ด์!
์ด ์ง๋ฌธ์ ๋ํ ๋ต๋ณ์ ๋ฉ์๋๊ฐ ์ ์๋์ด ์๊ตฌ์,
์ ์ฉํ๋ฉด ์ด๋ ๊ฒ ์์๊ฒ ์ฝ์์ ํธ๋ฆฌ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค!
ํ์(Search) - O(log N)
์ด์ง ํ์ ํธ๋ฆฌ์ ํน์ง์ด ์ด๋ค ๋ ธ๋์ ์ผ์ชฝ ์๋ธํธ๋ฆฌ๋ ํญ์ ์์ ๋ณด๋ค ์์ ๊ฐ๋ค์ด ์๊ณ , ์ค๋ฅธ์ชฝ์๋ ํญ์ ์์ ๋ณด๋ค ํฐ ๊ฐ๋ค์ด ์๋ค๋ ๊ฒ์ด์์ต๋๋ค. ํ์๋ ์ด๋ฅผ ์ด์ฉํด์ ์งํํฉ๋๋ค.
์ด ํธ๋ฆฌ์์ 5๋ฅผ ๊ฐ์ผ๋ก ๊ฐ์ง ๋ ธ๋๋ฅผ ์ฐพ์๊ฐ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น์? ํธ๋ฆฌ์ด๋๊น ์ผ๋จ ๋ฃจํธ๋ ธ๋์์ ์์ํด์ผ๊ฒ ์ฃ ?
๋ฃจํธ ๋ ธ๋์ ๊ฐ์ธ 4์ ์ฐพ๊ณ ์ ํ๋ ๋ ธ๋์ ๊ฐ์ธ 5๋ฅผ ๋น๊ตํด๋ด ์๋ค. ์ฐพ๊ณ ์ ํ๋ ๋ ธ๋์ ๋ ๊ฐ์ด ํฌ๋ค์. ๊ทธ๋ผ ์ด์ง ํ์ ํธ๋ฆฌ์ ๊ท์น๋๋ก ์ผ์ชฝ ์๋ธ ํธ๋ฆฌ๋ ํ์ํ ํ์์์ด ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ๋ก ์ด๋ํฉ์๋ค!
์ด๋ฒ์ ์๋ก์ด ๋ฃจํธ ๋ ธ๋์ ๊ทธ ๊ฐ์ธ 6์ ๋ง๋๊ฒ๋ฉ๋๋ค. 6์ ์ฐพ๊ณ ์ ํ๋ ๋ ธ๋์ ๊ฐ๋ณด๋ค ํฌ๊ธฐ ๋๋ฌธ์ ํ์ฌ ๋ฃจํธ๋ ธ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ๋ ํ์ํ ํ์๊ฐ ์์ต๋๋ค. ์ผ์ชฝ ์๋ธํธ๋ฆฌ๋ก ์ด๋ํ ๊ฒ์!
์ด๋ฒ์๋ ์๋ก์ด ๋ฃจํธ ๋ ธ๋์ ๊ฐ์ด ์ฐพ๊ณ ์ํ๋ ๊ฐ๊ณผ ๊ฐ๋ค์! ๊ทธ๋ผ ์ด ๋ ธ๋์ ์ฐธ์กฐ๊ฐ์ ๊ทธ๋๋ก ๋ฐํํด์ฃผ๋ฉด ์ํ๋ ๋ ธ๋์ ํ์์ ๋ง์น๊ฒ ๋ฉ๋๋ค. ๋ง์ฝ ์ด๋ฒ ๋ ธ๋์ ๊ฐ์ด 5๊ฐ ์๋์๋ค๋ฉด nil์ ๋ง๋๋ฉด์ ํ์์ด ์ข ๋ฃ๋๊ฒ ์ฃ ?
์ ๊ณผ์ ์ ์ฝ๋๋ก ์ ์ผ๋ฉด ์ด๋ ์ต๋๋ค.
private func search(data: T, in node: TreeNode<T>?) -> TreeNode<T>? {
if node == nil || node?.data == data { return node }
return node!.data > data
? search(data: data, in: node?.leftChild)
: search(data: data, in: node?.rightChild)
}
ํ์ฌ ๋ฃจํธ ๋ ธ๋(node)์ ๋ฐ์ดํฐ๊ฐ ์ฐพ๋ ๋ฐ์ดํฐ์ ๊ฐ๋ณด๋ค ํฌ๋ฉด ์ผ์ชฝ ์๋ธํธ๋ฆฌ๋ก ์ฌ๊ทํ๊ณ , ์์ผ๋ฉด ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ๋ก ์ฌ๊ทํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ฌ ๋ฃจํธ๋ ธ๋๊ฐ nil์ด๊ฑฐ๋, ๋ ๋ฐ์ดํฐ๊ฐ ์ผ์นํ๋ฉด ์ฌ๊ท๋ฅผ ์ข ๋ฃํ๊ณ ํ์ฌ ๋ฃจํธ๋ ธ๋๋ฅผ ๊ทธ๋๋ก ๋ฐํํฉ๋๋ค.
ํ์ํ๋ ๊ณผ์ ์์ ํธ๋ฆฌ์ ํ์ชฝ ์๋ธํธ๋ฆฌ์ ํ์์ ๊ณ์ ์๋ตํ๋ฉด์ ์งํํ๊ธฐ ๋๋ฌธ์ ์๊ฐ๋ณต์ก๋๋ ํธ๋ฆฌ์ ๋์ด์ ๋ฐ๋ฅธ ๋ ธ๋๊ฐ์์ธ O(log N)์ผ๋ก ์ ๋ฆฌ๋ฉ๋๋ค.
ํ์ Worst Case - O(N)
ํ์ง๋ง ๋ง์ฝ ์ด์ง ํ์ ํธ๋ฆฌ๊ฐ ๋ค์์ฒ๋ผ ๊ตฌ์ฑ๋์ด ์๋ค๋ฉด ์ด๋จ๊น์?
๊ฐ ์๋ธํธ๋ฆฌ์ ๋ฃจํธ๋ ธ๋์ ์ผ์ชฝ์๋ ์์ ๋ณด๋ค ์์ ๊ฐ๋ค๋ง ์๊ธฐ ๋๋ฌธ์ ์ด์ง ํ์ ํธ๋ฆฌ์ ์กฐ๊ฑด์๋ ์๋ฐฐ๋์ง ์์ง๋ง ํธํฅ ์ด์ง ํธ๋ฆฌ๊ฐ ๋์ด๋ฒ๋ฆฝ๋๋ค. ์ด๋ฐ ์ํฉ์์ ํ์์ ์งํํ๋ฉด ๊ณ์ํด์ ์ผ์ชฝ ์๋ธํธ๋ฆฌ๋ก๋ง ์ด๋ํ๊ฒ ๋๊ณ ์๋ตํ๋ ์๋ธํธ๋ฆฌ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๊ฒฐ๊ตญ ๋ชจ๋ ๋ ธ๋๋ฅผ ๋ค ํ์ธํด๋ O(N)์ ์๊ฐ๋ณต์ก๋๊ฐ ๋ฐ์ํฉ๋๋ค.
์ด๋ฐ ๋ฌธ์ ๋ฅผ ๋ง๊ธฐ ์ํด BBST(Balanced Binary Search Tree)์ธ AVL ํธ๋ฆฌ์ Red-Black ํธ๋ฆฌ๊ฐ ๊ณ ์๋์์ต๋๋ค. ๋์ค์ ๊ธฐํ๊ฐ ๋๋ค๋ฉด ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค! ๊ฒฐ๋ก ์ ์ผ๋ฐ ์ด์ง ํ์ ํธ๋ฆฌ๋ก๋ ์ด๋ฐ ๋ฌธ์ ๋ฅผ ๋ง์ ์ ์์ต๋๋ค..
์ฝ์ (add) - O(log N)
๊ฑฐ์ ๋ชจ๋ ์ด์ง ํธ๋ฆฌ์ ์ฐ์ฐ๋ค์ ํ์์ ์์กดํฉ๋๋ค. ์ฝ์ ์ญ์๋ ์ ์ ํ ์์น์ ์๋ก์ด ๊ฐ์ ๊ฐ์ง ๋ ธ๋๋ฅผ ๋ฃ์ด์ฃผ๊ธฐ ์ํด์ ํ์์ ์งํํด์ผํฉ๋๋ค.
์ด๋ฒ์๋ ์ด๋ ๊ฒ ์๊ธด ํธ๋ฆฌ์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ถ๊ฐํ๋ค๊ณ ํด๋ณด๊ฒ ์ต๋๋ค.
์ด๋ฒ์ ์ถ๊ฐํ ๋ ธ๋์ ๊ฐ์ 4์ ๋๋ค. ๋ฃจํธ ๋ ธ๋์ ๋จผ์ ๊ฐ์ ๋น๊ตํด๋ด ์๋ค. ์ ๋ ธ๋์ ๊ฐ์ด ๋ ์๋ค์. ์ผ์ชฝ ์๋ธํธ๋ฆฌ๋ก ๋ค์ด๊ฐ์๋ค.
์ด๋ฒ์ ์๋ก์ด ๋ ธ๋์ ๊ฐ์ด ์๋ธํธ๋ฆฌ์ ๋ฃจํธ๋ ธ๋ ๋ณด๋ค ๋ ํฐ ๊ฒ์ ํ์ธํ์ต๋๋ค. ๊ทธ๋ผ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ๋ก ๊ฐ์ผ๊ฒ ์ฃ ?
์๋ก์ด ๋ ธ๋์ ๊ฐ์ด ์๋ธํธ๋ฆฌ์ ๋ฃจํธ๋ ธ๋๋ณด๋ค ํฝ๋๋ค. ์ด์ ์ค๋ฅธ์ชฝ์ผ๋ก ์ด๋ํ๋ ค๊ณ ํ๋๋ฐ, ํ์ฌ ๋ฃจํธ ๋ ธ๋๋ ๋ฆฌํ ๋ ธ๋๋ผ์ ์ค๋ฅธ์ชฝ์ ์์ ๋ ธ๋๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ์๋ก์ด ๋ ธ๋๋ฅผ ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋๋ก ๋ง๋ค์ด์ฃผ๋ฉด ์๋ก์ด ๋ ธ๋์ ์ถ๊ฐ๊ฐ ์๋ฃ๋ฉ๋๋ค.
์ด ๊ณผ์ ์์ ๋ณธ ๊ฒ์ฒ๋ผ ์ค์ ๋ก ์๋ก์ด ๋ ธ๋๋ฅผ ํธ๋ฆฌ์ ์ถ๊ฐํ๋ ๊ฒ์ ์์์๊ฐ์ด์ง๋ง ์๋ก์ด ์์น๋ฅผ ํ์ํ๋๋ฐ๊น์ง ํ์ํ๋ ์๊ฐ์ด ์๊ตฌ๋๊ธฐ ๋๋ฌธ์ ์๊ฐ๋ณต์ก๋๋ ํ์์ ์๊ฐ๋ณต์ก๋์ ๋์ผํ O(log N)์ด ๋ฉ๋๋ค.
mutating func add(data: T) {
let node = TreeNode(data: data)
if root == nil {
self.root = node
return
}
self.add(newNode: node, under: root)
}
@discardableResult
private func add(newNode: TreeNode<T>, under parentNode: TreeNode<T>?) -> TreeNode<T>? {
guard newNode.data != parentNode?.data else { return nil }
if parentNode == nil {
return newNode
}
parentNode!.data > newNode.data
? (parentNode?.leftChild = add(newNode: newNode, under: parentNode?.leftChild))
: (parentNode?.rightChild = add(newNode: newNode, under: parentNode?.rightChild))
return parentNode
}
๊ตฌํ์ ํ์๊ณผ ๋์ผํ๊ฒ ์งํ๋์ง๋ง ๋ฆฌํ ๋ ธ๋์ ์์ ๋ ธ๋๋ฅผ ๋ง๋๋ฉด ์๋ก์ด ๋ ธ๋๋ฅผ ์ฝ์ ํด์ฃผ๋ ๋ก์ง์ด ์ถ๊ฐ๋ฉ๋๋ค.
์ญ์ - O(log N)
BST์ ์ต๊ณ ํท๊ฐ๋ฆฌ๋ ํฌ์ธํธ๋ ์ญ์ ์ฐ์ฐ์ด์ฃ ใ ์ญ์ ํ ๋ ธ๋์ ์์ ๋ ธ๋ ๊ฐ์์ ๋ฐ๋ผ์ ์ด ์ธ ๊ฐ์ ๊ฒฝ์ฐ๋ก ๋ก์ง์ด ๋ค๋ฅด๊ฒ ๊ตฌํ๋ฉ๋๋ค.
์ญ์ ์ฐ์ฐ๋ ์ญ์ ํ ๋ ธ๋๋ฅผ ๋จผ์ ์ฐพ์๋ด์ผ ํ๊ธฐ ๋๋ฌธ์ ํ์์ด ์ ํ๋ฉ๋๋ค. ํ์์ด ์๋ฃ๋์ด์ ์ญ์ ํ ๋ ธ๋๋ฅผ ์ฐพ์ผ๋ฉด ๋ค์ ๊ณผ์ ์ ์งํํฉ๋๋ค.
1) ์ญ์ ํ ๋ ธ๋๊ฐ ๋ฆฌํ๋ ธ๋์ธ ๊ฒฝ์ฐ
๊ฐ์ฅ ์ฌ์ด ๊ฒฝ์ฐ์ ๋๋ค. ๋ฆฌํ ๋ ธ๋์ ๊ฒฝ์ฐ์๋ ์ผ์ชฝ์ด๋ ์ค๋ฅธ์ชฝ์ ๋ค๋ฅธ ๋ ธ๋๋ค์ด ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฅ ํธ๋ฆฌ์์ ๋ฆฌํ๋ ธ๋๋ง ์ ๊ฑฐํด์ฃผ๋ฉด ์ญ์ ๊ฐ ์๋ฃ๋ฉ๋๋ค.
๊ฐ๋จํ์ฃ ? ์ฝ๋๋ก ์์ฑํด๋ณด๋ฉด ์ด๋ ๊ฒ ๋ฉ๋๋ค.
guard let targetNode = self.search(data: data, in: root) else { return nil }
// target is leaf node
if targetNode.isLeafNode {
let parent = self.findParent(of: targetNode, under: root)
parent?.rightChild === targetNode
? (parent?.rightChild = nil)
: (parent?.leftChild = nil)
return targetNode.data
}
์ญ์ ํ ๋ ธ๋๋ฅผ ์ฐพ๊ณ ํด๋น ๋ ธ๋์ ๋ถ๋ชจ ๋ ธ๋๊ฐ ๊ฐ์ง ์ญ์ ํ ๋ ธ๋์ ๋ํ ํฌ์ธํฐ๋ฅผ ์ง์์ฃผ๋ฉด ๋ฉ๋๋ค. ์ฌ์ค ํ์ํ๋ฉด์ ๋ถ๋ชจ๋ ธ๋๋ฅผ ์ฐพ๋๊ฒ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ธ๋ฐ ํธ์์ ๋ฏธ๋ฆฌ ๊ตฌํ๋ ํ์ ์๊ณ ๋ฆฌ์ฆ์ ๊ทธ๋๋ก ์ฌ์ฉํ๊ณ ์ถ์ด์ ๋ถ๋ชจ ๋ ธ๋๋ฅผ ์ฐพ๋ ๋ฉ์๋๋ฅผ ๋ฐ๋ก ๋ง๋ค์ด์ฃผ์์ต๋๋ค.
2) ์ญ์ ํ ๋ ธ๋์๊ฒ ํ๋์ ์์ ๋ ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ
์ด๋ฒ์๋ ์ญ์ ํ ๋ ธ๋๊ฐ ์์ ๋ ธ๋๋ฅผ ์ผ์ชฝ์ด๋ ์ค๋ฅธ์ชฝ์ ํ๋๋ง ๊ฐ์ง๊ณ ์๋ ๊ฒฝ์ฐ์ ๋๋ค. ์ด๋๋ก ๋ ธ๋๋ฅผ ์ญ์ ํ๋ฉด ์๋์ ๋ธ๋ ค์๋ ์๋ธ ํธ๋ฆฌ์ ์ํ๋ ๋ชจ๋ ๋ ธ๋๊ฐ ์ญ์ ๋๊ธฐ ๋๋ฌธ์ ์ญ์ ํ ๋ ธ๋๊ฐ ๊ฐ์ง ํ๋์ ์๋ธํธ๋ฆฌ๋ฅผ ๊ธฐ์กด ํธ๋ฆฌ์ ์ฐ๊ฒฐ์์ผ์ฃผ์ด์ผํฉ๋๋ค.
์ผ์ชฝ์ ์์๋ ธ๋๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ด 2์ธ ๋ ธ๋๋ฅผ ์ญ์ ํด๋ด ์๋ค.
์ญ์ ํ ๋ ธ๋์ ๋ถ๋ชจ ๋ ธ๋๋ฅผ ์ฐพ๊ณ ํด๋น ๋ ธ๋์ ์์ ๋ ธ๋๋ฅผ ์ญ์ ํ ๋ ธ๋์ ์์ ๋ ธ๋๋ก ๋ณ๊ฒฝํด์ค๋๋ค. ์ด์ง ํ์ ํธ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ ์ผ์ชฝ ์๋ธํธ๋ฆฌ๋ ๋ชจ๋ ์ญ์ ํ ๋ ธ๋์ ๋ถ๋ชจ ๋ ธ๋๋ณด๋ค ์์ ๊ฐ๋ค์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ํธ๋ฆฌ๋ฅผ ์ฌ์กฐ์ ํด ์ค ํ์๊ฐ ์์ต๋๋ค.
guard let targetNode = self.search(data: data, in: root) else { return nil }
// target has single child node
if targetNode.hasSingleChild {
let child = targetNode.leftChild != nil ? targetNode.leftChild : targetNode.rightChild
guard let parent = self.findParent(of: targetNode, under: root) else { return nil }
parent.data > child!.data ? (parent.leftChild = child) : (parent.rightChild = child)
return targetNode.data
}
์ฝ๋๋ก ๊ตฌํํ ๋๋ ์ด๋ ต์ง ์๊ฒ ๊ตฌํํ ์ ์์์ต๋๋ค. ์ญ์ ํ ๋ ธ๋์ ๋ถ๋ชจ ๋ ธ๋๋ฅผ ์ฐพ์ ์์ ๋ ธ๋ ์ ๋ณด๋ฅผ ๋ณ๊ฒฝํด์ฃผ๋ ๊ฒ์ผ๋ก ์ฝ๊ฒ ๊ตฌํ์ด ๊ฐ๋ฅํฉ๋๋ค.
3) ์ญ์ ํ ๋ ธ๋์๊ฒ ๋ ๊ฐ์ ์์ ๋ ธ๋๊ฐ ์๋ ๊ฒฝ์ฐ
๋ฌธ์ ๋ ์ญ์ ํ ๋ ธ๋๊ฐ ๋ ๊ฐ์ ์์๋ ธ๋๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฒฝ์ฐ์ ๋๋ค.
์ด๋ฒ์๋ ์ด ํธ๋ฆฌ์ ๋ฃจํธ ๋ ธ๋๋ฅผ ์ญ์ ํ๋ค๊ณ ํด๋ณด๊ฒ ์ต๋๋ค. ๋ฃจํธ๋ ธ๋๋ฅผ ์ญ์ ํ๋ฉด์ ์์ชฝ ์๋ธํธ๋ฆฌ๋ค์ ์ฐ๊ฒฐํด์ผ๋๋๋ฐ์, ์ด๋ป๊ฒ ํด์ผ ์ด์ง ํ์ ํธ๋ฆฌ๋ฅผ ์ ์งํ๋ฉด์ ์ฐ๊ฒฐํด์ค ์ ์์๊น์?
์ญ์ ๋ ๋ ธ๋์ ์์ชฝ ์๋ธํธ๋ฆฌ๋ฅผ ์ฐ๊ฒฐํ ๋ ธ๋๋ ์ผ์ชฝ ์๋ธํธ๋ฆฌ์ ๊ฐ๋ณด๋ค๋ ์ปค์ผํ๊ณ , ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์ ๊ฐ๋ณด๋ค๋ ์์์ผํฉ๋๋ค.
์ด ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ ธ๋๋ ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ ๊ฐ์ฅ ์ผ์ชฝ์ ์๋ ๋ ธ๋๋ฅผ ์ฐพ์ ์ป์ ์ ์์ต๋๋ค. ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ๋ ํญ์ ์ผ์ชฝ ์๋ธํธ๋ฆฌ๋ณด๋ค ๊ฐ์ด ํฌ๊ณ , ์ค๋ฅธ์ชฝ ์๋ธํธ๋ฆฌ์ ๊ฐ์ฅ ์ผ์ชฝ ์๋ธํธ๋ฆฌ๋ ๊ทธ ์ค์์๋ ๊ฐ์ฅ ์์ ๊ฐ์ด๊ธฐ ๋๋ฌธ์ ์ผ์ชฝ ์๋ธํธ๋ฆฌ์ ๋ฆฌํ ๋ ธ๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ด์ง ํ์ ํธ๋ฆฌ๋ฅผ ์ ์งํ๋ฉด์ ์์ชฝ ์๋ธํธ๋ฆฌ๋ฅผ ์ฐ๊ฒฐ์์ผ์ค ์ ์์ต๋๋ค.
์ด๋ ๊ฒ ์ญ์ ํ ๋ ธ๋์ ์ค๋ฅธ์ชฝ ์์์ ์๋ธํธ๋ฆฌ์ ์๋ ๊ฐ์ฅ ์์ ๊ฐ์ ๊ฐ์ง ๋ ธ๋๋ฅผ Successor ๋ผ๊ณ ํฉ๋๋ค. ์ญ์ ํ ๋ ธ๋์ ์์น๋ฅผ ๊ณ์น๋ฐ์ ๋ ธ๋๋ผ๋ ์๋ฏธ์ธ ๊ฒ ๊ฐ๋ค์.
์ญ์ ํ ๋ ธ๋์ ์ค๋ฅธ์ชฝ ์์ ๋ ธ๋๋ก ๋จผ์ ์ด๋ํ๊ณ , ํด๋น ๋ ธ๋์ ์ผ์ชฝ ์๋ธํธ๋ฆฌ๋ฅผ ๊ณ์ ๋ฐ๋ผ๊ฐ๋ฉด,
๊ฐ์ด 7์ธ ๋ ธ๋๋ฅผ ์ป์ ์ ์์ต๋๋ค.
์ด์ ์ด ๋ ธ๋๊ฐ ๊ฐ์ง ๊ฐ์ ๋ฃจํธ๋ ธ๋์ ๋ฎ์ด์์์ค์๋ค.
์ค์ ๋ก ๋ ธ๋๋ฅผ ๊ตํํ๋ ๊ฒ๋ ์ข๊ฒ ์ง๋ง ํค๋ก ์ฌ์ฉ๋๋ ๋ ธ๋์ ๊ฐ์ผ๋ก ๋ฎ์ด์์๋ ๋ฌด๋ฐฉํฉ๋๋ค. ๋ง์ฝ ๋ ธ๋ ์ธ์คํด์ค๋ฅผ ์ญ์ ์ดํ์ ๋ฐํํ๊ฒ ํ๋ค๋ฉด ๋ ธ๋ ์์ฒด๋ฅผ ๊ตํํด์ผ๊ฒ ์ฃ ?
๊ทธ๋ฆฌ๊ณ Successor๋ก ์ฌ์ฉ๋ ๋ ธ๋๋ฅผ ์ง์์ฃผ๋ฉด, ๋ชฉํ ๋ ธ๋๋ฅผ ์ ๊ฑฐํ๊ณ ๋ ์ด์ง ํ์ ํธ๋ฆฌ๋ฅผ ์ ์งํ ์ ์์ต๋๋ค.
// target has two child nodes
if targetNode.hasTwoChild {
let deleted = targetNode.data
guard let successor = self.findSuccessor(of: targetNode.rightChild) else { return nil }
if !successor.isLeafNode {
let parent = self.findParent(of: successor, under: root)
parent?.leftChild = successor.rightChild
}
_ = self.delete(data: successor.data)
targetNode.update(data: successor.data)
return deleted
}
์ฝ๋๋ก๋ ์ด๋ ๊ฒ ๊ตฌํ๋ฉ๋๋ค. ๋จผ์ Successor๋ฅผ ์ฐพ์์ ๊ฐ์ ๋ฎ์ด์์ด ๋ค์, Successor์ ๋ถ๋ชจ๋ ธ๋๋ฅผ ์ฐพ์์ ์์ ๋ ธ๋์ ์ฐธ์กฐ๋ฅผ ์ ๊ฑฐํด์ค๋๋ค.
์ด๋ ๊ฒ ํด์ ์ญ์ ๋ฅผ ์ ๋ฆฌํ๋๋ฐ์, ์ญ์ ๋ ํ์๊ณผ ์ญ์ ์ ์กฐํฉ์ด๊ธฐ ๋๋ฌธ์ O(logN)์ ์๊ฐ๋ณต์ก๋๊ฐ ์๊ตฌ๋ฉ๋๋ค. ์ ๊ตฌํ์์๋ ๋ถ๋ชจ ๋ ธ๋๋ฅผ ์ฐพ์ ๋ ํ์์ ํ๋ฒ ๋ ์งํํด์ ๊ฐ์ธ์ ์ผ๋ก๋ ์ข์ง ์๋ค๊ณ ์๊ฐํ๋๋ฐ, ๋ถ๋ชจ ๋ ธ๋์ ๋ํ ์ ๋ณด๋ฅผ ๋ ธ๋์ ํ๋กํผํฐ๋ก ๊ฐ์ง๊ณ ์๊ฑฐ๋, ํ์ํ ๋ ๋ถ๋ชจ๋ ธ๋์ ์ ๋ณด๊น์ง ๋ฐํํด์ฃผ๋ฉด ์ต์ ํ๊ฐ ๊ฐ๋ฅํ ๊ฒ ๊ฐ์ต๋๋ค.
์ ์ฒด ์ฝ๋
์๋ฃ๊ตฌ์กฐ ์๋ฆฌ์ฆ์ ์ฝ๋๋ค์ ์ด ๋ ํฌ์์ ๋ชจ๋ ํ์ธํ ์ ์์ด์!
'๐ฎ ์จ-์์ค > ๐ฆด ์๋ฃ๊ตฌ์กฐ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote