다익스트라(Dijkstra) 알고리즘
Download
Report
Transcript 다익스트라(Dijkstra) 알고리즘
다익스트라(Dijkstra) 알고리즘
1조: 박진우 ,정용양 ,송규석
다익스트라란?
(1959 년에 만들어진) Dijkstra 의 알고리즘은 오래된 널리 알려진 알고
리즘입니다. 이 알고리즘은
간선에 가중치(weight)를 가진 그래프에서 최단 경로를 찾을 수 있게 해
줍니다.또한 이 알고리즘은 음수값을 갖지 않는 간선(edge)을 가지는
가중치(weight)가 있는 유향 그래프(directed graph)에 사용됩니다. 이
러한 특별한 수행환경을 가짐과 동시에 그래프는 연결(connected)되어있
어야만 합니다.
간선을 가진 유향 그래프이며 정점들간의
알고리즘 원리
시작 정점으로부터 임의의 정점 X까지의 거리가 현재 다른 정점까지 가는
것보다 작다고 가정하자. 그렇다면 다른 정점을 경유해서 갈 경우, 그냥 임
의의 정점 X까지 가는 것이 무조건 더 작을 것이다. (가정에 의해, 그리고 모
든 가중치는 양수이다)
위에 그림에서 보면, S->X는 가장 짧은 간선이다. 그러므로 S->T라는 간
선은 S->X보다 클 것이다. 또한 T->X는 물론 양수이므로 결국, (S->T +
T->X) >(S->X)임을 알 수 있다. 물론, 가장 가중치가 작은 간선이 경로로
바뀐다 해도 이 원리는 변하지 않는다. 다익스트라는 이 원리를 이용한 알고리즘
이다.
최단거리 구할 시 알아야 할
다익스트라 알고리즘
[1] 시작 정점에서 가장 인접한 정점을 찾는다. 그 정점까지 거리
가 최단거리이다. 지금까지 최단거리가 알려진 정점은 2개(자
기 자신과 지금 찾은 정점)가 된다. 최단거리가 알려진 정점들
의 집합을 S라 하자.
[2] 집합 S에 포함되지 않은 정점 중에서 시작 정점으로부터 가장
가까운 정점을 찾는다. 이 새로운 정점은 집합 S에 바로 이웃
한 정점들 중 하나일 것이다. 그 정점까지 거리는 최단거리이
며, 그 정점을 집합 S에 포함시킨다.
[3] 새로운 정점이 없을 때까지, 즉 모든 정점이 집합 S에 포함될
때까지 []의 과정을 반복한다.
다익스트라 방법의 적용 예
∞
2
2
0
a
4
b
3
3
2
1
c
f
1
4
2
3
d
1
e
6
∞
3
(a)
A에서부터 최단경로를 계산한다
∞
B를 택한 것은 A에서 가장 가깝기 때문이다.
6
2
4
b
2
0
1
3
4
d
∞
3
3
2
a
c
f
1
2
1
e
5
3
(b)
6
2
2
0
a
4
b
c
3
3
2
1
5
f
1
4
∞
2
3
d
1
e
6
4
3
(c)
D를 선택한 이유는 B속한 정점을 거쳐서 A로부터 가는
최단경로이기 때문
E를 선택한 이유는 D와B를 속한 정점을 거쳐서 A로부터
가는 최단경로이기 때문
5
2
2
0
a
4
d
c
3
3
2
1
3
4
b
f
1
2
1
e
4
3
(d)
6
C를 선택한 이유는 D,B,E를 속한 정점을 거쳐서 A로부터
가는 최단경로이기 때문
2
4
b
2
0
1
c
3
3
2
a
5
f
1
4
2
3
d
1
e
4
3
(e)
6
8
A에서 F로 가는 최단경로는{a, b, d, e, c, f}
이다.
5
2
4
b
2
0
1
3
4
d
3
3
2
a
c
f
1
2
1
e
4
3
(f)
6
다익스트라 알고리즘을 사용할 시
알아야 할 배열 정의
s = 입력받는 출발점입니다
e = 입력받는 도착점입니다
data[i][j] = i정점부터 j정점까지의 거리(이건 최단거리가 아닙
니다. 하나의 간선을 거쳐서 가야 합니다) 그리고 i정점과 j정점
이 직접적으로 연결되어 있지 않으면 MAX값을 넣어줍니다
distance[i] = s(출발점)에서 i번째 정점까지의 최단거립니다.
v[i] = i번째 정점이 체크되었는지를 나타냅니다 (1 : 체크)
via[i] =s정점부터 i번째 정점으로 가는 최단경로에서 i번째 경
로의 바로 전 정점의 번호입니다
알고리즘…
#include<stdio.h>
int
int
int
열
int
data[5][5]={0,};
dist[5]={0,};
processed[5]={0,};
n,s,e;
// 인접행렬을 저장하는 배열
// 시작점으로부터의 거리를 저장하는 배열
// 그 노드가 이미 처리되었는지 여부를 저장하는 배
// n : 노드수
// s : 시작점
// e : 끝점
void input()
{
FILE *in=fopen("dijkstra.in","r");
int i,j;
fscanf(in,"%d",&n);
// 노드수와 시작점, 끝점 그리고 인접행렬을 입력받음
fscanf(in,"%d %d",&s,&e);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
fscanf(in,"%d",&data[i][j]);
}
void process()
{
int i,j;
int min,minx;
processed[s]=1;
for(i=1;i<=n;i++)
dist[i]=data[s][i];
// min : 아직 선택하지 않은 점들중 가장 가
까운 점까지의 거리를 저장하는 변수
// minx : min값의 거리에 있는 점의 노드번
호를 저장하는 변수
// 시작점에서 거리를 모두 초기화.. 즉, 아무
점도 거치지 않고 갈때의 거리 저장
for(i=1;i<=n;i++)
{
min=9999;
// 최소값을 줄임
for(j=1;j<=n;j++)
if ((processed[j]==0)&&(dist[j]<min))
{
// '현재 선택하지 않은 점'들중에서 가장 가까운 점을 찾음.
min=dist[j];
minx=j;
}
processed[minx]=1;
if (minx==e) break;
for(j=1;j<=n;j++)
void output()
{
FILE *out=fopen("dijkstra.out","w");
fprintf(out,"%d",dist[e]);
}
void main()
{
input();
process();
output();
}
// 가장 가까운 점을 선택한 것으로 저장.
// 만약 가장 가까운 점이 끝점이라면 루프 종료
// 시작점->가장 가까운 점 거리와 가장 가까운 점->j
까지의 거리가 시작점->j보다
// 작으면 dist[j]를 시작점->가장 가까운 점 + 가
장 가까운점->j 의 값으로 갱신
if (dist[j]>data[minx][j]+dist[minx])
dist[j]=data[minx][j]+dist[minx];
}
}
END…