Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

These are algorithm courses materials., Lecture notes of Algorithms and Programming

These are algorithm courses materials.

Typology: Lecture notes

2017/2018

Uploaded on 10/23/2018

keehwan
keehwan 🇨🇦

20 documents

1 / 19

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
- 159 -
제12장 그래프
장에서는 그래프라는 자료구조에 대해 살펴본다.
12.1. 교육목표
장의 교육목표는 다음과 같다.
교육목표
개요
그래프는 트리를 포함하고 있는 보다 개념의 자료구조로서,
와또다른노드간에여러경가존할수있, 간선의
방향이 존재할 있다.
비가중치 그래프
그래프 탐색: 너비 우선, 깊이 우선
신장 트리
가중치 그래프
최단 경로 알고리즘
12.2. 그래프
그래프
그래프
그래프(graph): 공집합이 아닌 정점
정점(vertex)들의 유한 집합과
정점들을 연결하는 간선
간선(edge)으로 구성되는 자료구조
수학적 정의: 그래프 GG = (V, E) 정의되며, 여기서
V(G): 공집합이 아닌 정점들의 유한집합
E(G): 간선들의 집합
무방향
무방향 그래프
그래프(undirected graph): 간선의 방향성이 없는 그래프
유방향
유방향 그래프
그래프(directed graph, digraph): 간선의 방향성이 있는
그래프
방향 그래프에서는 간선을 아크
아크(arc)라고도 한다.
인접
인접 정점
정점(adjacent vertex): 간선에 의해 연결되어 있는 정점
경로
경로(path): 개의 정점을 연결하는 일련의 정점들
정점 a에서 b까지의 경로 a, v1, v2, …, vn, b 존재하기 위해서는
간선 (a, v1), (v1, v2), …, (vn-1, vn), (vn, b) 존재해야 한다.
공집합이 아닌 정점(vertex)들의 유한집한과 정점들을 연결하는 간선(edge)으로 구성되는
자료구조를 그래프(graph) 한다. 따라서 10, 11장에서 살펴본 트리 구조는 그래프에
한다. , 트리는 그래프의 특수한 형태이다. 그래프는 간선의 방향성이 있는지에 따라 무방
(undirected) 또는 유방향(directed) 그래프로 나뉘어 진다. 방향성이 있는 간선을 다른
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13

Partial preview of the text

Download These are algorithm courses materials. and more Lecture notes Algorithms and Programming in PDF only on Docsity!

그래프그래프 (graph): 공집합이 아닌 정점정점 (vertex) 들의 유한 집합과

이 정점들을 연결하는 간선간선 (edge) 으로 구성되는 자료구조

수학적 정의 : 그래프 G 는 G = ( V , E ) 로 정의되며 , 여기서

V ( G ): 공집합이 아닌 정점들의 유한집합

E ( G ): 간선들의 집합

무방향무방향 그래프그래프 (undirected graph):^ 간선의 방향성이 없는 그래프

유방향유방향 그래프그래프 (directed graph, digraph): 간선의 방향성이 있는

방향 그래프에서는 간선을 아크아크 (arc) 라고도 한다.

인접인접 정점정점 (adjacent vertex):^ 간선에 의해 연결되어 있는 정점

경로경로 (path): 두 개의 정점을 연결하는 일련의 정점들

정점 a 에서 b 까지의 경로 a , v 1 , v 2 , …, vn , b 가 존재하기 위해서는

간선 ( a , v 1 ), ( v 1 , v 2 ), …, ( v n -1 , vn ), ( vn , b ) 가 존재해야 한다.

공집합이 아닌 정점(vertex)들의 유한집한과 이 정점들을 연결하는 간선(edge)으로 구성되는

자료구조를 그래프(graph)라 한다. 따라서 10 장, 11장에서 살펴본 트리 구조는 그래프에 속

향(undirected) 또는 유방향(directed) 그래프로 나뉘어 진다. 방향성이 있는 간선을 다른 말

로 아크(arc)라 한다. 인접정점(adjacent vertex)이란 간선에 의해 연결되는 정점을 말하며,

경로(path)란 두 개의 정점을 연결하는 일련의 정점들을 말한다.

M

E

L

B

A

A

B D

C

V(G1)={A,B,C,D}

E(G1)={(A,B),(A,D),(B,C),(C,D)}

V(G1)= {A,B,E,L,M}

E(G1)= {(A,E),(B,L),(E,A)

(L,L),(L,A),(M,B),(M,E)}

Path(M,A): M, B, L, A

  • 길이: 3

주기주기(cycle):^ 첫 번째 정점과 마지막 정점이 같은 경로

진입진입 차수차수(indegree)와 진출진출 차수차수(outdegree)로 나누어 고려된다.

이 슬라이드에 있는 무방향 그래프에서 A의 인접정점은 B와 D이다. 경로의 길이란 경로를

구성하는 간선의 수를 말한다. 경로 중 첫 번째 정점과 끝 정점이 같으면 주기(cycle)라 한

다. 위 슬라이드에 있는 무방향 그래프에서 (A, B), (B, C), (C, D), (D, A)는 주기이며, 이

경로의 길이는 4 이다. 경로의 차수(degree)란 정점에 연결된 간선의 수를 말하며, 유방향 그

서 A의 차수는 2 이고, 유방향 그래프에서 A의 진출차수는 1 이고, 진입차수는 2 이다.

(complete directed graph)

완전완전 그래프그래프(complete graph): 최대 수의 간선을 가진 그래프

N 개의 정점이 있으면 유방향은 N ( N -1) 개 , 무방향은 N ( N -1)/2 개의

(complete undirected graph)

완전 그래프(complete graph)란 최대 수의 간선을 가진 그래프를 말한다. 즉, 모든 정점은

에서는 총^     개의 간선이 존재한다.

A

B D

C

M

E

L

B A A B C D

B D

A C

B D

A C

A

B

E

L

E

L

A

A L

M B E

  • 역인접 리스트 유지

Graph ADT

<> Graph

MatrixGraph ListGraph

WeightedMatrixGraph UnweightedMatrixGraph WeightedListGraph UnweightedListGraph

DirectedWeightedMatrixGraph

UndirectedUnweightedMatrixGraph

UndirectedUnweightedListGraph

그래프는 크게 인접 행렬 또는 인접 리스트를 이용하는 구현할 수 있다. 따라서 Graph라는

MatrixGraph와 인접 리스트를 이용하는 구현 방식을 위한 추상 클래스를 ListGraph를 정의

한다. 그 다음에 그래프가 가중치, 비가중치 그래프인지에 따라 ListGraph는 다시 그것의 자

식 추상클래스인 WeightedListGraph, UnweightedListGraph를 정의하고, MatrixGraph는

WeightedMatrixGraph, UnweightedMatrixGraph를 정의한다.

Graph ADT

import java.util.Iterator;

interface Graph{ int DEF_CAPACITY = 10; int DFS = 1; // 탐색 방법을 지정하기 위한 상수 int BFS = 2; // 탐색 방법을 지정하기 위한 상수 boolean isEmpty(); boolean isFull(); void clear(); void insertVertex(String label) throws GraphOverflowException; void removeVertex(String label) throws GraphUnderflowException; void removeEdge(String from, String to) throws GraphUnderflowException; // 비가중치 그래프 // void insertEdge(String from, String to); // 가중치 그래프 // void insertEdge(String from, String to, int weight); Iterator iterator(int type, String start); }

public abstract ListGraph implements Graph{ protected class Vertex{ public String label; public SortedLinkedList edges; } protected class GraphIterator implements Iterator{ … } protected Vertex[] graph; protected int size = 0; // 정점의 개수 public ListGraph(){ setup(DEF_CAPACITY); } public ListGraph(int capacity){ if(capcity>0) setup(capacity); else setup(DEF_CAPACITY); } private void setup(int capacity){ … } public boolean isEmpty(){ return (size == 0); } public boolean isFull(){ return (size == graph.length); } public void clear() { … } protected int index(String label){ … } // 정점의 색인 찾기 public void insertVertex(String label) throws GraphOverflowException { … } public abstract void removeVertex(String label) throws GraphUnderflowException; public abstract void removeEdge(String from, String to) throws GraphUnderflowException; public boolean search(int type, String from, String to) throws GraphUnderflowException { … } public Iterator iterator(int type, String start) throws GraphUnderflowException { … } }

는 가선의 가중치, 방향성에 따라 다르기 때문에 이 슬라이드에 정의된 ListGraph 클래스에

Insert Vertex

public void insertVertex(String label) throws GraphOverflowException{ if(label==null) throw new NullPointerException(“…”); if(isFull()) throw new GraphOverflowException(“…"); Vertex v = new Vertex(); v.label = label; v.edges = new SortedLinkedList(); graph[size] = v; size++; } // ListGraph: insertVertex

protected int index(String label){ for(int i=0; i<size; i++){ if(label.equals(graph[i].label)) return i; } return -1; } // ListGraph: index 정점들은 배열을 이용한 비정렬 방식으로 유지

에는 그 정점에 관한 정보가 저장되어 있는 배열의 위치를 알아내기 위해 index라는 내부

Insert Edge

public void insertEdge(String from, String to) throws GraphUnderflowException{ if(from==null||to==null) throw new NullPointerException(“…”); if(isEmpty()) throw new GraphUnderflowException(“…”); int v1 = index(from); int v2 = index(to); // v1 정점이 존재하지 않는 경우 if(v1==-1) throw new GraphUnderflowException(“…”); // v2 정점이 존재하지 않는 경우 if(v2==-1) throw new GraphUnderflowException(“…”); graph[v1].edges.insert(graph[v2].label); graph[v2].edges.insert(graph[v1].label); } // UndirectedUnweightedListGraph: insertEdge

무방향 그래프이므로 A에서 B를 잇는 간선을 추가할 경우에는 B에서 A를 잇는 간선도 함

Remove Vertex

public void removeVertex(String label) throws GraphUnderflowException{ if(label==null) throw new NullPointerException(“…”); if(isEmpty()) throw new GraphUnderflowException(“…”); int v = index(label); // 제거하고자 하는 정점이 존재하지 않는 경우 if(v == -1) throw new GraphUnderflowException(“…”); graph[v] = graph[size-1]; size--; for(int i=0;i<size;i++){ if(!graph[i].edges.isEmpty()) graph[i].edges.delete(label); } } // UndirectedUnweightedListGraph: RemoveVertex

Remove Edge

public void removeEdge(String from, String to) throws GraphUnderflowException{ if(isEmpty()) throw new GraphUnderflowException(“…”); if(from==null||to==null) throw new NullPointerException(“…”); int v1 = index(from); int v2 = index(to); // v1 정점이 존재하지 않는 경우 if(v1==-1) throw new GraphUnderflowException(“…”); // v2 정점이 존재하지 않는 경우 if(v2==-1) throw new GraphUnderflowException(“…”); // v1에서 v2를 잇는 간선이 존재하지 않는 경우 if(!graph[v1].edges.delete(graph[v2].label)) throw new GraphUnderflowException(“…”); graph[v2].edges.delete(graph[v1].label); } // UndirectedUnweightedListGraph: RemoveEdge

무방향 그래프이므로 양쪽 인접리스트에 모두 제거해야 함.

A에서 B를 잇는 간선을 제거하고자 할 경우에는 A 정점과 B 정점이 존재해야 할 뿐만 아

니라 A에서 B를 잇는 간선이 실제 존재해야 한다. 또한 무방향 그래프이므로 A에서 B를 잇

는 간선을 제거할 때 B에서 A를 잇는 간선 정보 역시 함께 제거해야 한다.

한다. 따라서 큐에 B와 C가 차례대로 enqueue된다. 한 정점의 인접 정점들을 큐에

enqueue를 한 다음에는 바로 정점을 하나 dequeue한다. B가 큐 front에 있으므로 이 정점

의 인접 정점을 큐에 enqueue한다. 따라서 큐에 E가 enqueue된다. 현재 큐에 있는 정점은

큐 front부터 나열하면 C, E이다. 이런 방법으로 순회하면 그 결과는 A, B, C, E, D 순으로

UnweightedListGraph의 반복자 클래스

protected class GraphIterator implements Iterator{ LinkedQueue traverseQueue; public GraphIterator(int type, int start){ … } public boolean hasNext() { … } public Object next() { … } public void remove() { … } private void BreadthFirstSearch(int start); private void DepthFirstSearch(int start); }

public Iterator iterator(int type, String start) throws GraphUnderflowException { if(start==null) throw new NullPointerException(“…”); int v = index(start); if(v==-1) throw new GraphUnderflowException(“…”); if(type==Graph.BFS||type==Graph.DFS) return new GraphIterator(type, v); else throw new GraphUnderflowException(“…”); }

public GraphIterator(int type, int start){ traverseQueue = new LinkedQueue(); if(type==Graph.BFS) BreadthFirstSearch(start); else DepthFirstSearch(start); }

는 두 가지 방법으로 순회할 수 있도록 해야 한다. 여기서 traverseQueue는 각 순회 방법을

따라서 BreadthFirstSearch와 DepthFirstSearch 메소드 내에서는 traverseQueue 외에 각각

연결연결 그래프그래프(connected graph): 무방향 그래프에서 서로 다른 모든

DFS, BFS를 이용하여 연결 여부를 확인할 수 있다.

DFS( G , i ): i 노드로부터 시작하여 방문한 모든 정점

이 때 G = DFS( G , i )이면 연결 그래프

연결 그래프(connected graph)란 무방향 그래프에서 서로 다른 모든 쌍의 정점들 사이에 경

Spanning Tree

부분부분 그래프그래프(subgraph): 다음이 성립하면 G' ( V' , E' ) 는 G ( V , E ) 의

V' ⊆ V , E' ⊆ E

신장신장 트리트리(spanning tree):^ G 의 부분 그래프 중^ G 의 모든 정점들을

A

C

E

B

D

A

C

E

B

D

A

C

E

B

D

A

C B

D

부분 그래프(subgraph)란 원 그래프의 정점 집합 중에 부분집합을 취하고, 원 그래프에서

분 그래프라 한다. 신장 트리(spanning tree)란 원 그래프의 부분 그래프 중 원 그래프의 모

최소최소 신장신장 트리트리(minimum spanning tree): 최소의 간선 수로

그래프의 정점 수가 N 이면 최소 신장 트리의 간선 수는 N -1 이다.

DFS, BFS로 만들어진 신장 트리는 최소 신장 트리가 된다.

깊이우선깊이우선 신장트리신장트리(depth first spanning tree)

너비우선너비우선 신장트리신장트리(breadth first spanning tree)

A

C

E

B

D

A

C

E

B

D

A

C

E

B

D

DFS(A)의 신장 트리 BFS(A)의 신장 트리

최소 신장 트리(minimum spanning tree)란 최소의 간선 수로 구성된 신장 트리를 말한다.

public abstract MatrixGraph implements Graph{ public static final int NULLEDGE = -1; protected class GraphIterator implements Iterator{ … } protected String[] graph; protected int size = 0; // 정점의 개수 public MatrixGraph(){ setup(DEF_CAPACITY); } public MatrixGraph(int capacity){ if(capcity>0) setup(capacity); else setup(DEF_CAPACITY); } private void setup(int capacity){ … } public boolean isEmpty(){ return (size == 0); } public boolean isFull(){ return (size == graph.length); } public void clear() { … } protected int index(String label){ … } // 정점의 색인 찾기 public void insertVertex(String label) throws GraphOverflowException { … } public abstract void removeVertex(String label) throws GraphUnderflowException; public abstract void removeEdge(String from, String to) throws GraphUnderflowException; public boolean search(int type, String from, String to) throws GraphUnderflowException { … } public Iterator iterator(int type, String start) throws GraphUnderflowException { … } }

private void setup(int capacity){ graph = new String[capacity]; adjMatrix = new int[capacity][capacity]; for(int i=0; i<capacity; i++) for(int j=0; j<capacity; j++) if(i!=j) adjMatrix[i][j] = NULLEDGE; else adjMatrix[i][j] = 0; }

이 절에서는 인접 행렬 방법을 이용하여 유방향 가중치 그래프를 구현해본다. 무방향 비가

중치 그래프를 구현할 때와 마찬가지로 정점들을 정렬하여 유지하지 않는다. 이를 위해 우

선 Graph 인터페이스를 구현한 추상 클래스 MatrixGraph를 정의한다. MatrixGraph도 앞서

살펴본 ListGraph와 마찬가지로 정점의 추가, 검색, 순회는 간선의 가중치 여부, 방향성 여

부와 무관하게 구현할 수 있다.

WeightedMatrixGraph, UnweightedMatrixGraph

public abstract class WeightedMatrixGraph extends MatrixGraph{ public WeightedMatrixGraph(){ super(); } public WeightedMatrixGraph(int capacity){ super(capacity); } public abstract void insertEdge(String from, String to, int weight); }

public abstract class UnweightedMatrixGraph extends MatrixGraph{ public WeightedMatrixGraph(){ super(); } public WeightedMatrixGraph(int capacity){ super(capacity); } public abstract void insertEdge(String from, String to); }

DirectedWeightedMatrixGraph

public class DirectedWeightedMatrixGraph implements WeightedListGraph{ public DirectedWeightedMatrixGraph(){ super(); } public DirectedWeightedMatrixGraph(int capacity){ super(capacity); } public void removeVertex(String label) throws GraphUnderflowException { … } public void removeEdge(String from, String to) throws GraphUnderflowException { … } public void insertEdge(String from, String to, int weight) throws GraphUnderflowException { … } }

Insert Vertex

public void insertVertex(String label) throws GraphOverflowException{ if(label==null) throw new NullPointerException(“…”); if(isFull()) throw new GraphOverflowException(“…”); graph[size] = label; size++; } // MatrixGraph: insertVertex

모든 간선의 가중치가 같은 유한 무방향 그래프에서 정점 s 에서

정점 t 까지 길이가 가장 짧은 경로를 찾아라.

BFS 검색을 이용하면 찾을 수 있다.

MooreMoore^ 알고리즘알고리즘:^ 정점의 수는^ n 이라 하자.

단계단계 1.1. ∀λ [ v ] = -

λ [ s ] = 0;

단계단계 2.2. l = 0;

단계단계 3.3. λ [ v ] = l 인 정점 v 와 인접한 모든 정점 u 중 λ [ u ] 가 -1 이면

λ [ u ] = l +1, 인접한 노드가 없으면 종료한다.

단계단계 4.4. λ [ t ] != -1 이면 종료한다.

단계단계 5.5. l = l +1; 단계 3 부터 반복

펴본다. 이 알고리즘은 Moore가 제안한 알고리즘으로서 너비우선 방법을 이용한다.

A

B

D

C

E

A에서 D까지

A B C D E

A B C D E

A B C D E

A B C D E

C에서 A까지

A B C D E

A B C D E

A B C D E

A B C D E

Moore의 알고리즘을 예제를 통해 설명하면 다음과 같다. 먼저 정점 개수만큼의 정수 배열

이 A이므로 A의 항 값은 0 으로 초기화되었고, A의 인접 정점인 B와 E는 1 값을 가지게 된

열 값을 2 로 바꾼다. 따라서 B의 인접 정점인 C와 D는 2 값을 가지게 된다. 이렇게 하여

모든 간선의 가중치가 양수인 유한 유방향 그래프에서 정점 s 에서

정점 t 까지 길이가 가장 짧은 경로를 찾아라.

DijkstraDijkstra 알고리즘알고리즘

정점의 수는 n 이라 하고 , 정점들의 집합을 V 라 하자.

단계단계 1.1. ∀λ [ v ] = ∞ ;

λ [s] = 0;

단계단계 2.2. T Å V

단계단계 3.3. T 중에 λ [ u ] 가 최소인 정점을 u 라 하자.

단계단계 4.4. u 가 t 이면 종료

단계단계 5.5. 정점 u 에서 진출하는 모든 간선 에 대해 v ∈ T 이고

λ [ v ] > λ [ u ]+ l ( e ) 이면 λ [ v ] = λ [ u ]+ l ( e )

단계단계 6.6. T Å T - { u }, 단계 3 부터 반복

e

u ⎯⎯→ v

는 알고리즘으로서 Dijkstra가 제안한 알고리즘이다.

A

C

3 B

D

E

A B C D E

A B C D E

A B C D E

A B C D E

A B C D E

A B C D E

A B C D E

A B C D E

Bellman과 Ford가 제안한 알고리즘은 그래프에 개의 정점이 있을 때 출발 정점부터 경로

서 우선 A를 출발 정점으로 경로의 길이가 1 인 모든 경로를 구한다. 그 다음에 경로의 길이

BellmanBellman과과^ FordFord^ 알고리즘알고리즘

Dist k [ u ] : 시작 정점 v 에서 u 까지 최대 k 개의 아크를 포함할 수 있는

Dist [ ] k^ u ← min(Dist k^ −^1^^ [ u ],min(Dist k −^1 [ ] i + weight[ , i u ]))

A

C

3 B

D

E

E

D

C

B

A 0 5 3 -2 99

A B C D E

A B C D E

Dist^1

Dist^2 각 정점의 진입차수 고려(열)

Dist^2 [B] = min(5, (3+(-2))= Dist^2 [D] = min(-2, (5+(-1))=- Dist^2 [E] = min(99, min(3+(-1), -2+3))=