project #5
최단거리 찾기
자료구조 D0
조장
김 현호20093468
조원
서 상현20113293
김 창헌20093463
최 고봉20093530
김 정무20113281
순서
조원별 업무분담•
일정 계획•
자료조사 및 문제 파악•
알고리즘 계획•
소스구현•
잘된 점 잘 못된 점/•
업무 분담-
조장 김 현호:
자료 조사 김 창헌 김 정무 서 상현: , ,
프로그래밍 최 고봉:
일정-
업무분담 및 알고리즘 조사5/29
사용할 알고리즘 채택 및 알고리즘 공부5/31
자료 조사 및 문제 파악
자료조사-그래프 개념 정리그래프 개념 정리그래프 개념 정리그래프 개념 정리1.1.1.1.
그래프(1)
그래프란? 그래프란 연결되어 있는 객체간의 관계를 표현할 수 있는 자료구조
그래프 용어그래프 용어그래프 용어그래프 용어a.정점(Vertex)노드 라고도 하며 객체를 나타내며 데이터가 저장된 곳(Node) , .
b.간선(Edge)정점을 연결하는 것.
차수c. (Degree)하나의 정점에 닿아있는 간선의 수.번 정점의 차수는 이 됩니다1 3 .
인접d. (Adjacent)한 정점에서 간선을 한번만 통해 갈수 있다면 해당 정점간은 인접하다라고 합니다.번 정점과 번 정점은 인접하지만 번 정점과 번 정점은 인접하지 않습니다1 2 , 1 4 .
무향 그래프e. (Undirected Graph)말 그대로 방향성이 없는 간선으로 이루어진 그래프
유향 그래프f. (Directed graph)간선에 방향성을 나타내어 정점간의 방향관계를 타나내는 그래프
번 정점은 번과 번으로 갈수 있지만 번 정점은 번 정점과 번 정점으로만 갈 수2 3 1 , 1 3 4있습니다.
완전 그래프g. (Complete Graph)모든 정점이 인접한 상태인 그래프.모든 정점이 서로 간선으로 연결된 그래프이며 개 정점이 있다면 모든 정점이 개의, n n-1간선을 갖는 그래프.
그래프 저장 방법 1)
배열로 저장1.
정점의 개수가 이라면 배열로 표현- n n*n
행은 진출 방향을 열은 진입방향을 나타냄-
무 방향 그래프 간선 로 표시- : -1
연결 리스트로 저장2.
각 정점에서 진출하는 리스트를 저장-
그래프 탐색3.
깊이 우선 탐색a.
정점을 탐색할 때 아래쪽으로 먼저 탐색한다- .
넓이 우선 탐색b.
특징 정점을 기준으로 가로로 먼저 탐색한다- .
정렬4. ( Sort )
자료를 일정한 기준에 따라 순서 있게 정리 하는 것-
정렬 위치에 따른 구분a.
내부 정렬
주 기억 장치 안에서 정렬하는 방법-
외부 정렬
보조 기억 장치를 활용해서 정렬하는 방법-
정렬 순서에 따른 구분b.
오름 차순 정렬
값이 작은 것 부터 큰 순서대로 정렬하는 방법-
내림 차순 정렬
값이 큰 것부터 작은 순서대로 정렬하는 방법-
정렬 알고리즘c.
버블 정렬
가장 간단한 알고리즘으로 인접한 두 개의 자료를 비교한 뒤 그 크기에- ,
따라 자료 위치를 바꾸어 정렬
선택 정렬
하나의 기준 자료를 선택한 후 그 다음 자료에서부터 끝의 자료까지 하-
나씩 비교해 가는 방식으로 간단한 반면 속도가 느리다.
삽입 정렬
이미 자료가 정렬되어 있는 상태에서 새로운 자료를 삽입할 경우 또는-
거의 정렬이 되어 있는 자료일 경우 효율적
셀 정렬
주어진 자료를 특정 길이만큼씩 서브파일로 나눈다음 각 서브파일을 삽-
입 정렬 형식으로 처리하고 서브파일 길이를 조금씩 줄여가면 최종 결과
가 나온다.
퀵 정렬
자료 중에서 특정한 하나의 자료를 제어키로 정한 뒤 그 키를 기준으로- ,
그 보다 작은 값은 왼쪽에 큰 값은 오른쪽에 배치한다, .
힙 정렬
힙이라는 자료 구조를 이용 완전이진 트리 형태를 가지고 있는 각 노드- ' ' ,
값이 자식 노드들의 값보다 적지 않아야 한다.
병합 정렬
셀 정렬의 반대 개념으로 자료를 개씩 하나의 그룹으로 묶어 그룹 내부- 2
를 정렬한 후 다시 그룹 두개씩을 묶어 정렬한다, .
출처 : http://blog.naver.com/s2miniwish?Redirect=Log&logNo=158638753
다익스트라 알고리즘다익스트라 알고리즘다익스트라 알고리즘다익스트라 알고리즘2.2.2.2.
정의(1)
출발점에서 시작하여 거리가 최소인 정점을 선택해 나가면 최단 경로를 구할 수 있다는1)
알고리즘의 일종이다greedy .
사용(2)
시작 정점에서 인접한 정점 중 가장 비용이 최소인 정점을 선택하여 지나온 경로 에 포1) S
함 시킨다.
미 선택 정점 중에서 선택한 최소 거리 정점 거리 는 에서 까지의 최단경2) w Dist[w] S w
로의 길이다.
더 짧은 새로운 길을 발견 할 때 의 누적 길이를 갱신한다3) Dist[w] .
갱신시에 지나온 경로를 역 추적 하기위해 배열에 이전 를 기억한다4) previous[n] vertex .
다익스트라 작동 원리(3)
벨만포드 알고리즘벨만포드 알고리즘벨만포드 알고리즘벨만포드 알고리즘3.3.3.3.
정의(1)
간선의 가중치를 음의 값을 허용1)
음의 은 허용하지 않음2) cycle
의 가중치의 합이 일 경우 여러 번 수행 할수록 비용이 감소:cycle <0
결국 의 최단 경로 생성되므로 최단 경로의 의미가 없음- .∞
개요(2)
간선을 최대 개 사용하는 최단 경로1) 1
간선을 최대 개 사용하는 최단 경로2) 2
간선을 최대 개 사용하는 최단 경로3) 3
정점의 개수 만큼 반복4) ( |v|-1 )
플로이드 알고리즘플로이드 알고리즘플로이드 알고리즘플로이드 알고리즘4.4.4.4.개요(1)
알고리즘의 시간복잡도가 인데 반해 플로이드 알고리즘은 이다 이것만Dijkstra O(n^2) O(n^3) .봐서는 알고리즘이 더 느릴 것이라고 생각하기 쉽다 하지만 알고리즘이 한Floyd . Dijkstra번의 루프를 돌 때마다 하는 일이 많다보니 복잡하다보니 실제로는 가 빠른 경우가( ) Floyd상당히 많다.
동작원리 자체는 매우 간단하다 에서 로 갈 수 있는 경로가 있고 또한 에서 로 갈 수. A B , B C
있는 경로가 있다고 한다면 결국 에서 로 갈 수 있는 경로가 있다고 할 수 있다 만약A C .
에서 로 직접 갈 수 있는 경로가 원래 존재했는데 직접 갈 때의 비용이 를 거쳐 로A C ' ' B C
가는 것보다 많이 든다고 하자 그러면 플로이드 알고리즘에서는 에서 로 가는 것을. A C
폐기하고 에서 를 거쳐 로 가는 최단거리 로 업데이트를 하게 된다A B C ' ' .
알고리즘알고리즘알고리즘알고리즘5.A*5.A*5.A*5.A*
개요(1)
에이 스타 알고리즘은 년에 만들어진 것으로 탐색을 수행하는데 있어 매우 효과적인A*( ) 1968 ,
알고리즘이며 다양한 종류의 문제들을 해결하는데 사용되어 왔다 알고리즘은 출발지점에서. A*
목표지점까지 가장 비용이 낮은 보통 가장 짧은 경로를 찾는데 다음과 같이( ) , 'f = g + h'
계산값을 사용하여 다음으로 이동할 경로를 결정한다.
는 목표 로서 시작노드로부터 이 노드까지 오는 데 드는 비용이다 시작노드에서 이g goal( ) , .
위치까지 오는 경로들은 여러 개가 있을 수 있는데 이 노드는 그 경로들 중 특정한 하나를,
의미한다.
는 휴리스틱 으로 이 노드에서 목표까지 가는데 드는 추정된 비용이다 이때 는h heuristic( ) , ' ' . h
휴리스틱을 의미하며 휴리스틱이란 경험에 기초한 추측을 뜻한다 이것이 추측된 비용인, ' ' . ' '
이유는 목표까지의 실제 비용을 아직은 알지 못하기 때문이다 휴리스틱을 계산하는데 여러.
가지 방법이 있을 수 있지만 일반적으로 현재 위치에서 목표까지의 일직선 거리값을,
사용한다.
는 적합도 로서 와 의 합이고 이 노드를 거쳐 가는 경로의 비용에 대한 최선의f fitness( ) , g h
추측을 의미한다 값이 낮을수록 이 경로가 최단 경로일 가능성이 크다. f .
현재위치에서 다음의 어떤 노드로 이동할 것인가를 결정하는 방법은 다음과 같다 현재위치에.
연결된 다음 노드가 여러개일 경우 각각의 다음 노드마다 시작위치에서 다음 노드까지의,
거리와 그 노드에서 목표까지의 추정된 휴리스틱 값을 더한 값들을 계산하여 값이 가장 작은f , f
노드쪽으로 이동하는 것이 목표까지의 가장 짧은 경로가 될 가능성이 높다 이렇게 값이 가장. f
작은 노드들을 선택하여 탐색을 수행하다 목표노드에 도착하면 탐색을 종료한다.
문제 파악-정의된 모든 노드에서 모든 노드로의 패스 중에서
값이 가장 낮은 패스 개를 출력한다weight 3 .
이때 가중치의 합 또한 같이 출력되게 한다.
알고리즘 계획-플로이드 알고리즘을 이용하여 정의된 모든 노드에서 다른 모든 노드로의 패스를 구한다음
값이 가장 낮은 패스 개를 가중치의 합과 함께 출력하도록 한다weight 3 .
소스 구현-#include <stdio.h>
#include <stdlib.h>
int **graph;
int ***result;
int ***max_tmp;
char *node;
void InitGraph(int n);
void PrintPath(int i, int j);
void UnInitGraph(int n);
void main(int argc, char* argv[]) {
FILE* input;
int n, k, i, j, x;
int weight;
char name[3];
if ( argc != 2 || strlen(argv[1]) == 0) {
printf("Usage : %s filename\n" , argv[0]);
getch();
return 0;
}
input = fopen(argv[1],"r");
if (!input) {
fprintf(stderr,"Can not open a file. : %s \n",argv[1]);
getch();
exit(1);
}
fscanf(input,"%d",&n);
InitGraph(n);
printf("%d\n",n);
for( i = 0 ; i < n ; i++ ) {
graph[i][i] = 0;
result[i][i][0] = 0;
result[i][i][1] = 0;
result[i][i][2] = 0;
}
while ( !feof(input) ) {
fscanf(input,"%s",name);
for( i = 0 ; i < n ; i++ ) {
if( node[i] == name[0] ) break;
if( node[i] == 0 ) {
node[i] = name[0];
break;
}
}
for( j = 0 ; j < n ; j++ ) {
if( node[j] == name[1] ) break;
if( node[j] == 0 ) {
node[j] = name[1];
break;
}
}
fscanf(input,"%d",&weight);
graph[i][j] = weight;
graph[j][i] = weight;
result[i][j][0] = weight;
result[j][i][0] = weight;
printf("%c%c %d\n",node[i],node[j],graph[i][j]);
}
printf("\n");
for( x = 0 ; x < 3 ; x++ ) {
for( k = 0 ; k < n ; k++ ) {
for( i = 0 ; i < n ; i++ ) {
for( j = 0 ; j < n ; j++ ) {
if( x > 0 ) {
if( result[i][j][x-1] < result[i][k][0] + result[k][j][0] ) {
if( result[i][j][x] > result[i][k][0] + result[k][j][0] ) {
result[i][j][x] = result[i][k][0] + result[k][j][0];
}
}
}
else {
if( result[i][j][0] > result[i][k][0] + result[k][j][0] ) {
result[i][j][x] = result[i][k][x] + result[k][j][x];
}
}
}
}
}
}
for( i = 0 ; i < n ; i++ ) {
for( j = 0 ; j < n ; j++ ) {
if( result[i][j][0] > result[i][j][1] ) {
if( result[i][j][0] > result[i][j][2] ) {
if( result[i][j][1] > result[i][j][2] ) {
x = result[i][j][0];
result[i][j][0] = result[i][j][2];
result[i][j][2] = x;
}
else {
x = result[i][j][0];
result[i][j][0] = result[i][j][1];
result[i][j][1] = result[i][j][2];
result[i][j][2] = x;
}
}
else {
x = result[i][j][0];
result[i][j][0] = result[i][j][1];
result[i][j][1] = x;
}
}
else {
if( result[i][j][0] < result[i][j][2] ) {
if( result[i][j][1] > result[i][j][2] ) {
x = result[i][j][1];
result[i][j][1] = result[i][j][2];
result[i][j][2] = x;
}
}
else {
x = result[i][j][0];
result[i][j][0] = result[i][j][2];
result[i][j][2] = result[i][j][1];
result[i][j][1] = x;
}
}
}
}
printf(" Graph weight array :\n");
for (i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
if( graph[i][j] == 30000 )
printf(" oo");
else
printf("%3d", graph[i][j]);
}
printf("\n");
}
printf("\n");
for( x = 0 ; x < 3 ; x++ ) {
printf(" Shortest Path %d weight array :\n",x+1);
for ( i = 0 ; i < n ; i++) {
for( j = 0 ; j < n ; j++) {
if( result[i][j][x] == 30000 ) {
result[i][j][x] = result[i][j][x-1];
printf("%3d", result[i][j][x]);
}
else
printf("%3d", result[i][j][x]);
}
printf("\n");
}
printf("\n");
}
UnInitGraph(n);
fclose(input);
printf( 계속하시혀면 아무키나 누르세요" .....“);
getch();
}
void InitGraph(int n) {
int i,j;
graph = (int **)malloc(n*sizeof(int *));
result = (int ***)malloc(n*sizeof(int **));
max_tmp = (int ***)malloc(n*sizeof(int **));
node = (char *)malloc(n*sizeof(char));
for( i = 0 ; i < n ; i++ ) {
graph[i] = (int *)malloc(n*sizeof(int));
result[i] = (int **)malloc(n*sizeof(int *));
max_tmp[i] = (int **)malloc(n*sizeof(int *));
node[i] = 0;
for( j = 0 ; j < n ; j++ ) {
result[i][j] = (int *)malloc(3*sizeof(int));
max_tmp[i][j] = (int *)malloc(2*sizeof(int));
graph[i][j] = 30000;
result[i][j][0] = 30000;
result[i][j][1] = 30000;
result[i][j][2] = 30000;
max_tmp[i][j][0] = 30000;
max_tmp[i][j][1] = 0;
}
}
}
void UnInitGraph(int n) {
int i,j;
for( i = 0 ; i < n ; i++ ) {
for( j = 0 ; j < n ; j++ ) {
free(result[i][j]);
free(max_tmp[i][j]);
}
free(graph[i]);
free(result[i]);
free(max_tmp[i]);
}
free(graph);
free(result);
free(max_tmp);
free(node);
}
결과-
잘된 점-각자 역할에 맞게 할 일들을 잘 처리해 주었기에 이번 프로젝트도 무사히 마칠 수가 있었다.
잘 못된 점-처음부터 문제를 파악하기 힘들었다 모든 노드를 정의하고 사용자가 임의로 지정한 시작 노.
드와 끝 노드 사이의 최단 패스 개를 출력하는 프로그램을 짜려했으나 잘 못된 판단이었고 시3 ,
간을 소비했다.
고쳐야 할 점-각자 이때까지 조에서 나름대로의 역할을 수행해 왔기 때문에 역할에 맞는 일처리가 알맞게 이
루어 졌으나 문제파악에 대한 부족함이 보였다 그로인해 아까운 시간을 많이 허비하게 되었.
다 다음 프로젝트에서는 첫 회의 때에 문제파악부터 제대로 이루어 져야 할 것이다. .