BFS는 시작 정점에서 가장 가까운 정점부터 차례대로 모든 정점을 방문합니다. 이 과정에서 각 정점은 "Level"이라고 하는 개념으로 분류할 수 있으며, 이는 시작 정점으로부터의 거리에 해당합니다.
BFS는 최단 경로를 찾는 데 자주 사용됩니다. 예를 들어, 미로 찾기, 최단 경로 문제 등에서 활용됩니다. BFS를 사용하면 시작 정점으로부터 각 정점까지의 최단 경로를 찾을 수 있습니다.
BFS는 그래프 내의 사이클을 탐지하는 데에도 사용될 수 있습니다. 그래프 탐색 중에 이미 방문한 정점을 다시 방문하게 되면 사이클이 존재한다고 볼 수 있습니다.
BFS는 레벨별 탐색 특성을 이용하여 여러 응용 프로그램에서 사용됩니다. 예를 들어, 소셜 네트워크에서 사용자 간의 연결 단계를 찾는 데 사용될 수 있습니다.
struct QueueStack<T> {
var leftStack: [T] = []
var rightStack: [T] = []
public init() { }
public var isEmpty:Bool {
leftStack.isEmpty && rightStack.isEmpty
}
public var peek: T? {
!leftStack.isEmpty ? leftStack.last : rightStack.first
}
public mutating func enqueue(_ element: T) {
rightStack.append(element)
}
public mutating func dequeue() -> T? {
if leftStack.isEmpty {
leftStack = rightStack.reversed()
rightStack.removeAll()
}
return leftStack.popLast()
}
}
extension Graph where Element: Hashable {
func breadthFirstSearch(from source: Vertex<Element>) -> [Vertex<Element>] {
var queue = QueueStack<Vertex<Element>>()
var enqueued: Set<Vertex<Element>> = []
var visited: [Vertex<Element>] = []
queue.enqueue(source)
enqueued.insert(source)
while let vertex = queue.dequeue() {
visited.append(vertex)
let neighborEdges = edges(from: vertex)
neighborEdges.forEach { edge in
if !enqueued.contains(edge.destination) {
queue.enqueue(edge.destination)
enqueue.insert(edge.destination)
}
}
}
return visited
}
}
Set
을 사용하면 이미 큐에 추가된 정점을 효율적으로 관리하고 중복을 방지할 수 있습니다. Set
의 검색 시간 복잡도는 O(1) 입니다. 따라서 큐에 정점을 추가하기 전에 해당 정점이 이미 추가되었는지 빠르게 확인할 수 있습니다. Set
을 사용하면 전체적인 BFS 알고리즘의 효율성이 향상됩니다. 특히 정점의 수가 많은 그래프에서 성능 차이가 두드러집니다. func noSetBFS(from source: Vertex<Element>) -> [Vertex<Element>] {
var queue = QueueStack<Vertex<Element>>()
var visited: [Vertex<Element>] = []
queue.enqueue(source)
visited.append(source)
while let vertex = queue.dequeue() {
let neighborEdges = edges(from: vertex)
neighborEdges.forEach { edge in
if !visited.contains(edge.destination) {
queue.enqueue(edge.destination)
visited.append(edge.destination)
}
}
}
return visited
}
print(graph2.breadthFirstSearch(from: tokyo2))
print(graph2.noSetBFS(from: tokyo2))
[1: Tokyo, 3: Detroit, 5: Washington DC, 6: Austin Texas, 7: Seattle, 4: San Francisco]
[1: Tokyo, 3: Detroit, 5: Washington DC, 6: Austin Texas, 7: Seattle, 4: San Francisco]
Set
을 활용한 BFS let testGraph = [
[],
[2,3,8],
[1,7],
[1,4,5],
[3,5],
[3,4],
[7],
[2,6,8],
[1,7]
]
var visited: [Int] = []
func bfs(_ graph: [[Int]], _ start: Int) {
var queue = QueueStack<Int>()
var enqueued: Set<Int> = []
queue.enqueue(start)
enqueued.insert(start)
while let value = queue.dequeue() {
visited.append(value)
for i in graph[value] {
if !enqueued.contains(i) {
queue.enqueue(i)
enqueued.insert(i)
}
}
}
}
bfs(testGraph, 1)
[1, 2, 3, 8, 7, 4, 5, 6]
print(visited)
Set
을 사용하지 않고 visited
배열만을 활용한 bfs
let testGraph = [
[],
[2,3,8],
[1,7],
[1,4,5],
[3,5],
[3,4],
[7],
[2,6,8],
[1,7]
]
var visited = [Bool](repeating: false, count: testGraph.count)
func bfs(_ graph: [[Int]], _ start: Int) {
var queue = QueueStack<Int>()
queue.enqueue(start)
visited[start] = true
while let value = queue.dequeue() {
print(value, terminator: " ")
for i in graph[value] {
if !visited[i] {
queue.enqueue(i)
visited[i] = true
}
}
}
}
bfs(testGraph, 1)
[1, 2, 3, 8, 7, 4, 5, 6]
제가 학습한 내용을 요약하여 정리한 것입니다. 내용에 오류가 있을 수 있으며, 어떠한 피드백도 감사히 받겠습니다.
감사합니다.