๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ–ฅ 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
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€