๐Ÿ“•Week1 day2(20-21)

๋ฐ•์ค€ํฌยท2023๋…„ 8์›” 23์ผ

ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค

๋ชฉ๋ก ๋ณด๊ธฐ
4/28
post-thumbnail

์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ(Binary Search Tree)


๋ชจ๋“  ๋…ธ๋“œ์— ๋Œ€ํ•ด์„œ ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋Š” ๋ชจ๋‘ ํ˜„์žฌ ๋…ธ๋“œ์˜ ๊ฐ’๋ณด๋‹ค ์ž‘๊ณ  ์˜ค๋ฅธ์ชฝ์€ ๋ชจ๋‘ ํฐ ์„ฑ์งˆ์„ ๋งŒ์กฑํ•˜๋Š” ์ด์ง„ํŠธ๋ฆฌ.

์ด์ง„ํƒ์ƒ‰๊ณผ ์œ ์‚ฌํ•œ ์ ์ด ๋งŽ์•„ ์ด์ง„ํƒ์ƒ‰๊ณผ ๋น„๊ตํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์žฅ์  : ๋ฐ์ดํ„ฐ ์›์†Œ์˜ ์ถ”๊ฐ€, ์‚ญ์ œ๊ฐ€ ์šฉ์ดํ•˜๋‹ค.
๋‹จ์  : ๊ณต๊ฐ„ ์†Œ์š”๊ฐ€ ํผ

์ด์ง„ํƒ์ƒ‰ํŠธ๋ฆฌ์˜ ์ถ”์ƒ์  ์ž๋ฃŒ๊ตฌ์กฐ


๋ฐ์ดํ„ฐ ํ‘œํ˜„- ๊ฐ ๋…ธ๋“œ๋Š” key, value ์Œ์œผ๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ๋‹ค.
key๋ฅผ ์ด์šฉํ•ด์„œ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•˜๋‹ค.

์ด์ง„ํƒ์ƒ‰ํŠธ๋ฆฌ ์—ฐ์‚ฐ์˜ ์ •์˜

  • insert(key, data) ๋ฐ์ดํ„ฐ์›์†Œ๋ฅผ ์ถ”๊ฐ€
  • remove(key)ํŠน์ • ์›์†Œ ์‚ญ์ œ
  • lookup(key) ํŠน์ • ์›์†Œ ๊ฒ€์ƒ‰
  • inorder() ํ‚ค์˜ ์ˆœ์„œ๋Œ€๋กœ ์›์†Œ ๋‚˜์—ด
  • min,max ์ตœ์†Œํ‚ค ์ตœ๋Œ€ํ‚ค๋ฅผ ๊ฐ€์ง€๋Š” ์›์†Œ ํƒ์ƒ‰

์ด์ง„ํƒ์ƒ‰ํŠธ๋ฆฌ ๊ตฌํ˜„


์ด์ง„ํƒ์ƒ‰ํŠธ๋ฆฌ ์—ฐ์‚ฐ์ค‘์— ๋Œ€๋ถ€๋ถ„ ์—ฐ์‚ฐ๋“ค์€ ๊ฐ„๋‹จํ–ˆ์ง€๋งŒ remove ์—ฐ์‚ฐ์€ ์กฐ๊ธˆ ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค.

๋ฃจํŠธ ๋…ธ๋“œ ๋˜๋Š” ๋‚ด๋ถ€ ๋…ธ๋“œ๊ฐ€ ์‚ญ์ œ๋˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋‹ค๋ฅธ ๋…ธ๋“œ๋“ค์„ ์ด๋ฆฌ์ €๋ฆฌ ์˜ฎ๊ฒจ์„œ ํŠธ๋ฆฌ์˜ ๋ชจ์Šต์„ ๊ฐ–์ถ”๋„๋ก ๊ตฌ์กฐ๋ฅผ ์กฐ์ •ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

remove๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์ƒํ™ฉ์„ ์ •๋ฆฌํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.
์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ๊ฐ€
1. ๋ง๋‹จ (leaf) ๋…ธ๋“œ์ธ ๊ฒฝ์šฐ
๊ทธ๋ƒฅ ๊ทธ ๋…ธ๋“œ๋ฅผ ์—†์• ๋ฉด ๋œ๋‹ค.
โ†’ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๋งํฌ๋ฅผ ์กฐ์ • (์ขŒ? ์šฐ?)
โ†’ ์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ (X) ๊ฐ€ root node ์ธ ๊ฒฝ์šฐ๋„ ํŠน๋ณ„ ์ฒ˜๋ฆฌ!

2.์ž์‹์„ ํ•˜๋‚˜ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ
์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ ์ž๋ฆฌ์— ๊ทธ ์ž์‹์„ ๋Œ€์‹  ๋ฐฐ์น˜
โ†’ ์ž์‹์ด ์™ผ์ชฝ? ์˜ค๋ฅธ์ชฝ?
โ†’ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๋งํฌ๋ฅผ ์กฐ์ • (์ขŒ? ์šฐ?)
โ†’ ์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ (X) ๊ฐ€ root node ์ธ ๊ฒฝ์šฐ, ๋Œ€์‹  ๋“ค์–ด์˜ค๋Š” ์ž์‹์ด ์ƒˆ๋กœ root๊ฐ€ ๋จ

3.์ž์‹์„ ๋‘˜ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ
์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ๋ณด๋‹ค ๋ฐ”๋กœ ๋‹ค์Œ (ํฐ) ํ‚ค๋ฅผ ๊ฐ€์ง€๋Š” ๋…ธ๋“œ๋ฅผ ์ฐพ์•„
๊ทธ ๋…ธ๋“œ๋ฅผ ์‚ญ์ œ๋˜๋Š” ๋…ธ๋“œ ์ž๋ฆฌ์— ๋Œ€์‹  ๋ฐฐ์น˜ํ•˜๊ณ 
์ด ๋…ธ๋“œ๋ฅผ ๋Œ€์‹  ์‚ญ์ œ

๋‹ค์Œ์€ remove์— ๋Œ€ํ•œ ๊ตฌํ˜„์ž…๋‹ˆ๋‹ค.

def remove(self, key):
        node, parent = self.lookup(key)

        if node:
            nChildren = node.countChildren()
            # The simplest case of no children
            if nChildren == 0:
                # ๋งŒ์•ฝ parent ๊ฐ€ ์žˆ์œผ๋ฉด
                # node ๊ฐ€ ์™ผ์ชฝ ์ž์‹์ธ์ง€ ์˜ค๋ฅธ์ชฝ ์ž์‹์ธ์ง€ ํŒ๋‹จํ•˜์—ฌ
                # parent.left ๋˜๋Š” parent.right ๋ฅผ None ์œผ๋กœ ํ•˜์—ฌ
                # leaf node ์˜€๋˜ ์ž์‹์„ ํŠธ๋ฆฌ์—์„œ ๋Š์–ด๋‚ด์–ด ์—†์•ฑ๋‹ˆ๋‹ค.
                if parent:
                    if node == parent.right:
                        parent.right = None
                    if node == parent.left:
                        parent.left = None
                # ๋งŒ์•ฝ parent ๊ฐ€ ์—†์œผ๋ฉด (node ๋Š” root ์ธ ๊ฒฝ์šฐ)
                # self.root ๋ฅผ None ์œผ๋กœ ํ•˜์—ฌ ๋นˆ ํŠธ๋ฆฌ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
                else:
                    self.root = None
            # When the node has only one child
            elif nChildren == 1:
                # ํ•˜๋‚˜ ์žˆ๋Š” ์ž์‹์ด ์™ผ์ชฝ์ธ์ง€ ์˜ค๋ฅธ์ชฝ์ธ์ง€๋ฅผ ํŒ๋‹จํ•˜์—ฌ
                # ๊ทธ ์ž์‹์„ ์–ด๋–ค ๋ณ€์ˆ˜๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
                if node.left:
                    direct = node.left
                else:
                    direct = node.right
                # ๋งŒ์•ฝ parent ๊ฐ€ ์žˆ์œผ๋ฉด
                # node ๊ฐ€ ์™ผ์ชฝ ์ž์‹์ธ์ง€ ์˜ค๋ฅธ์ชฝ ์ž์‹์ธ์ง€ ํŒ๋‹จํ•˜์—ฌ
                # ์œ„์—์„œ ๊ฐ€๋ฆฌํ‚จ ์ž์‹์„ ๋Œ€์‹  node ์˜ ์ž๋ฆฌ์— ๋„ฃ์Šต๋‹ˆ๋‹ค.
                if parent:
                    if node == parent.right:
                        parent.right = direct
                    else:
                        parent.left = direct
                # ๋งŒ์•ฝ parent ๊ฐ€ ์—†์œผ๋ฉด (node ๋Š” root ์ธ ๊ฒฝ์šฐ)
                # self.root ์— ์œ„์—์„œ ๊ฐ€๋ฆฌํ‚จ ์ž์‹์„ ๋Œ€์‹  ๋„ฃ์Šต๋‹ˆ๋‹ค.
                else:
                    self.root = direct
            # When the node has both left and right children
            else:
                parent = node
                successor = node.right
                # parent ๋Š” node ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๊ณ ,
                # successor ๋Š” node ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ์œผ๋ฏ€๋กœ
                # successor ๋กœ๋ถ€ํ„ฐ ์™ผ์ชฝ ์ž์‹์˜ ๋งํฌ๋ฅผ ๋ฐ˜๋ณตํ•˜์—ฌ ๋”ฐ๋ผ๊ฐ์œผ๋กœ์จ
                # ์ˆœํ™˜๋ฌธ์ด ์ข…๋ฃŒํ•  ๋•Œ successor ๋Š” ๋ฐ”๋กœ ๋‹ค์Œ ํ‚ค๋ฅผ ๊ฐ€์ง„ ๋…ธ๋“œ๋ฅผ,
                # ๊ทธ๋ฆฌ๊ณ  parent ๋Š” ๊ทธ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ์ฐพ์•„๋ƒ…๋‹ˆ๋‹ค.
                while successor.left:
                    parent = successor
                    successor = successor.left
                # ์‚ญ์ œํ•˜๋ ค๋Š” ๋…ธ๋“œ์ธ node ์— successor ์˜ key ์™€ data ๋ฅผ ๋Œ€์ž…ํ•ฉ๋‹ˆ๋‹ค.
                node.key = successor.key
                node.data = successor.data
                # ์ด์ œ, successor ๊ฐ€ parent ์˜ ์™ผ์ชฝ ์ž์‹์ธ์ง€ ์˜ค๋ฅธ์ชฝ ์ž์‹์ธ์ง€๋ฅผ ํŒ๋‹จํ•˜์—ฌ
                # ๊ทธ์— ๋”ฐ๋ผ parent.left ๋˜๋Š” parent.right ๋ฅผ
                # successor ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋˜ (์—†์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ) ์ž์‹์„ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
                    if successor.key == parent.left.key:
                        parent.left = successor.right
                    else:
                        parent.right = successor.right

                return True

๐Ÿ’ก์ด์ง„ํƒ์ƒ‰ํŠธ๋ฆฌ๊ฐ€ ๋งŒ์•ฝ์— ํ•œ์ค„๋กœ ๋Š˜์–ด์„œ ์žˆ์„ ๋•Œ, ํƒ์ƒ‰ ์—ฐ์‚ฐ ๋ณต์žก๋„๋Š” ์„ ํ˜• ํƒ์ƒ‰ ๋ณต์žก๋„์™€ ๋™์ผํ•ด ์ง„๋‹ค๋Š” ๋‹จ์ ์„ ์•Œ์•˜๋‹ค.

profile
๊ฒŒ์„๋ €๋˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ณต๋ถ€

0๊ฐœ์˜ ๋Œ“๊ธ€