Download Notes on Graphs (INA240) and more Lecture notes Data Structures and Algorithms in PDF only on Docsity!
©copyright 2005 자료구조 및 실습( INA240) NOTE 11
그래프
그래프그래프 (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 , …, v n , b 가 존재하기 위해서는
간선 ( a , v 1 ), ( v 1 , v 2 ), …, ( v n -1 , v n ), ( v n , b ) 가 존재해야 한다.
그래프 – 계속
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
주기주기(cycle): 첫 번째 정점과 마지막 정점이 같은 경로
정점의정점의 차수차수:^ 정점에 연결된 간선의 수를 말하며,^ 유방향 그래프에서는
진입진입 차수차수(indegree)와 진출진출 차수차수(outdegree)로 나누어 고려된다.
비가중치 그래프의 표현
방법방법^ 1.1.^ 인접 행렬
A
B D
C
D 1 0 1 0
C 0 1 0 1
B 1 0 1 0
A 0 1 0 1
A B C D
M
E
L
B
A 1
0
0
0
0
B
B 0 0 1 0
M 0 1 0 0
L 1 0 1 0
E 1 0 0 0
A 0 1 0 0
A E L M
단점 단점.. n^2 공간이 필요
비가중치 그래프의 표현 – 계속
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 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);
UndirectedUnweightedListGraph
public abstract UndirectedUnweightedListGraph implements UnweightedGraph{
public UndirectedUnweightedListGraph(){
super(DEF_CAPACITY);
public UndirectedUnweightedListGraph(int capacity){
super(DEF_CAPACITY);
public void removeVertex(String label)
throws GraphUnderflowException { … }
public void removeEdge(String from, String to)
throws GraphUnderflowException { … }
public void insertEdge(String from, String to)
throws GraphUnderflowException { … }
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 정점들은 배열을 이용한 비정렬 방식으로 유지
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
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
Traverse
너비우선탐색너비우선탐색(BFS, Breadth First Search)
단계 단계 1.1. 정점 i 를 방문한다.
단계 단계 2.2. 정점 i 에 인접한 정점 중에 아직 방문하지 않은 정점이
단계 단계 3.3. 큐에서 정점을 제거하고, 이 정점을 i 로 하여 단계 1 부터
한다. A
C
E
B
D
순회 순서: A,B,C,E,D
A
C
F
B
D
E
G
순회 순서: A,B,C,D,F,E,G
ListGraph의 반복자 클래스
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); }
연결 여부
연결연결 그래프그래프(connected graph):^ 무방향 그래프에서 서로 다른 모든
DFS, BFS를 이용하여 연결 여부를 확인할 수 있다.
DFS( G , i ): i 노드로부터 시작하여 방문한 모든 정점
이 때 G = DFS( G , i )이면 연결 그래프
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
가중치 그래프의 표현 – 계속
방법방법^ 2.2.^ 인접 행렬
public abstract MatrixGraph implements Graph{ public static final int NULLEDGE = -1; protected class GraphIterator implements Iterator{ … } protected String[] graph; protected int[][] adjMatrix; 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; }
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 { … }
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(“…”);
size--;
graph[v] = graph[size];
for(int i=0;i<size; i++){
adjMatrix[v][i] = adjMatrix[size][i];
adjMatrix[size][i] = NULLEDGE;
adjMatrix[i][v] = adjMatrix[i][size];
adjMatrix[i][size] = NULLEDGE;
adjMatrix[v][v] = NULLEDGE;
}// DirectedWeightedMatrixGraph: insertEdge
최단 경로 알고리즘
최단 경로 알고리즘 1.
모든 간선의 가중치가 같은 유한 무방향 그래프에서 정점 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 부터 반복
최단 경로 알고리즘 1. – 계속
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
최단 경로 알고리즘 3.
유한 유방향 그래프에서 정점 s 에서
정점 t 까지 길이가 가장 짧은 경로를
n 이 정점의 수일 때, 음의 주기가
길이는 최대 n -1 이다.
길이가 1 인 것부터 n -1 인 것까지
A
C
B
A
C
B
최단 경로 알고리즘 3. – 계속
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
최단 경로 알고리즘 3. – 계속
BellmanBellman과과^ FordFord^ 알고리즘알고리즘
Dist k [ u ] : 시작 정점 v 에서 u 까지 최대 k 개의 아크를 포함할 수 있는
1 1
Dist [ ] min(Dist [ ],min(Dist [ ] weight[ , ]))
k k k
u u i 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))=