Binary Search Tree


๐Ÿ’ก ์ด์ง„ย ํƒ์ƒ‰ย ํŠธ๋ฆฌ๋Š” ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ์‚ฝ์ž…์ด๋‚˜ ์‚ญ์ œ๋ณด๋‹ค๋Š” ํƒ์ƒ‰์— ์ฃผ ๋ชฉ์ ์„ ๋‘” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค. {: .notice}


Search Tree

ํƒ์ƒ‰ ํŠธ๋ฆฌ

  • skip lists์™€ hash table๋“ค๊ณผ ๊ฐ™๊ฑฐ๋‚˜ ๊ทธ ์ด์ƒ์˜ ์„ฑ๋Šฅ์„ ๊ฐ€์ง
  • ์‚ฌ์ „์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ์— ์ด์ƒ์ ์ธ ๊ตฌ์กฐ
  • ์ˆœ์ฐจ์  ๋˜๋Š” ๋“ฑ๊ธ‰๋ณ„ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ์— ์ด์ƒ์ 
๐Ÿ’ก ๋นˆ์ถœ! ์ด์ง„ ํŠธ๋ฆฌ์™€ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ์ฐจ์ด์ 
    <br>
  - **์ด์ง„ ํŠธ๋ฆฌ**    
        : ๋…ธ๋“œ์˜ ์ตœ๋Œ€ Branch๊ฐ€ 2์ธ ํŠธ๋ฆฌ
    <br>
  - **์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ (Binary Search Tree, BST)**
        : ์ด์ง„ ํŠธ๋ฆฌ์— ์ถ”๊ฐ€์ ์ธ ์กฐ๊ฑด์ด ์žˆ๋Š” ํŠธ๋ฆฌ
            <br>
        โ‡’ ์กฐ๊ฑด : ์™ผ์ชฝ ๋…ธ๋“œ๋Š” ํ•ด๋‹น ๋…ธ๋“œ๋ณด๋‹ค ์ž‘์€ ๊ฐ’, ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ๋Š” ํ•ด๋‹น ๋…ธ๋“œ๋ณด๋‹ค ํฐ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ.
{.:notice}    


Binary Search Tree

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

Untitled

์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ๋Š” ํŠธ๋ฆฌ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†์„ฑ์„ ๋งŒ์กฑํ•œ๋‹ค.

  • ๋ชจ๋“  ๋…ธ๋“œ x์— ๋Œ€ํ•˜์—ฌ,

    ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์˜ ๋ชจ๋“  key๊ฐ’์€ ๋…ธ๋“œ x์˜ key๊ฐ’๋ณด๋‹ค ์ž‘๋‹ค.

    ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์˜ ๋ชจ๋“  key๊ฐ’์€ ๋…ธ๋“œ x์˜ key๊ฐ’๋ณด๋‹ค ํฌ๋‹ค.

  • ๋ชจ๋“  ๋…ธ๋“œ๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์œ ์ผํ•œ key๊ฐ’์„ ๊ฐ€์ง
  • ์™ผ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ์™€ ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ๋„ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์ž„
  • ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ๋ฅผ ์ค‘์œ„ ์ˆœํšŒํ•˜๋ฉด ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌ๋œ ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ์Œ


the class BinarySearchTree


์ž‘์—…์ด ์ˆ˜ํ–‰๋จ์— ๋”ฐ๋ผ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ๋ชจ์–‘๊ณผ ์š”์†Œ๋“ค์˜ ์ˆ˜๊ฐ€ ๋ณ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ผ๋ฐ˜์ ์œผ๋กœ linked representation์„ ์‚ฌ์šฉํ•˜์—ฌ ํ‘œํ˜„๋œ๋‹ค.

Python ๊ตฌํ˜„ ํด๋ž˜์Šค ์ •์˜ ๋ฐ ์ดˆ๊ธฐํ™”
class Node(object):                       # ๋จผ์ €ย Nodeย ํด๋ž˜์Šค๋ฅผ ์ •์˜
    def __init__(self, data):
        self.data = data
        self.left = self.right = None     # ์ดˆ๊ธฐํ™”ํ•  ๋•Œ๋Š” ๋ฐ์ดํ„ฐ ๊ฐ’๋งŒ ์ฃผ์–ด์ง€๊ณ  ์ขŒ์šฐ ๋…ธ๋“œ๋Š” ๋น„์–ด์žˆ์Œ

class BinarySearchTree(object):
    def __init__(self):
        self.root = None                # ์ฒ˜์Œ์—๋Š” ๋น„์–ด ์žˆ๋Š” ํŠธ๋ฆฌ๋กœ ์ดˆ๊ธฐํ™”


Ascend()

๋ชจ๋“  ์š”์†Œ๋ฅผ key์˜ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ถœ๋ ฅ


Find(key)

ํƒ์ƒ‰


๋ฃจํŠธ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋ฉฐ, key๊ฐ€ ๋ฃจํŠธ๋ณด๋‹ค ์ž‘์œผ๋ฉด ์™ผ์ชฝ ํ•˜์œ„ ํŠธ๋ฆฌ๊ฐ€ ํƒ์ƒ‰๋˜๊ณ  key๊ฐ€ ๋ฃจํŠธ๋ณด๋‹ค ํฌ๋ฉด ์˜ค๋ฅธ์ชฝ ํ•˜์œ„ ํŠธ๋ฆฌ๊ฐ€ ํƒ์ƒ‰๋œ๋‹ค. key๊ฐ€ ๋ฃจํŠธ์™€ ๊ฐ™์œผ๋ฉด ๊ฒ€์ƒ‰์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ข…๋ฃŒ๋œ๋‹ค.

  • ๋ฃจํŠธ๊ฐ€ NULL์ด๋ฉด ํƒ์ƒ‰ ํŠธ๋ฆฌ๊ฐ€ ํŠธ๋ฆฌ๊ฐ€ ๋น„์–ด ์žˆ์–ด ํƒ์ƒ‰ ์‹คํŒจ
  • ์‹œ๊ฐ„ ๋ณต์žก๋„ O(height)
Python ๊ตฌํ˜„ : find() Method ์žฌ๊ท€์™€ ๊ฐ’์˜ ๋Œ€์†Œ๊ด€๊ณ„ ๋น„๊ต๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
class BinarySearchTree(object):
    ...
    def find(self, key):
        return self._find_value(self.root, key)
    def _find_value(self, root, key):
        if root is None or root.data == key:
            return root is not None
        elif key < root.data:
            return self._find_value(root.left, key)
        else:
            return self._find_value(root.right, key)


Insert(key)

์‚ฝ์ž…


  • ์ด์ง„ ๊ฒ€์ƒ‰ ํŠธ๋ฆฌ์— ์ƒˆ ์š”์†Œ e๋ฅผ ์‚ฝ์ž…ํ•˜๋ ค๋ฉด ๋จผ์ € ํŠธ๋ฆฌ์—์„œ ํƒ์ƒ‰์„ ์ˆ˜ํ–‰ํ•˜์—ฌ key๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค.
  • ํƒ์ƒ‰์ด ์„ฑ๊ณตํ•˜๋ฉด ์‚ฝ์ž…ํ•˜์ง€ ์•Š์œผ๋ฉฐ, ํƒ์ƒ‰์— ์‹คํŒจํ•˜๋ฉด ์š”์†Œ๊ฐ€ ๊ฒ€์ƒ‰์ด ์ข…๋ฃŒ๋œ ์ง€์ ์— ์‚ฝ์ž…๋œ๋‹ค.

๐Ÿ’ก ์™œ ๊ทธ ์ง€์ ์— ์‚ฝ์ž…๋˜๋Š”๊ฐ€?
ํƒ์ƒ‰์˜ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ–ˆ์œผ๋ฉด ์‰ฝ๋‹ค. ํƒ์ƒ‰ ์ค‘ ๋ฃจํŠธ๊ฐ€ NULL์œผ๋กœ ํŠธ๋ฆฌ๊ฐ€ ๋น„์–ด์žˆ๋Š” ๊ฒฝ์šฐ ํƒ์ƒ‰์— ์‹คํŒจํ•˜๊ธฐ ๋•Œ๋ฌธ{: .notice}

  • ์‹œ๊ฐ„ ๋ณต์žก๋„ O(height)
  • ex: insert key=7

    Untitled 1

    Python ๊ตฌํ˜„ : Insert Method ์žฌ๊ท€๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๋‹ค. ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•  ์›์†Œ์˜ ๊ฐ’์„ ํ˜„์žฌ ๋…ธ๋“œ์˜ ๊ฐ’๊ณผ ๋น„๊ตํ•˜์—ฌ ์™ผ์ชฝ/์˜ค๋ฅธ์ชฝ ์ค‘ ์•Œ๋งž์€ ์œ„์น˜๋กœ ๋…ธ๋“œ๋ฅผ ์˜ฎ๊ฒจ๊ฐ€๋ฉด์„œ ์‚ฝ์ž… ์œ„์น˜๋ฅผ ํ™•์ธํ•œ๋‹ค.
      class BinarySearchTree(object):
          ...
          def insert(self, data):
              self.root = self._insert_value(self.root, data)
              return self.root is not None
          def _insert_value(self, node, data):
              if node is None:
                  node = Node(data)
              else:
                  if data <= node.data:
                      node.left = self._insert_value(node.left, data)
                  else:
                      node.right = self._insert_value(node.right, data)
              return node
    


Delete(key)

์‚ญ์ œ


์š”์†Œ์˜ ์‚ญ์ œ๋Š” ์„ธ ๊ฐ€์ง€ ๊ฒฝ์šฐ๋กœ ๋‚˜๋ˆ„์–ด ์ƒ๊ฐํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  • case 1 : ์š”์†Œ๊ฐ€ leaf์— ์žˆ๋‹ค.
    • delete key=7

      Untitled 2


  • case 2 : ์š”์†Œ๊ฐ€ ์ฐจ์ˆ˜ 1์˜ ๋…ธ๋“œ์— ์žˆ๋‹ค(์ฆ‰, ๋น„์–ด ์žˆ์ง€ ์•Š์€ ์„œ๋ธŒํŠธ๋ฆฌ๊ฐ€ ํ•˜๋‚˜ ์กด์žฌ).
    • delete key=40 Untitled 3


    • delete key=15 Untitled 4


  • case 3 : ์š”์†Œ๊ฐ€ ์ฐจ์ˆ˜ 2์˜ ๋…ธ๋“œ์— ์žˆ๋‹ค (์ฆ‰, ๋น„์–ด ์žˆ์ง€ ์•Š์€ ๋‘ ๊ฐœ์˜ ์„œ๋ธŒํŠธ๋ฆฌ๊ฐ€ ์กด์žฌ).
    • ex 1) delete key=10s | Untitled 5 | |:โ€“:| |step 1|

      | Untitled 6 | |:โ€“:| |step 2. ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์—์„œ ๊ฐ€์žฅ ํฐ key(๋˜๋Š” ์˜ค๋ฅธ์ชฝ ํ•˜์œ„ ํŠธ๋ฆฌ์—์„œ ๊ฐ€์žฅ ์ž‘์€ key)๋กœ ๋Œ€์ฒด|
      | Untitled 7 | |:โ€“:| |step 3. ๊ฐ€์žฅ ํฐ key๋Š” leaf ๋˜๋Š” ์ฐจ์ˆ˜ 1์ธ ๋…ธ๋“œ์— ์žˆ์–ด์•ผ ํ•œ๋‹ค.|


    • ex 2) delete key=20

      Untitled 8
      ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์˜ ๊ฐ€์žฅ ํฐ key๊ฐ’์œผ๋กœ ๋Œ€์ฒดํ•œ๋‹ค.
  • ์™ผ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ์—์„œ key๊ฐ€ ๊ฐ€์žฅ ํฐ ๋…ธ๋“œ(+ ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒ ํŠธ๋ฆฌ์—์„œ key๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๋…ธ๋“œ)๋Š” 0 ๋˜๋Š” ๋น„์–ด ์žˆ์ง€ ์•Š์€ ์„œ๋ธŒ ํŠธ๋ฆฌ๊ฐ€ ํ•˜๋‚˜ ์žˆ๋Š” ๋…ธ๋“œ์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ’ก ๋…ธ๋“œ์˜ ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์—์„œ key๊ฐ€ ๊ฐ€์žฅ ํฐ ๋…ธ๋“œ๋ฅผ ์ฐพ๋Š” ๋ฐฉ๋ฒ•
์„œ๋ธŒ ํŠธ๋ฆฌ์˜ ๋ฃจํŠธ๋กœ ์ด๋™ํ•œ ๋‹ค์Œ ์˜ค๋ฅธ์ชฝ ์ž์‹์˜ ํฌ์ธํ„ฐ๊ฐ€ NULL์ธ ๋…ธ๋“œ์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๊ณ„์† ์˜ค๋ฅธ์ชฝ ์ž์‹ ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋ผ๊ฐ„๋‹ค.

๐Ÿ’ก ๋…ธ๋“œ์˜ ์˜ค๋ฅธ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์—์„œ key๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๋…ธ๋“œ๋ฅผ ์ฐพ๋Š” ๋ฐฉ๋ฒ•
์„œ๋ธŒ ํŠธ๋ฆฌ์˜ ๋ฃจํŠธ๋กœ ์ด๋™ํ•œ ๋‹ค์Œ ์™ผ์ชฝ ์ž์‹์˜ ํฌ์ธํ„ฐ๊ฐ€ NULL์ธ ๋…ธ๋“œ์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๊ณ„์† ์™ผ์ชฝ ์ž์‹ ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋ผ๊ฐ„๋‹ค.


  • ์‹œ๊ฐ„๋ณต์žก๋„ : O(height)
Python ๊ตฌํ˜„ : delete() method
    class BinarySearchTree(object):
        ...
        def delete(self, key):
            self.root, deleted = self._delete_value(self.root, key)
            return deleted
        def _delete_value(self, node, key):
            if node is None:
                return node, False
            deleted = False
            if key == node.data:
                deleted = True
                if node.left and node.right:
                                    # replace the node to the leftmost of node.right
                    parent, child = node, node.right
                    while child.left is not None:
                        parent, child = child, child.left
                    child.left = node.left
                    if parent != node:
                        parent.left = child.right
                        child.right = node.right
                    node = child
                elif node.left or node.right:
                    node = node.left or node.right
                else:
                    node = None
            elif key < node.data:
                node.left, deleted = self._delete_value(node.left, key)
            else:
                node.right, deleted = self._delete_value(node.right, key)
            return node, deleted


Binary Search Tree์˜ ์‹œ๊ฐ„๋ณต์žก๋„


  • ์ด์ง„ ํŠธ๋ฆฌ์˜ ์ขŒ์šฐ ๊ท ํ˜•์ด ๋งž๋Š”๋‹ค๋ฉด ํƒ์ƒ‰, ์‚ฝ์ž…, ์‚ญ์ œ์˜ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ย O(log n)
  • ๊ทธ๋Ÿฌ๋‚˜ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ๋Š” ์ •๋ ฌ๋œ ๋ฐ์ดํ„ฐ์—๋Š” ์ทจ์•ฝํ•˜๋‹ค.

    โ†’ ์˜ค๋ฆ„์ฐจ์ˆœ์ด๋“  ๋‚ด๋ฆผ์ฐจ์ˆœ์ด๋“  ์ •๋ ฌ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž…๋ ฅ๋˜๋ฉด ํŽธํ–ฅ ํŠธ๋ฆฌ(skewed tree)๊ฐ€ ์ƒ๊น€

    โ‡’ ์ตœ์•…์˜ ๊ฒฝ์šฐ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์‚ดํŽด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์–ด ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ย O(n)์ด ๋œ๋‹ค.



Indexed Binary Search Trees


-

Untitled 9

  • ๊ฐ ๋…ธ๋“œ์—๋Š” ์ถ”๊ฐ€์ ์ธ ํ•„๋“œ โ€˜LeftSizeโ€™๋ผ๋Š” ๋ณ€์ˆ˜๊ฐ€ ์žˆ์Œ
  • ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ๊ธฐ๋Šฅ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ˆœ์œ„(rank)๋ณ„ ๊ฒ€์ƒ‰ ๋ฐ ์‚ญ์ œ ์ž‘์—…์ด ๊ฐ€๋Šฅ
  • LeftSize : ์™ผ์ชฝ ์„œ๋ธŒํŠธ๋ฆฌ์˜ ์›์†Œ ์ˆ˜


LeftSize์™€ Rank

  • ์š”์†Œ์˜ rank ์ฆ‰, ์ˆœ์œ„๋Š” ์˜ค๋ฆ„์ฐจ์ˆœ ์ˆœ์„œ์— ๋”ฐ๋ฅธ ์œ„์น˜๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

    [2, 6, 7, 8, 10, 15, 18, 20, 25, 30, 35, 40]

    rank(2) = 0

    rank(15) = 5

    rank(20) = 7

    Untitled 10

  • x๋ฅผ ๋ฃจํŠธ๋…ธ๋“œ๋กœ ํ•˜๋Š” ์„œ๋ธŒํŠธ๋ฆฌ์˜ ์š”์†Œ์— ๋Œ€ํ•˜์—ฌ LeftSize(x) = rank(x)
  • indexed Binary Tree์˜ ํ™œ์šฉ

    insert(index, element)

    Untitled 11

    Untitled 12

    Untitled 13

    Untitled 14

  • ์—ฌ๋Ÿฌ ๊ฐ€๋Šฅ์„ฑ์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฃจํŠธ ๋…ธ๋“œ๋ถ€ํ„ฐ ์ƒˆ๋กœ์šด ๋…ธ๋“œ๊นŒ์ง€์˜ leftSize๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•œ๋‹ค.
  • ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(height)



Binary Search Tree with Duplicates

์ค‘๋ณต์ด ์žˆ๋Š” ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ


์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ๋ชจ๋“  ์š”์†Œ์— ๋ณ„๋„์˜ key๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ์š”๊ตฌ์‚ฌํ•ญ์„ ์ œ๊ฑฐํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

For every node x,

all keys in the left subtree of x are smaller than that in x. all keys in the right subtree of x are larger than that in x

  • โ€œsmallerโ€ โ†’ โ€œsmaller or equal toโ€๋กœ,
  • โ€œlargerโ€ โ†’ โ€œlarger or equal toโ€์œผ๋กœ ๋ฐ”๊พผ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์ด์ง„ ๊ฒ€์ƒ‰ ํŠธ๋ฆฌ๊ฐ€ ์ค‘๋ณต ํ‚ค๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.



์ฐธ๊ณ ์ž๋ฃŒ