[Data Structures] Tree

Tree

์šฉ์–ด ์„ค๋ช…

๋ง๊ทธ๋Œ€๋กœ ํŠธ๋ฆฌ ๋ชจ์–‘์ด๋‹ค. ๋ฌผ๋ก  ์ง„์งœ ๋‚˜๋ฌด๋Š” ๋ฟŒ๋ฆฌ๊ฐ€ ์•„๋ž˜์— ์žˆ์ง€๋งŒ ์ด๊ฑด ์œ„์— ์žˆ๋Š”..ใ…Ž

image

  • Node: ๋งํฌ๋“œ๋ฆฌ์ŠคํŠธ์ฒ˜๋Ÿผ ํŠธ๋ฆฌ๋„ ๋…ธ๋“œ๋“ค๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค. ๋…ธ๋“œ๋“ค์€ children์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ง„๋‹ค
  • Parent, Children: ์•„๋ž˜ ๊ฐ€์ง€๋“ค์ด ๋ชจ์ด๋Š” ๋…ธ๋“œ๋ฅผ parent๋ผ๊ณ  ํ•œ๋‹ค. ์•„๋ž˜๋Š” children. child๋Š” ๋ฌด์กฐ๊ฑด ํ•˜๋‚˜์˜ ๋ถ€๋ชจ๋ฅผ ๊ฐ€์ง„๋‹ค.
  • Root: ํŠธ๋ฆฌ์˜ ๊ฐ€์žฅ ์ตœ์ƒ์œ„ ๋…ธ๋“œ๋ฅผ ๋งํ•œ๋‹ค. ์• ๋Š” parent๊ฐ€ ์—†๋‹ค.
  • Leaf: ํŠธ๋ฆฌ์˜ ๊ฐ€์žฅ ์ตœํ•˜์œ„ ๋…ธ๋“œ๋“ค์„ ๋งํ•˜๋Š”๋ฐ, ์ด๋“ค์€ children์ด ์—†๋‹ค.

Tree ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ

์šฐ์„  Tree๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” TreeNode ๋ถ€ํ„ฐ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.

TreeNode

class TreeNode<T> {
    var value: T
    var children: [TreeNode] = []
    
    init(value: T) {
        self.value = value
    }

   func add(child: TreeNode) {
        children.append(child)
    }
}

๊ฐ๊ฐ์˜ treenode๋“ค์€ ์ž์‹ ์˜ ๊ฐ’๊ณผ children์„ ์ €์žฅํ•  ๊ณต๊ฐ„์ด ํ•„์š”ํ•ด์„œ value, children์„ ์„ ์–ธํ–ˆ๋‹ค. children์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก add ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค.

let beverages = TreeNode(value: "Beverages")
let hot = TreeNode(value: "hot")
let cold = TreeNode(value: "cold")

beverages.add(child: hot)
beverages.add(child: cold)

์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํŠธ๋ฆฌ ๊ทธ๋ฆผ์œผ๋กœ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋ชจ์–‘์ด ๋‚˜์˜จ๋‹ค. image

Traversal Algorithms

ํŠธ๋ฆฌ๋ฅผ ์ˆœํšŒํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค. ๊นŠ๊ฒŒ ๋จผ์ € ๋“ค์–ด๊ฐ€๋Š” ๊ฒŒ ์žˆ๊ธฐ๋„ ํ•˜๊ณ  ์ธต๋ณ„๋กœ ๋ฐฉ๋ฌธํ•ด๋ณด๋Š” ๊ฒƒ๋„ ์žˆ๊ณ , ๋ฃจํŠธ๋ฅผ ์–ด๋Š ์ˆœ์„œ์— ๋ฐฉ๋ฌธํ• ๊ฑด์ง€์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๊ธฐ๋„ ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๊นŠ๊ฒŒ ๋จผ์ € ๋“ค์–ด๊ฐ€๋Š” Depth-first ์™€ ์ธต๋ณ„๋กœ ๋ฐฉ๋ฌธํ•˜๋Š” Level-order ์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

Depth-first traversal

TreeNode์— ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋„ฃ๋Š”๋‹ค.

    func forEachDepthFirst(visit: (TreeNode) -> Void) {
        visit(self)
        children.forEach { $0.forEachDepthFirst(visit: visit) }
    }

forEach ๋‚ด๋ถ€์—์„œ forEachDepthFirst๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋œ๋‹ค. ์žฌ๊ท€ํ•จ์ˆ˜.. ์œผ ์žฌ๊ท€ํ•จ์ˆ˜..

์‹ค์ œ๋กœ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š”์ง€ ์‹คํ–‰ํ•ด๋ณด์ž.

func makeBeverageTree() -> TreeNode<String> {
  let tree = TreeNode("Beverages")

  let hot = TreeNode("hot")
  let cold = TreeNode("cold")

  let tea = TreeNode("tea")
  let coffee = TreeNode("coffee")
  let chocolate = TreeNode("cocoa")

  let blackTea = TreeNode("black")
  let greenTea = TreeNode("green")
  let chaiTea = TreeNode("chai")

  let soda = TreeNode("soda")
  let milk = TreeNode("milk")

  let gingerAle = TreeNode("ginger ale")
  let bitterLemon = TreeNode("bitter lemon")

  tree.add(hot)
  tree.add(cold)

  hot.add(tea)
  hot.add(coffee)
  hot.add(chocolate)

  cold.add(soda)
  cold.add(milk)

  tea.add(blackTea)
  tea.add(greenTea)
  tea.add(chaiTea)

  soda.add(gingerAle)
  soda.add(bitterLemon)

  return tree
}

let tree = makeBeverageTree()
tree.forEachDepthFirst { treeNode in
    print(treeNode.value)
}

image

์š”๋Ÿฐ ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ Depth-first traversal์„ ํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค.

image

์ค„์„ ๊ทธ์–ด๋ณด๋ฉด ๊นŠ์ด ์šฐ์„ ์ด๊ณ , ์™ผ์ชฝ ๋…ธ๋“œ๋ถ€ํ„ฐ ๋ฐฉ๋ฌธํ–ˆ๋‹ค. image

Level-order traversal

๊ฐ™์€ ์ธต๋ถ€ํ„ฐ ๋ฐฉ๋ฌธํ•˜๋Š” level-order.

func forEachLevelOrder(visit: (TreeNode) -> Void) {
        visit(self)
        var queue = QueueStack<TreeNode>()
        children.forEach { queue.enqueue($0) }
        
        while let node = queue.dequeue() {
            visit(node)
            node.children.forEach { queue.enqueue($0) }
        }
    }

image

์•„๊นŒ์™€ ์ˆœ์„œ๊ฐ€ ๋‹ค๋ฅด๋‹ค.

image ์ธต๋ณ„๋กœ ๋ฐฉ๋ฌธํ•œ๋‹ค. Head๋ถ€ํ„ฐ ๋„ฃ์–ด์„œ children์„ ๊ณ„์† enqueueํ•˜๋Š” ์ž‘์—…์„ ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ ‡๊ฒŒ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค.

extension TreeNode where T: Equatable {
  func search(_ value: T) -> TreeNode? {
    var result: TreeNode?
    forEachLevelOrder { node in
      if node.value == value {
        result = node
      }
    }
    return result
  }
}

level order๋กœ ๋…ธ๋“œ๋ฅผ ํ•˜๋‚˜์”ฉ ๋ฐฉ๋ฌธํ•ด ์›ํ•˜๋Š” value๊ฐ€ ๋‚˜ํƒ€๋‚  ๋•Œ ๊นŒ์ง€ ์ฐพ์•„๋ณด๋Š” ์ฝ”๋“œ.

Leave a comment