λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸ–₯ Computer Science/Data Structure

[Data Structure] 이진 탐색 트리(Binary Search Tree) κ΅¬ν˜„ν•΄λ³΄κΈ° (feat.Swift)

by Fomagran πŸ’» 2021. 11. 18.
728x90
λ°˜μ‘ν˜•

μ•ˆλ…•ν•˜μ„Έμš” 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
728x90
λ°˜μ‘ν˜•

λŒ“κΈ€