μλ νμΈμ Foma π» μ λλ€!
μ λ² μκ°μ μ΄μ§ νμ νΈλ¦¬κ° λμ§ μ΄λ‘ μ λν΄ μμ보μλλ°μ.
μ€λμ μ΄μ§ νμ νΈλ¦¬λ₯Ό μ§μ ꡬνν΄λ³΄λ €κ³ ν©λλ€.
λ°λ‘ μμν κ²μ~
BSTNode
μ΄μ§ νμ νΈλ¦¬μ λ Έλλ₯Ό λ§λ€μ΄ μ£Όκ² μ΅λλ€.
λ Έλλ κ°,μΌμͺ½,μ€λ₯Έμͺ½ μμμ λ Έλ μ 보λ₯Ό κ°μ§κ³ μμ΅λλ€.
class BSTNode<T:Comparable> {
var value:T
var leftChild:BSTNode?
var rightChild:BSTNode?
init(value:T) {
self.value = value
}
}
Binary Search Tree
μ΄μ§ νμ νΈλ¦¬μ μ΅μλ¨ κ°μ κ°μ§ rootλ₯Ό νλ‘νΌν°λ‘ μ μνμ΅λλ€.
struct BinarySearchTree<T:Comparable> {
var root:BSTNode<T>?
Insert
public mutating func insert(value:T) {
guard let _ = root else {
self.root = BSTNode(value: value)
return
}
var node:BSTNode = root!
while true {
if node.value > value {
if node.leftChild == nil {
node.leftChild = BSTNode(value: value)
break
}else {
node = node.leftChild!
}
}else {
if node.rightChild == nil {
node.rightChild = BSTNode(value: value)
break
}else {
node = node.rightChild!
}
}
}
}
κ°μ΄ μ λ€μ΄κ°λμ§ ν μ€νΈ ν΄λ΄μΌκ² μ£ ?
ν μ€νΈ νκΈ° μν΄μ μλμ κ°μ΄ μΌμͺ½κ³Ό μ€λ₯Έμͺ½ μμλ€μ μ¬κ·νλ©° μΆλ ₯νλ λ©μλλ₯Ό ꡬννμ΅λλ€.
func printChild(node:BSTNode<Int>?) {
if node == nil { return }
print("\(node!.value)μ μΌμͺ½ μμ :\(node!.leftChild?.value)")
print("\(node!.value)μ μ€λ₯Έμͺ½ μμ :\(node!.rightChild?.value)")
printChild(node: node!.leftChild)
printChild(node: node!.rightChild)
}
10,11,8,1,3μ μ°¨λ‘λ‘ μ½μ νκ³ μΆλ ₯ν΄λ³΄λ©΄ μλμ κ°μ΄ κ°μ΄ μ λ€μ΄κ° κ²μ νμΈν μ μμ΅λλ€.
var bst = BinarySearchTree<Int>()
bst.insert(value: 10)
bst.insert(value: 11)
bst.insert(value: 8)
bst.insert(value: 1)
bst.insert(value: 3)
printChild(node: bst.root)
// 10μ μΌμͺ½ μμ :Optional(8)
// 10μ μ€λ₯Έμͺ½ μμ :Optional(11)
// 8μ μΌμͺ½ μμ :Optional(1)
// 8μ μ€λ₯Έμͺ½ μμ :nil
// 1μ μΌμͺ½ μμ :nil
// 1μ μ€λ₯Έμͺ½ μμ :Optional(3)
// 3μ μΌμͺ½ μμ :nil
// 3μ μ€λ₯Έμͺ½ μμ :nil
// 11μ μΌμͺ½ μμ :nil
// 11μ μ€λ₯Έμͺ½ μμ :nil
// 10
// 8 11
//1
// 3
Search
'μ΄μ§ νμ νΈλ¦¬μ κ²μμ μ΄λ€ κ±Έ λ°νν΄μΌ ν κΉ?' λΌκ³ κ³ λ―Όνλλ°, λ³΄ν΅ ν΄λΉ κ°μ΄ μλμ§ μλμ§λ₯Ό λ°ννλλΌκ΅¬μ.
κ·Έλμ μ λ SearchλΌλ μ΄λ¦ λμ isContainμΌλ‘ μ΄λ¦μ§μ΄μ€¬μ΅λλ€.
public func isContain(value:T) -> Bool {
var node:BSTNode? = root
while node != nil {
if node!.value == value {
return true
}
node = node!.value > value ? node?.leftChild : node?.rightChild
}
return false
}
Insertμμ μ½μ ν κ°μ ν λλ‘ κ²μμ΄ μ λλμ§ νμΈν΄λ³΄κ² μ΅λλ€.
μλμ κ°μ΄ ν¬ν¨λμ΄ μλ€λ©΄ trueλ₯Ό κ·Έλ μ§ μλ€λ©΄ falseλ₯Ό λ°ννλ κ²μ λ³Ό μ μμ΅λλ€.
bst.isContain(value: 11) //true
bst.isContain(value: 100) //false
bst.isContain(value: 0) //false
bst.isContain(value: 8) //true
Delete
μμ λ₯Ό ꡬνν λ μ§μ§ 볡μ‘νμ΅λλ€..
μμμ΄ μμ λ,1κ°μΌ λ,2κ°μΌ λλ₯Ό λͺ¨λ λ°μ Έμ€μΌ νμ΅λλ€..
(μ½λκ° μ λ§ λ§μ μλ€μ§λ§... λμ€μ 리ν©ν°λ§ν΄μ μμ νλλ‘ νκ² μ΅λλ€.)
public mutating func remove(value:T) {
if root == nil {
return
}
var parent:BSTNode = root!
var node:BSTNode? = root
while node != nil {
if node!.value == value {
//μμμ΄ 2κ° μμ λ
if node?.leftChild != nil && node?.rightChild != nil {
let rightChild = node?.rightChild
node = findLeftChildMaxValue(node: node!.leftChild!)
node?.rightChild = rightChild
//μμμ΄ μΌμͺ½λ§ μμ λ
}else if node?.leftChild != nil{
if node!.value < parent.value {
parent.leftChild = node?.leftChild
}else {
parent.rightChild = node?.leftChild
}
//μμμ΄ μ€λ₯Έμͺ½λ§ μμ λ
}else if node?.rightChild != nil {
if node!.value < parent.value {
parent.leftChild = node?.rightChild
}else {
parent.rightChild = node?.rightChild
}
//μμμ΄ μμ λ
}else {
if node?.value == root?.value {
root = nil
return
}
if node!.value < parent.value {
parent.leftChild = nil
}else {
parent.rightChild = nil
}
}
if value == root?.value {
self.root = node!
}
break
}
parent = node!
node = node!.value > value ? node?.leftChild : node?.rightChild
}
}
μ¬κΈ°μ λ§μ½ μμμ΄ 2κ°λΌλ©΄ μ€λ₯Έμͺ½ μμμ κ°μ₯ μμ κ° λλ μΌμͺ½ μμμ κ°μ₯ ν° κ°μ λ체ν΄μΌ νκΈ° λλ¬Έμ
μλλ μ€λ₯Έμͺ½ μμμ κ°μ₯ μμ κ°μ ꡬνλ λ©μλμ΄κ³ ,
private func findRightChildMinValue(node:BSTNode<T>) -> BSTNode<T> {
var parent:BSTNode<T> = node
var leftChild:BSTNode? = node.leftChild
while leftChild?.leftChild != nil {
leftChild = leftChild?.leftChild!
parent = leftChild!
}
if leftChild?.rightChild != nil {
parent.rightChild = leftChild?.rightChild
}
return leftChild ?? parent
}
μλλ μΌμͺ½ μμμ κ°μ₯ ν° κ°μ ꡬνλ λ©μλ μ λλ€.
private func findLeftChildMaxValue(node:BSTNode<T>) -> BSTNode<T> {
var parent:BSTNode<T> = node
var rightChild:BSTNode? = node.rightChild
while rightChild?.rightChild != nil {
rightChild = rightChild?.rightChild!
parent = rightChild!
}
if rightChild?.leftChild != nil {
parent.leftChild = rightChild?.leftChild
}
return rightChild ?? parent
}
μμ λν Insertμμ λ£μ κ°μΌλ‘ ν μ€νΈ ν΄λ³΄κ² μ΅λλ€.
1. μμμ΄ μμ κ²½μ°
λ¨Όμ μμμ΄ μμ λμ κ°μΈ 3μ μμ ν΄ λ³΄κ² μ΅λλ€.
μλμ κ°μ΄ μ μμ μΌλ‘ 3μ΄ μμ λ κ²μ λ³Ό μ μμ΅λλ€.
bst.remove(value: 3)
printChild(node: bst.root)
// 10μ μΌμͺ½ μμ :Optional(8)
// 10μ μ€λ₯Έμͺ½ μμ :Optional(11)
// 8μ μΌμͺ½ μμ :Optional(1)
// 8μ μ€λ₯Έμͺ½ μμ :nil
// 1μ μΌμͺ½ μμ :nil
// 1μ μ€λ₯Έμͺ½ μμ :nil
// 11μ μΌμͺ½ μμ :nil
// 11μ μ€λ₯Έμͺ½ μμ :nil
// 10
// 8 11
//1
2. μμμ΄ 1κ°μΈ κ²½μ°
κ·Έ λ€μμΌλ‘ μμμ΄ 1κ°μΈ κ²½μ°μΈ 8μ μμ ν΄λ³΄κ² μ΅λλ€.
μλμ κ°μ΄ 8μ΄ μμ λκ³ κ·Έ μλ μμμΌλ‘ λ체λ κ²μ λ³Ό μ μμ΅λλ€.
bst.remove(value: 8)
printChild(node: bst.root)
// 10μ μΌμͺ½ μμ :Optional(1)
// 10μ μ€λ₯Έμͺ½ μμ :Optional(11)
// 1μ μΌμͺ½ μμ :nil
// 1μ μ€λ₯Έμͺ½ μμ :Optional(3)
// 3μ μΌμͺ½ μμ :nil
// 3μ μ€λ₯Έμͺ½ μμ :nil
// 11μ μΌμͺ½ μμ :nil
// 11μ μ€λ₯Έμͺ½ μμ :nil
// 10
// 1 11
// 3
3. μμμ΄ 2κ°μΈ κ²½μ°
κ·Έ λ€μμΌλ‘ μμμ΄ 2κ°μΈ κ²½μ°μΈ 10μ μμ ν΄λ³΄κ² μ΅λλ€.
(μ λ μΌμͺ½ μμ μ€ κ°μ₯ ν° κ°μΌλ‘ λ체νλ λ©μλλ₯Ό μ¬μ©νμ΅λλ€.)
μλμ κ°μ΄ 10μ΄ μμ λκ³ μΌμͺ½ κ° μ€ κ°μ₯ ν° κ°μΈ 8λ‘ λ체λλ κ²μ λ³Ό μ μμ΅λλ€.
bst.remove(value: 10)
printChild(node: bst.root)
// 8μ μΌμͺ½ μμ :Optional(1)
// 8μ μ€λ₯Έμͺ½ μμ :Optional(11)
// 1μ μΌμͺ½ μμ :nil
// 1μ μ€λ₯Έμͺ½ μμ :Optional(3)
// 3μ μΌμͺ½ μμ :nil
// 3μ μ€λ₯Έμͺ½ μμ :nil
// 11μ μΌμͺ½ μμ :nil
// 11μ μ€λ₯Έμͺ½ μμ :nil
// 8
// 1 11
// 3
λκΈ