
트리의 재귀적 구조를 이해하자!

1. 트리의 루트: A
2. A의 Degree: 3
3. Leaf: K, L, F, G, M, I, J
4. D의 Parent: A
5. D의 Children: H, I, J
6. H의 Siblings: I, J
7. 트리의 depth: 4
8. 노드 M의 ancestors: H, D, A
9. 노드 D의 descendants: H, I, J, M
트리에서 children의 순서는 중요하지 않기 때문에 특정 노드의 어떤 children이더라도 leftmost할 수 있다!


i에서 최대 개 노드를 가진다.k인 이진 트리는 최대 개 노드를 가진다.k인 이진 트리의 노드 개수가 개인 이진 트리
n개가 depth가 k인 정 이진 트리 안에서 노드 n번까지 상응하는 이진 트리
i를 통해 찾을 수 있음 → i/2, 2i, 2i+1 세 가지 방식을 통해 표현 (루트 노드는 parent가 없는 예외 존재)

import Foundation
let mockTree = ["nil", "A", "B", "C", "D", "E", "F", "G", "H", "I"]
func inorderTraverse(idx: Int) {
if idx * 2 < mockTree.count {
inorderTraverse(idx: idx * 2)
}
print(mockTree[idx], terminator: " ")
if idx * 2 + 1 < mockTree.count {
inorderTraverse(idx: idx * 2 + 1)
}
}
inorderTraverse(idx: 1)
// H D I B E A F C G
let mockTree = ["nil", "A", "B", "C", "D", "E", "F", "G", "H", "I"]
func preorderTraverse(idx: Int) {
print(mockTree[idx], terminator: " ")
if idx * 2 < mockTree.count {
preorderTraverse(idx: idx * 2)
}
if idx * 2 + 1 < mockTree.count {
preorderTraverse(idx: idx * 2 + 1)
}
}
preorderTraverse(idx: 1)
// A B D H I E C F G
import Foundation
let mockTree = ["nil", "A", "B", "C", "D", "E", "F", "G", "H", "I"]
func postorderTraverse(idx: Int) {
if idx * 2 < mockTree.count {
postorderTraverse(idx: idx * 2)
}
if idx * 2 + 1 < mockTree.count {
postorderTraverse(idx: idx * 2 + 1)
}
print(mockTree[idx], terminator: " ")
}
postorderTraverse(idx: 1)
// H I D E B F G C A

leftThread, rightThread라는 두 개의 추가적인 프로퍼티 필요

dangling thread pointer): 새로운 루트 노드를 만들어서 기존 이진 트리와 연결 가능. 기존 이진 트리의 루트 노드는 새롭게 생긴 노드의 왼쪽 서브 트리로 연결됨rightThread가 참이라면 중위 순회의 successor는 우측 자식. 그렇지 않다면 노드에 연결된 자식 노드의 좌측 자식을 향해 leftThread가 참일 때까지 탐색.


우선순위 큐를 구현하기 위해서는
heap이라는 자료구조가 필요하다!
- 최대 트리: 각 노드의 키 값이 자식 노드의 키 값보다 큰 트리
- 최대 힙: 최대 트리이자 동시에 완전 이진 트리인 경우
- 최소 트리: 최대 트리의 최소 버전
- 최소 힙: 최소 트리이자 동시에 완전 이진 트리인 경우
완전 이진 트리이기 때문에 배열을 통해 효율적으로 표현 가능
import Foundation
struct Heap<T> {
var nodes = [T]()
let sort: (T, T) -> Bool
init(sort: @escaping(T, T) -> Bool) {
self.sort = sort
}
var isEmpty: Bool {
return nodes.isEmpty
}
var count: Int {
return nodes.count
}
func peek() -> T? {
return nodes.first
}
func leftChild(from parentIndex: Int) -> Int {
return parentIndex * 2 + 1
}
func rightChild(from parentIndex: Int) -> Int {
return parentIndex * 2 + 2
}
func parentIndex(from childIndex: Int) -> Int {
return (childIndex - 1) / 2
}
mutating func push(_ element: T) {
nodes.append(element)
siftUp(from: count-1)
}
mutating func siftUp(from index: Int) {
var child = index
var parent = parentIndex(from: child)
while child > 0 && sort(nodes[child], nodes[parent]) {
nodes.swapAt(child, parent)
child = parent
parent = parentIndex(from: child)
}
}
mutating func pop() -> T? {
guard !isEmpty else { return nil }
nodes.swapAt(0, count-1)
defer {
siftDown(from: 0)
}
return nodes.removeLast()
}
mutating func siftDown(from index: Int) {
var parent = index
while true {
let left = leftChild(from: parent)
let right = rightChild(from: parent)
var candidate = parent
if left < count && sort(nodes[left], nodes[candidate]) {
candidate = left
}
if right < count && sort(nodes[right], nodes[candidate]) {
candidate = right
}
if parent == candidate {
return
}
nodes.swapAt(parent, candidate)
parent = candidate
}
}
}
var minHeap = Heap<Int>(sort: <)
minHeap.push(1)
minHeap.push(10)
minHeap.push(100)
minHeap.push(5)
minHeap.push(4)
minHeap.push(3)
minHeap.push(2)
minHeap.push(20)
while !minHeap.isEmpty {
guard let node = minHeap.pop() else { break }
print(node, terminator: " ")
}
// 1 2 3 4 5 10 20 100



import Foundation
class Node<T> {
var data:T
var leftChild: Node?
var rightChild: Node?
init(data: T, leftChild: Node? = nil, rightChild: Node? = nil) {
self.data = data
self.leftChild = leftChild
self.rightChild = rightChild
}
}
struct BST<T> where T : Comparable {
var root: Node<T>?
}
func searchIterative(_ element: T) -> T? {
var root = self.root
while root != nil {
if root!.data == element {
return element
} else if root!.data > element {
root = root!.leftChild
} else {
root = root!.rightChild
}
}
return nil
}
func searchRecursive(_ root: Node<T>?, _ element: T) -> T? {
if root != nil {
if root!.data == element {
return element
} else if root!.data > element {
return searchRecursive(root!.leftChild, element)
} else {
return searchRecursive(root!.rightChild, element)
}
}
return nil
}
func inorderTraverse(_ root: Node<T>?) {
if root != nil {
inorderTraverse(root?.leftChild)
print(root!.data)
inorderTraverse(root?.rightChild)
}
}
func preorderTraverse(_ root: Node<T>?) {
if root != nil {
print(root!.data)
preorderTraverse(root?.leftChild)
preorderTraverse(root?.rightChild)
}
}
func postorderTraverse(_ root: Node<T>?) {
if root != nil {
postorderTraverse(root?.leftChild)
postorderTraverse(root?.rightChild)
print(root!.data)
}
}
mutating func insert(_ element: T) {
let node = Node(data: element)
if let root = root {
insert(root, node)
} else {
self.root = node
}
}
func insert(_ root: Node<T>, _ node: Node<T>) {
if root.data > node.data {
if let leftChild = root.leftChild {
insert(leftChild, node)
} else {
root.leftChild = node
}
} else {
if let rightChild = root.rightChild {
insert(rightChild, node)
} else {
root.rightChild = node
}
}
}


mutating func delete(_ element: T) {
root = delete(root, element)
}
func delete(_ root: Node<T>?, _ element: T) -> Node<T>? {
guard let root = root else { return nil }
if root.data == element {
if root.leftChild == nil && root.rightChild == nil {
return nil
}
if root.leftChild == nil {
return root.rightChild
}
if root.rightChild == nil {
return root.leftChild
}
if let leftmost = getLeftmost(root.rightChild) {
root.data = leftmost.data
}
// min 값
root.rightChild = delete(root.rightChild, root.data)
} else if element < root.data {
root.leftChild = delete(root.leftChild, element)
} else {
root.rightChild = delete(root.rightChild, element)
}
return root
}
func getLeftmost(_ root: Node<T>?) -> Node<T>? {
var root = root
while root?.leftChild != nil {
root = root?.leftChild
}
return root
}
k 키 값을 기준으로 small, mid, big 세 가지로 구성 가능k개의 정렬된 시퀀스, runs가 하나의 정렬된 시퀀스로 병합되는 경우run: 여러 개의 레코드로 구성, key 데이터를 기준으로 오름차순 구성k 개의 runs 안에 각각 n개의 레코드 존재
runs 큐에서 pop되는 노드들이 가장 하단부 8개 노드에 입력, 각각 비교를 통해 부모 노드의 값이 결정, 마지막 루트 노드 값이 정해질 때까지 결정됨

import Foundation
struct DisjointTree {
private var nodes = Array(repeating: -1, count: 100)
// 100개 사이즈 할당
private var setPointers = Set<Int>()
mutating func makeSet(setLabel: Int) {
nodes[setLabel] = setLabel
setPointers.insert(setLabel)
}
mutating func insertSet(setLabel: Int, elements: [Int]) {
if setPointers.contains(setLabel) {
for element in elements {
nodes[element] = setLabel
}
}
}
mutating func unionSet(setLabel1: Int, setLabel2: Int) {
if setPointers.contains(setLabel1) && setPointers.contains(setLabel2) {
nodes[setLabel2] = setLabel1
}
}
func getSet(setLabel: Int) {
if setPointers.contains(setLabel) {
for item in nodes.enumerated() {
if item.element == setLabel {
print(item.offset, terminator: " ")
if item.offset != setLabel && setPointers.contains(item.offset) {
getSet(setLabel: item.offset)
}
}
}
}
}
}
var disjointTree = DisjointTree()
disjointTree.makeSet(setLabel: 1)
disjointTree.makeSet(setLabel: 2)
disjointTree.insertSet(setLabel: 1, elements: [3, 4, 5, 6, 7, 8])
disjointTree.insertSet(setLabel: 2, elements: [9, 11, 13, 15])
disjointTree.getSet(setLabel: 1)
// 1 3 4 5 6 7 8
disjointTree.getSet(setLabel: 2)
// 2 9 11 13 15
disjointTree.unionSet(setLabel1: 1, setLabel2: 2)
disjointTree.getSet(setLabel: 1)
// 1 2 9 11 13 15 3 4 5 6 7 8