๊ด€๋ฆฌ ๋ฉ”๋‰ด

DOing

[์ž๋ฃŒ๊ตฌ์กฐ] ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ with Python ๋ณธ๋ฌธ

์•Œ๊ณ ๋ฆฌ์ฆ˜

[์ž๋ฃŒ๊ตฌ์กฐ] ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ with Python

mangdo 2021. 6. 21. 19:19

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

:  ์ด์ง„ํŠธ๋ฆฌ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถ”๊ฐ€์ ์ธ ์กฐ๊ฑด์ด ์žˆ๋Š” ํŠธ๋ฆฌ

1) ๋ชจ๋“  ๋…ธ๋“œ๋Š” ์™ผ์ชฝ ๊ฐ€์ง€์— ํฌํ•จ๋˜๋Š” ์–ด๋–ค ์ˆซ์ž๋ณด๋‹ค๋„ ํฐ๊ฐ’์„ ๊ฐ€์ง„๋‹ค.

2) ๋ชจ๋“  ๋…ธ๋“œ๋Š” ์˜ค๋ฅธ์ชฝ ๊ฐ€์ง€์— ํฌํ•จ๋˜๋Š” ์–ด๋–ค ์ˆซ์ž๋ณด๋‹ค๋„ ์ž‘์€๊ฐ’์„ ๊ฐ€์ง„๋‹ค.

ํ•ด๋‹น ๊ทธ๋ฆผ์—์„œ ๋ณผ ๋•Œ 14๋ฅผ ์˜ˆ์‹œ๋กœ ๋“ค์–ด๋ณด์ž.

1) 14๋Š” ์™ผ์ชฝ๊ฐ€์ง€์— ํฌํ•จ๋˜๋Š” 11๋ณด๋‹ค ํฐ๊ฐ’์„ ๊ฐ€์ง„๋‹ค.

2) 14๋Š” ์˜ค๋ฅธ์ชฝ๊ฐ€์ง€์— ํฌํ•จ๋˜๋Š” 15,18,19๋ณด๋‹ค ์ž‘์€๊ฐ’์„ ๊ฐ€์ง„๋‹ค.

 

๐Ÿ’ก ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ ์‚ฝ์ž…, ํƒ์ƒ‰ ๋™์ž‘๊ณผ์ •

[ ํƒ์ƒ‰๊ณผ์ • ]

1. ์ฐพ๋Š” ์ˆซ์ž๊ฐ€ ํ˜„์žฌ ๋…ธ๋“œ ๊ฐ’๊ณผ ๊ฐ™๋‹ค๋ฉด ํƒ์ƒ‰ ์„ฑ๊ณต!

2. ์ฐพ๋Š” ์ˆซ์ž๊ฐ€ ํ˜„์žฌ ๋…ธ๋“œ ๊ฐ’๋ณด๋‹ค ์ž‘๋‹ค๋ฉด ์™ผ์ชฝ์œผ๋กœ ๊ฐ„๋‹ค.

3. ์ฐพ๋Š” ์ˆซ์ž๊ฐ€ ํ˜„์žฌ ๋…ธ๋“œ ๊ฐ’๋ณด๋‹ค ํฌ๋‹ค๋ฉด ์˜ค๋ฅธ์ชฝ์œผ๋กœ ๊ฐ„๋‹ค.

 

[ ์‚ฝ์ž…๊ณผ์ • ]

1. ์‚ฝ์ž…ํ•  ์ˆซ์ž๊ฐ€ ํ˜„์žฌ ๋…ธ๋“œ ๊ฐ’๋ณด๋‹ค ์ž‘๋‹ค๋ฉด ์™ผ์ชฝ์œผ๋กœ ๊ฐ„๋‹ค.

2. ์‚ฝ์ž…ํ•  ์ˆซ์ž๊ฐ€ ํ˜„์žฌ ๋…ธ๋“œ ๊ฐ’๋ณด๋‹ค ํฌ๋‹ค๋ฉด ์˜ค๋ฅธ์ชฝ์œผ๋กœ ๊ฐ„๋‹ค.

3. ์ž์‹๋…ธ๋“œ๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ 1~2๊ณผ์ •์„ ๋ฐ˜๋ณตํ•˜๊ณ  ์ž์‹๋…ธ๋“œ๊ฐ€ ์—†์„ ๋•Œ ๋งŒ๋“ค์–ด์„œ ์—ฐ๊ฒฐ์‹œ์ผœ์ค€๋‹ค.

 

๐Ÿ’ก ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ ์‚ฝ์ž…, ํƒ์ƒ‰ ์ฝ”๋“œ

 

class Node:
    def __init__(self, value):
        # double linked list
        self.value = value
        self.left = None
        self.right = None


class NodeMgmt:
    def __init__(self, head):
        self.head = head  # ๋ฃจํŠธ๋…ธ๋“œ

    # ์‚ฝ์ž…
    def insert(self, value):
        self.current_node = self.head
        while True:
            if value < self.current_node.value:
                if self.current_node.left != None:  # ์ด๋ฏธ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด
                    self.current_node = self.current_node.left  # ๋น„๊ต๋Œ€์ƒ์„ ๋ฐ”๊พผ๋‹ค.
                else:
                    self.current_node.left = Node(value)  # ์—†๋‹ค๋ฉด ์ƒˆ๋กœ ๋งŒ๋“ค์–ด ์—ฐ๊ฒฐ์‹œํ‚จ๋‹ค.
                    break
            else:
                if self.current_node.right != None:  # ์ด๋ฏธ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด
                    self.current_node = self.current_node.right  # ๋น„๊ต๋Œ€์ƒ์„ ๋ฐ”๊พผ๋‹ค.
                else:
                    self.current_node.right = Node(value)
                    break

    # ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ ์ถœ๋ ฅ
    def search(self, value):
        self.current_node = self.head

        while self.current_node:
            if self.current_node.value == value:  # ์ฐพ์•˜๋‹ค
                return True
            elif value < self.current_node.value:
                self.current_node = self.current_node.left  # ๋น„๊ต๋Œ€์ƒ ๋ฐ”๊พธ๊ธฐ
            else:
                self.current_node = self.current_node.right  # ๋น„๊ต๋Œ€์ƒ ๋ฐ”๊พธ๊ธฐ
        return False  # ๋‹ค ์ฐพ์•„๋ดค๋Š”๋ฐ ์—†๋‹ค.

# ์‹คํ–‰
head = Node(1)
BST = NodeMgmt(head)
BST.insert(2)
BST.insert(3)

print(BST.search(2))
print(BST.search(5))

 

๐Ÿ’ก ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ์‚ญ์ œ ๋™์ž‘

์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ์‚ญ์ œ๋Š” ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฝ์šฐ๋ฅผ ๋‚˜๋ˆ ์„œ ์ƒ๊ฐํ•ด๋ณด์ž.

1) Leaf Node๋ฅผ ์‚ญ์ œ

: parent node๊ฐ€ ์‚ญ์ œํ•  ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฅดํ‚ค์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

๋ฆฌํ”„๋…ธ๋“œ๋ฅผ ์‚ญ์ œํ•  ๋•Œ

2) Child Node๊ฐ€ ํ•œ๊ฐœ์ธ Node ์‚ญ์ œ

: ์‚ญ์ œํ•  ๋…ธ๋“œ์˜ Parent Node๊ฐ€ ์‚ญ์ œํ•  Node์˜ child Node๋ฅผ ๊ฐ€๋ฅดํ‚ค๋„๋ก ํ•œ๋‹ค.

์ž์‹ ๋…ธ๋“œ๊ฐ€ ํ•œ๊ฐœ์ธ ๋…ธ๋“œ ์‚ญ์ œ

3) Child Node๊ฐ€ ๋‘๊ฐœ์ธ Node ์‚ญ์ œ(์ค‘์š”!)

: ์‚ญ์ œํ•  Node์˜ ์˜ค๋ฅธ์กฑ ์ž์‹ ์ค‘, ๊ฐ€์žฅ ์ž‘์€๊ฐ’์„ Parent Node๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋„๋กํ•œ๋‹ค.

: ๋˜๋Š” ์‚ญ์ œํ•  ๋…ธ๋“œ์˜ ์™ผ์ชฝ ์ž์‹ ์ค‘, ๊ฐ€์žฅ ํฐ๊ฐ’์„ Parent Node๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋„๋กํ•œ๋‹ค.

๊ธ€๋กœ ์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

1. ์‚ญ์ œํ•  Node์˜ ์˜ค๋ฅธ์ชฝ์ž์‹ ์„ ํƒ

2. ์˜ค๋ฅธ์ชฝ ์ž์‹์˜ ๊ฐ€์žฅ ์™ผ์ชฝ์— ์žˆ๋Š” Node ์„ ํƒ

3. ํ•ด๋‹น Node๋ฅผ ์‚ญ์ œํ•  Node์˜ Parent Node์˜ ์™ผ์ชฝ ๋ธŒ๋žœ์น˜๊ฐ€ ๊ฐ€๋ฅดํ‚ค๊ฒŒ ํ•จ.

4. ํ•ด๋‹น Node์˜ ์™ผ์ชฝ ๋ธŒ๋žœ์น˜๊ฐ€ ์‚ญ์ œํ•  Node์˜ ์™ผ์ชฝ child Node๋ฅผ ๊ฐ€๋ฅดํ‚ค๊ฒŒ ํ•จ

5. ํ•ด๋‹น Node์˜ ์˜ค๋ฅธ์ชฝ branch๊ฐ€ ์‚ญ์ œํ•  Node์˜ ์˜ค๋ฅธ์ชฝ child Node๋ฅผ ๊ฐ€๋ฅดํ‚ค๊ฒŒ ํ•จ

6. ๋งŒ์•ฝ ํ•ด๋‹น Node๊ฐ€ ์˜ค๋ฅธ์ชฝ child node๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ์„ ๊ฒฝ์šฐ,

   ํ•ด๋‹น Node์˜ ๋ณธ๋ž˜ Parent Node์˜ ์™ผ์ชฝ ๋ธŒ๋žœ์น˜๊ฐ€ ํ•ด๋‹น Node์˜ ์˜ค๋ฅธ์ชฝ child Node๋ฅผ ๊ฐ€๋ฅดํ‚ค๊ฒŒํ•จ

 

์ด๊ฑธ ์ฝ”๋“œ๋กœ ์˜ฎ๊ธฐ๋ฉด๋œ๋‹ค...^^

 


๐Ÿ’ก ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ์‚ญ์ œ ์ฝ”๋“œ

์•„๊นŒ ์จ๋„ฃ์€ NodeMgmt ํด๋ž˜์Šค์— ๋“ค์–ด๊ฐ€๋Š” ํ•จ์ˆ˜๋ผ๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•ด๋ผ.

๋‹ค ๋„ฃ์œผ๋ ค๋ฉด ๋„ˆ๋ฌด ๊ธธ์–ด์ง€๋‹ˆ๊นŒ!

    def delete(self, value):
        # ์‚ญ์ œํ•  ๋…ธ๋“œ ํƒ์ƒ‰
        self.current_node = self.head  # ์‚ญ์ œํ•  ๋…ธ๋“œ
        self.parent = self.head  # ์‚ญ์ œํ•  ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ

        # ์ผ๋‹จ ํ•ด๋‹น ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š”์ง€๋ฅผ ์ฐพ๋Š”๋‹ค
        while self.current_node:
            if self.current_node.value == value:
                searched = True
                break
            elif value < self.current_node.value:
                self.parent = self.current_node
                self.curent_node = self.current_node.left  # ๋น„๊ต๋Œ€์ƒ ๋ณ€๊ฒฝ
            else:
                self.parent = self.current_node
                self.current_node = self.current_node.right  # ๋น„๊ต๋Œ€์ƒ ๋ณ€๊ฒฝ

        if searched == False:  # ๊ทธ๋Ÿฐ ๊ฐ’์„ ๊ฐ€์ง„ ๋…ธ๋“œ๊ฐ€ ์—†๋‹ค = ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ์—†๋‹ค
            return False

        ## ํ•ด๋‹น๋…ธ๋“œ๋ฅผ ์ฐพ์•˜๋‹ค. ์ด์ œ ์‚ญ์ œ๋ฅผ ํ•˜์ž!

 

1) Leaf Node๋ฅผ ์‚ญ์ œ

: parent node๊ฐ€ ์‚ญ์ œํ•  ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฅดํ‚ค์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

# case1
        if self.current_node.left == None and self.current_node.right == None:
            if value < self.parent.value:
                self.parent.left = None
            else:
                self.parent.right = None

 

2) Child Node๊ฐ€ ํ•œ๊ฐœ์ธ Node ์‚ญ์ œ

: ์‚ญ์ œํ•  ๋…ธ๋“œ์˜ Parent Node๊ฐ€ ์‚ญ์ œํ•  Node์˜ child Node๋ฅผ ๊ฐ€๋ฅดํ‚ค๋„๋ก ํ•œ๋‹ค.

child ๋…ธ๋“œ๋ฅผ ์˜ค๋ฅธ์ชฝ์— ๊ฐ€์ง€๊ณ  ์žˆ๋ƒ, ์™ผ์ชฝ์— ๊ฐ€์ง€๊ณ  ์žˆ๋ƒ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง„๋‹ค.

# case2
        # ์™ผ์ชฝ ๋…ธ๋“œ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
        elif self.current_node.left != None and self.current_node.right == None:
            # ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ parent์˜ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋ƒ ์™ผ์ชฝ์— ์žˆ๋ƒ
            if value < self.parent.value:
                self.parent.left = self.current_node.left
            else:
                self.parent.right = self.current_node.left
        # ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
        elif self.current_node.left == None and self.current_node.right != None:
            if value < self.parent.value:
                self.parent.left = self.current_node.right
            else:
                self.parent.right = self.current_node.right

 

3) Child Node๊ฐ€ ๋‘๊ฐœ์ธ Node ์‚ญ์ œ

3-1.  ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ parent node ์™ผ์ชฝ์— ์žˆ๋‹ค.

3-1-1. ์‚ญ์ œํ•  ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์ค‘, ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์„ ๊ฐ€์ง„ node์˜ chlid node๊ฐ€ ์—†์„๋•Œ

3-1-2. ์‚ญ์ œํ•  ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์ค‘, ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์„ ๊ฐ€์ง„ node์˜ ์˜ค๋ฅธ์ชฝ์— chlid node๊ฐ€ ์žˆ์„๋•Œ

: ์˜ค๋ฅธ์ชฝ์— chlid node๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์™ผ์ชฝ์— ์žˆ์—ˆ์œผ๋ฉด ๊ฑ”๊ฐ€ ์˜ฌ๋ผ๊ฐ€๊ฒ ์ง€?

 

# case3 : ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ๋‘๊ฐœ์˜ ์ž์‹์„ ๊ฐ€์ง„๋‹ค
        if self.current_node.left != None and self.current_node.right != None:

            # case3-1 : ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ์™ผ์ชฝ์— ์žˆ๋‹ค
            if value < self.parent.value:
                self.change_node = self.current_node.right
                self.change_node_parent = self.current_node.right

                # ๊ฐ€์žฅ ์ž‘์€๊ฐ’์€ ๋ฌด์กฐ๊ฑด left์— ์žˆ๋‹ค = ์ผ๋‹จ left ๋๊นŒ์ง€ ๊ฐ€๊ฒŒ
                while self.change_node.left != None:
                    self.change_node_parent = self.change_node
                self.change_node = self.change_node.left

                # 3-1-2
                if self.change_node.right != None:
                    self.change_node_parent.left = self.change_node.right
                else:  # 3-1-1
                    self.change_node_parent.left = None

                # ์œ„๋กœ ์˜ฎ๊ธฐ๊ธฐ
                self.parent.left = self.change_node
                self.change_node.right = self.current_node.right
                self.change_node.left = self.current_node.left

3-2. ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ parent node์˜ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋‹ค.

3-2-1. ์‚ญ์ œํ•  ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์ค‘, ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์„ ๊ฐ€์ง„ node์˜ chlid node๊ฐ€ ์—†์„๋•Œ

3-2-2. ์‚ญ์ œํ•  ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ ์ž์‹์ค‘, ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์„ ๊ฐ€์ง„ node์˜ ์˜ค๋ฅธ์ชฝ์— chlid node๊ฐ€ ์žˆ์„๋•Œ

: ์˜ค๋ฅธ์ชฝ์— chlid node๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์™ผ์ชฝ์— ์žˆ์—ˆ์œผ๋ฉด ๊ฑ”๊ฐ€ ์˜ฌ๋ผ๊ฐ€๊ฒ ์ง€?

# case3-2 : ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋‹ค
            else:
                self.change_node = self.current_node.right
                self.change_node_parent = self.current_node.right
                while self.change_node.left != None:
                    self.change_node_parent = self.change_node
                    self.chage_node = self.change_node.left  # ๋น„๊ต ๋Œ€์ƒ ๋ณ€๊ฒฝ
                # 3-2-2
                if self.chage_node.right != None:
                    self.change_node_parent.left = self.change_node.right
                else:  # 3-2-1
                    self.change_node_parent.left = None

                # ์œ„๋กœ ์˜ฎ๊ธด๋‹ค.
                self.parent.right = self.change_node
                self.change_node.left = self.current_node.left
                self.chage_node.right = self.current_node.right

 

 

์ „์ฒด ์ฝ”๋“œ ๋ณด๊ธฐ

๋”๋ณด๊ธฐ
class Node:
    def __init__(self, value):
        # double linked list
        self.value = value
        self.left = None
        self.right = None


class NodeMgmt:
    def __init__(self, head):
        self.head = head  # ๋ฃจํŠธ๋…ธ๋“œ

    # ์‚ฝ์ž…
    def insert(self, value):
        self.current_node = self.head
        while True:
            if value < self.current_node.value:
                if self.current_node.left != None:  # ์ด๋ฏธ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด
                    self.current_node = self.current_node.left  # ๋น„๊ต๋Œ€์ƒ์„ ๋ฐ”๊พผ๋‹ค.
                else:
                    self.current_node.left = Node(value)  # ์—†๋‹ค๋ฉด ์ƒˆ๋กœ ๋งŒ๋“ค์–ด ์—ฐ๊ฒฐ์‹œํ‚จ๋‹ค.
                    break
            else:
                if self.current_node.right != None:  # ์ด๋ฏธ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด
                    self.current_node = self.current_node.right  # ๋น„๊ต๋Œ€์ƒ์„ ๋ฐ”๊พผ๋‹ค.
                else:
                    self.current_node.right = Node(value)
                    break

    # ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ ์ถœ๋ ฅ
    def search(self, value):
        self.current_node = self.head

        while self.current_node:
            if self.current_node.value == value:  # ์ฐพ์•˜๋‹ค
                return True
            elif value < self.current_node.value:
                self.current_node = self.current_node.left  # ๋น„๊ต๋Œ€์ƒ ๋ฐ”๊พธ๊ธฐ
            else:
                self.current_node = self.current_node.right  # ๋น„๊ต๋Œ€์ƒ ๋ฐ”๊พธ๊ธฐ
        return False  # ๋‹ค ์ฐพ์•„๋ดค๋Š”๋ฐ ์—†๋‹ค.


    def delete(self, value):
        # ์‚ญ์ œํ•  ๋…ธ๋“œ ํƒ์ƒ‰
        self.current_node = self.head  # ์‚ญ์ œํ•  ๋…ธ๋“œ
        self.parent = self.head  # ์‚ญ์ œํ•  ๋…ธ๋“œ์˜ ๋ถ€๋ชจ ๋…ธ๋“œ

        # ์ผ๋‹จ ํ•ด๋‹น ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š”์ง€๋ฅผ ์ฐพ๋Š”๋‹ค
        while self.current_node:
            if self.current_node.value == value:
                searched = True
                break
            elif value < self.current_node.value:
                self.parent = self.current_node
                self.curent_node = self.current_node.left  # ๋น„๊ต๋Œ€์ƒ ๋ณ€๊ฒฝ
            else:
                self.parent = self.current_node
                self.current_node = self.current_node.right  # ๋น„๊ต๋Œ€์ƒ ๋ณ€๊ฒฝ

        if searched == False:  # ๊ทธ๋Ÿฐ ๊ฐ’์„ ๊ฐ€์ง„ ๋…ธ๋“œ๊ฐ€ ์—†๋‹ค = ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ์—†๋‹ค
            return False

        ## ํ•ด๋‹น๋…ธ๋“œ๋ฅผ ์ฐพ์•˜๋‹ค. ์ด์ œ ์‚ญ์ œ๋ฅผ ํ•˜์ž!
        # case1
        if self.current_node.left == None and self.current_node.right == None:
            if value < self.parent.value:
                self.parent.left = None
            else:
                self.parent.right = None
        # case2
        # ์™ผ์ชฝ ๋…ธ๋“œ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
        elif self.current_node.left != None and self.current_node.right == None:
            # ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ parent์˜ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋ƒ ์™ผ์ชฝ์— ์žˆ๋ƒ
            if value < self.parent.value:
                self.parent.left = self.current_node.left
            else:
                self.parent.right = self.current_node.left
        # ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
        elif self.current_node.left == None and self.current_node.right != None:
            if value < self.parent.value:
                self.parent.left = self.current_node.right
            else:
                self.parent.right = self.current_node.right

        # case3 : ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ๋‘๊ฐœ์˜ ์ž์‹์„ ๊ฐ€์ง„๋‹ค
        if self.current_node.left != None and self.current_node.right != None:

            # case3-1 : ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ์™ผ์ชฝ์— ์žˆ๋‹ค
            if value < self.parent.value:
                self.change_node = self.current_node.right
                self.change_node_parent = self.current_node.right

                # ๊ฐ€์žฅ ์ž‘์€๊ฐ’์€ ๋ฌด์กฐ๊ฑด left์— ์žˆ๋‹ค = ์ผ๋‹จ left ๋๊นŒ์ง€ ๊ฐ€๊ฒŒ
                while self.change_node.left != None:
                    self.change_node_parent = self.change_node
                self.change_node = self.change_node.left

                # 3-1-2
                if self.change_node.right != None:
                    self.change_node_parent.left = self.change_node.right
                else:  # 3-1-1
                    self.change_node_parent.left = None

                # ์œ„๋กœ ์˜ฎ๊ธฐ๊ธฐ
                self.parent.left = self.change_node
                self.change_node.right = self.current_node.right
                self.change_node.left = self.current_node.left
            # case3-2 : ์‚ญ์ œํ•  ๋…ธ๋“œ๊ฐ€ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ์— ์žˆ๋‹ค
            else:
                self.change_node = self.current_node.right
                self.change_node_parent = self.current_node.right
                while self.change_node.left != None:
                    self.change_node_parent = self.change_node
                    self.chage_node = self.change_node.left  # ๋น„๊ต ๋Œ€์ƒ ๋ณ€๊ฒฝ
                # 3-2-2
                if self.chage_node.right != None:
                    self.change_node_parent.left = self.change_node.right
                else:  # 3-2-1
                    self.change_node_parent.left = None

                # ์œ„๋กœ ์˜ฎ๊ธด๋‹ค.
                self.parent.right = self.change_node
                self.change_node.left = self.current_node.left
                self.chage_node.right = self.current_node.right


# 1๋ถ€ํ„ฐ 999 ์ˆซ์ž ์ค‘์—์„œ ์ž„์˜๋กœ 100๊ฐœ ์ถ”์ถœํ•˜์—ฌ ์ด์ง„ ํŠธ๋ฆฌ์— ์ž…๋ ฅ/๊ฒ€์ƒ‰/์‚ญ์ œ
import random

# 1~999์ค‘ 100๊ฐœ์˜ ์ˆซ์ž ๋žœ๋ค ์„ ํƒ
bst_nums = set()  # 100๊ฐœ๋ฅผ ๋žœ๋ค์„ ํƒํ•˜๋‹ค๋ณด๋ฉด ์ค‘๋ณต์ด ์žˆ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ง‘ํ•ฉ(set)์œผ๋กœ ์ด๋ฅผ ๋ฐฉ์ง€
while len(bst_nums) != 100:
    bst_nums.add(random.randint(0, 999))  # ์ค‘๋ณต์ด๋ผ๋ฉด ์•„์˜ˆ ๋“ค์–ด๊ฐ€์งˆ ์•Š์Œ. ๊ทธ๋ž˜์„œ ๋ฐ˜๋ณต๋ฌธ์€ 100๋ฒˆ ์ด์ƒ ์‹คํ–‰๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Œ

#print(bst_nums)

# ์„ ํƒ๋œ 100๊ฐœ์˜ ์ˆซ์ž๋ฅผ ์ด์ง„ ํƒ์ƒ‰ํŠธ๋ฆฌ์— ์ž…๋ ฅ, ๋ฃจํŠธ๋…ธํŠธ๋Š” 500์œผ๋กœ ์ž„์˜๋กœ ์ง€์ •
# 1์ด๋‚˜ 999์ด๋Ÿฌ๋ฉด ํ•œ์ชฝ์— ์น˜์šฐ์นœ ํŠธ๋ฆฌ๊ฐ€ ๋ ๊ฒƒ์ด๋‹ค. ์ฃผ์˜ํ•˜์ž
head = Node(500)
binary_tree = NodeMgmt(head)
for num in bst_nums:
    binary_tree.insert(num)

# ์ž…๋ ฅํ•œ 100๊ฐœ์˜ ์ˆซ์ž ๊ฒ€์ƒ‰ (๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ํ™•์ธ)
for num in bst_nums:
    if binary_tree.search(num) == False:
        print("search failed", num)  # ์ด๊ฒŒ ์‚ฌ์‹ค ๋‚˜์˜ค๋ฉด ์ฝ”๋“œ ์ž˜๋ชป์ง ๊ฒƒ์ž„

# ์ž…๋ ฅํ•œ 100๊ฐœ์˜ ์ˆซ์ž ์ค‘ 10๊ฐœ์˜ ์ˆซ์ž๋ฅผ ๋žœ๋ค ์„ ํƒ
delete_nums = set()
bst_nums = list(bst_nums)  # ์ธ๋ฑ์Šค๋กœ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด listํƒ€์ž…์œผ๋กœ ๋ณ€ํ˜•์‹œํ‚จ๋‹ค.
while len(delete_nums) != 10:
    delete_nums.add(bst_nums[random.randint(0, 99)])

# ์„ ํƒํ•œ 10๊ฐœ์˜ ์ˆซ์ž๋ฅผ ์‚ญ์ œ(์‚ญ์ œ ๊ธฐ๋Šฅํ™•์ธ)
for del_num in delete_nums:
    if binary_tree.delete(del_num) == False:
        print('delete failed', del_num)  # ์ด๊ฒŒ ์‚ฌ์‹ค ๋‚˜์˜ค๋ฉด ์ฝ”๋“œ ์ž˜๋ชป์ง ๊ฒƒ์ž„

 

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

๋”๋ณด๊ธฐ

 

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋Œ๋ ธ์„๋•Œ ์•„๋ฌด๊ฒƒ๋„ ๋‚˜์˜ค์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ž˜ ์ง ๊ฒƒ์ด๋‹ค.

# 1๋ถ€ํ„ฐ 999 ์ˆซ์ž ์ค‘์—์„œ ์ž„์˜๋กœ 100๊ฐœ ์ถ”์ถœํ•˜์—ฌ ์ด์ง„ ํŠธ๋ฆฌ์— ์ž…๋ ฅ/๊ฒ€์ƒ‰/์‚ญ์ œ
import random

# 1~999์ค‘ 100๊ฐœ์˜ ์ˆซ์ž ๋žœ๋ค ์„ ํƒ
bst_nums = set()  # 100๊ฐœ๋ฅผ ๋žœ๋ค์„ ํƒํ•˜๋‹ค๋ณด๋ฉด ์ค‘๋ณต์ด ์žˆ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ง‘ํ•ฉ(set)์œผ๋กœ ์ด๋ฅผ ๋ฐฉ์ง€
while len(bst_nums) != 100:
    bst_nums.add(random.randint(0, 999))  # ์ค‘๋ณต์ด๋ผ๋ฉด ์•„์˜ˆ ๋“ค์–ด๊ฐ€์งˆ ์•Š์Œ. ๊ทธ๋ž˜์„œ ๋ฐ˜๋ณต๋ฌธ์€ 100๋ฒˆ ์ด์ƒ ์‹คํ–‰๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Œ

#print(bst_nums)

# ์„ ํƒ๋œ 100๊ฐœ์˜ ์ˆซ์ž๋ฅผ ์ด์ง„ ํƒ์ƒ‰ํŠธ๋ฆฌ์— ์ž…๋ ฅ, ๋ฃจํŠธ๋…ธํŠธ๋Š” 500์œผ๋กœ ์ž„์˜๋กœ ์ง€์ •
# 1์ด๋‚˜ 999์ด๋Ÿฌ๋ฉด ํ•œ์ชฝ์— ์น˜์šฐ์นœ ํŠธ๋ฆฌ๊ฐ€ ๋ ๊ฒƒ์ด๋‹ค. ์ฃผ์˜ํ•˜์ž
head = Node(500)
binary_tree = NodeMgmt(head)
for num in bst_nums:
    binary_tree.insert(num)

# ์ž…๋ ฅํ•œ 100๊ฐœ์˜ ์ˆซ์ž ๊ฒ€์ƒ‰ (๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ํ™•์ธ)
for num in bst_nums:
    if binary_tree.search(num) == False:
        print("search failed", num)  # ์ด๊ฒŒ ์‚ฌ์‹ค ๋‚˜์˜ค๋ฉด ์ฝ”๋“œ ์ž˜๋ชป์ง ๊ฒƒ์ž„

# ์ž…๋ ฅํ•œ 100๊ฐœ์˜ ์ˆซ์ž ์ค‘ 10๊ฐœ์˜ ์ˆซ์ž๋ฅผ ๋žœ๋ค ์„ ํƒ
delete_nums = set()
bst_nums = list(bst_nums)  # ์ธ๋ฑ์Šค๋กœ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด listํƒ€์ž…์œผ๋กœ ๋ณ€ํ˜•์‹œํ‚จ๋‹ค.
while len(delete_nums) != 10:
    delete_nums.add(bst_nums[random.randint(0, 99)])

# ์„ ํƒํ•œ 10๊ฐœ์˜ ์ˆซ์ž๋ฅผ ์‚ญ์ œ(์‚ญ์ œ ๊ธฐ๋Šฅํ™•์ธ)
for del_num in delete_nums:
    if binary_tree.delete(del_num) == False:
        print('delete failed', del_num)  # ์ด๊ฒŒ ์‚ฌ์‹ค ๋‚˜์˜ค๋ฉด ์ฝ”๋“œ ์ž˜๋ชป์ง ๊ฒƒ์ž„

๐Ÿ’ก ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„์™€ ๋‹จ์ 

[ ์‹œ๊ฐ„ ๋ณต์žก๋„ ]

: ๋…ธ๋“œ๊ฐ€ n๊ฐœ ์ผ๋•Œ ํŠธ๋ฆฌ์˜ ๋†’์ด h = logn์ด๋‹ค.

: ์ฆ‰, ์ด์ง„ ํƒ์ƒ‰ํŠธ๋ฆฌ์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” O(logn)์œผ๋กœ ๋ฆฌ์ŠคํŠธ์—์„œ ํƒ์ƒ‰ํ• ์‹œ์—๋Š” O(n)์ด ๊ฑธ๋ฆฌ๋Š” ๊ฒƒ์— ๋น„ํ•ด ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌ๊ฐ€๋Šฅํ•˜๋‹ค.

[ ๋‹จ์  ]

: O(logn)์€ ํŠธ๋ฆฌ๊ฐ€ ๊ท ํ˜•์žกํ˜€์žˆ์„ ๋•Œ์˜ ํ‰๊ท  ์‹œ๊ฐ„๋ณต์žก๋„์ด๋‹ค.

: ์œ„์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด root node๋ฅผ ์ž˜๋ชป์žก์•„์„œ ํŠธ๋ฆฌ๊ฐ€ ๋ถˆ๊ท ํ˜•์ด ๋˜์–ด ์ตœ์•…์˜ ๊ฒฝ์šฐ, linked list์™€ ๋™์ผํ•œ ์„ฑ๋Šฅ์„ ๋ณด์ผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ท ํ˜•์žกํžŒ ํŠธ๋ฆฌ๋ฅผ ์žก๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•œ๋ฐ, ๊นŠ๊ฒŒ ๋“ค์–ด๊ฐ€๋ฉด ์ด๋Ÿฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋„ ์กด์žฌํ•œ๋‹ค.

 

 

 

์ถœ์ฒ˜

PENJEE.COM'S BLOG : ์ด์ง„ํƒ์ƒ‰ํŠธ๋ฆฌ

ํŒจ์ŠคํŠธ ์บ ํผ์Šค ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์˜ฌ์ธ์› ๊ฐ•์˜