그래프

개요

오일러 경로

모든 간선(edge)을 한 번씩 방문하는 유한 그래프(Finite Graph).

Königsberg_bridge_graph

해밀턴 경로

각 정점을 한 번씩 방문하는 무향 또는 유향 그래프 경로.

그래프 순회

그래프 탐색(Search). 그래프의 각 정점을 방문하는 과정.

그래프 표현 방식

인접 행렬(Adjacency Matrix)

graph = {
       1  2  3  4  5  6  7
    1:[0, 1, 1, 1, 0, 0, 0],
    2:[0, 0, 0, 0, 1, 0, 0]
    3:[0, 0, 0, 0, 1, 0, 0]
    4:[0, 0, 0, 0, 0, 0, 0]
    5:[0, 0, 0, 0, 0, 1, 1]
    6:[0, 0, 0, 0, 0, 0, 0]
    7:[0, 0, 1, 0, 0, 0, 0]
}

인접 리스트(Adjacency List)

graph = {
    1: [2, 3, 4],
    2: [5],
    3: [5],
    4: [],
    5: [6, 7],
    6: [],
    7: [3],
}

DFS - 재귀

DFS(G, v)
    # v(vertex, 정점)에 방문 표시
    label v as discovered ''' 1. 방문 표시 '''
    # 정점 v에서 v와 인접한 정점 w로 이어지는 모든 방향 있는(directed) 간선에 대해 
    for all directed edges from v to w that are in G.adjacentEdges(v) do
        # w에 방문 표시(label)가 없다면
        if vertex w is not labeled as discovered then
            # 정점 w에 대한 재귀 호출
            recursively call DFS(G, w)
def recursive_dfs(v, discovered = []):
    discovered.append(v) ''' 1. 방문 표시 '''
    for w in graph[v]:
        if not w in discovered:
            discovered = recursive_dfs(w, discovered)
    return discovered

DFS - 반복(스택)

DFS-iterative(G, v)
    # 스택 생성
    let S be a stack
    # 스택에 최초 미방문 정점 삽입
    S.push(v)
    while S is not empty do
        v = S.pop()
        # 현재 정점 v가 방문 표시 되지 않았다면
        if v is not labeled as discovered then
            # 현재 정점 v에 방문 표시 하고
            label v as discovered ''' 1. 방문 표시 '''
            # 정점 v에서 v와 인접한 정점 w로 이어지는 모든 간선 대해 
            for all edges from v to w in G.adjacentEdges(v) do
                # 방문 체크 위해 스택에 삽입
                S.push(w)
def iterative_dfs(start_v):
    discovered = []
    stack = [start_v]
    while stack:
        v = stack.pop()
        if v not in discovered:
            discovered.append(v) ''' 1. 방문 표시 '''
            for w in graph[v]:
                stack.append(w)
    return discovered

BFS - 반복(큐)

BFS(G, start_v)
    # Q를 큐로 선언
    let Q be a queue
    # start_v 방문 표시
    label start_v as discovered  ''' 1. 방문 표시 '''
    # Q에 삽입(선입선출)
    Q.enqueue(start_v)
    while Q is not empty do
        v := Q.dequeue()
        # v가 목적지인 경우 v 리턴
        if v is the goal then
            return v
        # v가 목적지가 아닌 경우, 노드 v에서 v에 인접한 노드 w의 모든 간선에 대하여 반복
        for all edges from v to w in G.adjacentEdges(v) do
            # 노드 w를 방문한 적 없다면
            if w is not labeled as discovered then
                # 노트 w 방문 표시
                label w as discovered ''' 2. 방문 표시 '''
                # w의 부모 노드를 v로 붙이고
                w.parent := v
                # w를 큐에 삽입하여 다음 반복문에서 목적지인지 검증한다
                Q.enqueue(w)

def iterative_bfs(start_v):
    discovered = [start_v]  ''' 1. 방문 표시 '''
    queue = [start_v]
    while queue:
        v = queue.pop(0)
        for w in graph[v]:
            if not w in discovered:
                discovered.append(w) ''' 2. 방문 표시 '''
                queue.append(w)
    return discovered

BFS - 재귀

백트래킹

해결책에 대한 후보를 구축해 나아가다 가능성 없다고 판단되는 즉시 후보를 포기(backtrack)해 정답을 찾아가는 범용적인 알고리즘

제약 충족 문제(Constraint Satisfaction Problems, CSP)

수많은 제약 조건(constraints)을 충족하는 상태(states)를 찾아내는 수학 문제를 일컫는다

용어

정점

간선

차수

참고 링크