[Data Structures] Tree
Tree
์ฉ์ด ์ค๋ช
๋ง๊ทธ๋๋ก ํธ๋ฆฌ ๋ชจ์์ด๋ค. ๋ฌผ๋ก ์ง์ง ๋๋ฌด๋ ๋ฟ๋ฆฌ๊ฐ ์๋์ ์์ง๋ง ์ด๊ฑด ์์ ์๋..ใ
- 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)
์์ ๊ฐ์ ์ฝ๋๋ฅผ ํธ์ถํ๋ฉด ํธ๋ฆฌ ๊ทธ๋ฆผ์ผ๋ก๋ ์๋์ ๊ฐ์ ๋ชจ์์ด ๋์จ๋ค.
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)
}
์๋ฐ ํธ๋ฆฌ๋ฅผ ๋ง๋ค์ด์ Depth-first traversal์ ํด๋ณด๋ฉด ์๋์ ๊ฐ์ด ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
์ค์ ๊ทธ์ด๋ณด๋ฉด ๊น์ด ์ฐ์ ์ด๊ณ , ์ผ์ชฝ ๋ ธ๋๋ถํฐ ๋ฐฉ๋ฌธํ๋ค.
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) }
}
}
์๊น์ ์์๊ฐ ๋ค๋ฅด๋ค.
์ธต๋ณ๋ก ๋ฐฉ๋ฌธํ๋ค. Head๋ถํฐ ๋ฃ์ด์ children์ ๊ณ์ enqueueํ๋ ์์ ์ ํด์ฃผ๊ธฐ ๋๋ฌธ์ ์ด๋ ๊ฒ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
Search
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