3. -업무 분담
조장: 김 현호
자료 조사: 김 창헌, 김 정무, 서 상현
프로그래밍: 최 고봉
-일정
5/29 업무분담 및 알고리즘 조사
5/31 사용할 알고리즘 채택 및 알고리즘 공부
4. 자료 조사 및 문제 파악
-자료조사
1.그래프 개념 정리
(1) 그래프
그래프란? 그래프란 연결되어 있는 객체간의 관계를 표현할 수 있는 자료구조
그래프 용어
a.정점(Vertex)
노드(Node)라고도 하며 객체를 나타내며, 데이터가 저장된 곳.
b.간선(Edge)
정점을 연결하는 것.
c.차수(Degree)
하나의 정점에 닿아있는 간선의 수.
1번 정점의 차수는 3 이 됩니다.
d.인접(Adjacent)
한 정점에서 간선을 한번만 통해 갈수 있다면 해당 정점간은 인접하다라고 합니다.
1번 정점과 2번 정점은 인접하지만, 1번 정점과 4번 정점은 인접하지 않습니다.
e.무향 그래프(Undirected Graph)
말 그대로 방향성이 없는 간선으로 이루어진 그래프
5. f.유향 그래프(Directed graph)
간선에 방향성을 나타내어 정점간의 방향관계를 타나내는 그래프
2번 정점은 3번과 1번으로 갈수 있지만, 1번 정점은 3번 정점과 4번 정점으로만 갈 수
있습니다.
g.완전 그래프(Complete Graph)
모든 정점이 인접한 상태인 그래프.
모든 정점이 서로 간선으로 연결된 그래프이며, n개 정점이 있다면 모든 정점이 n-1개의
간선을 갖는 그래프.
6. 1) 그래프 저장 방법
1. 배열로 저장
- 정점의 개수가 n이라면 n*n 배열로 표현
- 행은 진출 방향을 열은 진입방향을 나타냄
- 무 방향 그래프 : 간선 -1로 표시
2. 연결 리스트로 저장
- 각 정점에서 진출하는 리스트를 저장
3. 그래프 탐색
7. a. 깊이 우선 탐색
- 정점을 탐색할 때 아래쪽으로 먼저 탐색한다.
b. 넓이 우선 탐색
- 특징 정점을 기준으로 가로로 먼저 탐색한다.
4. 정렬 ( Sort )
- 자료를 일정한 기준에 따라 순서 있게 정리 하는 것
a. 정렬 위치에 따른 구분
내부 정렬
- 주 기억 장치 안에서 정렬하는 방법
외부 정렬
- 보조 기억 장치를 활용해서 정렬하는 방법
b. 정렬 순서에 따른 구분
오름 차순 정렬
- 값이 작은 것 부터 큰 순서대로 정렬하는 방법
내림 차순 정렬
8. - 값이 큰 것부터 작은 순서대로 정렬하는 방법
c. 정렬 알고리즘
버블 정렬
- 가장 간단한 알고리즘으로 인접한 두 개의 자료를 비교한 뒤, 그 크기에
따라 자료 위치를 바꾸어 정렬
선택 정렬
- 하나의 기준 자료를 선택한 후 그 다음 자료에서부터 끝의 자료까지 하
나씩 비교해 가는 방식으로 간단한 반면 속도가 느리다.
삽입 정렬
- 이미 자료가 정렬되어 있는 상태에서 새로운 자료를 삽입할 경우 또는
거의 정렬이 되어 있는 자료일 경우 효율적
셀 정렬
- 주어진 자료를 특정 길이만큼씩 서브파일로 나눈다음 각 서브파일을 삽
입 정렬 형식으로 처리하고 서브파일 길이를 조금씩 줄여가면 최종 결과
가 나온다.
퀵 정렬
- 자료 중에서 특정한 하나의 자료를 제어키로 정한 뒤, 그 키를 기준으로
그 보다 작은 값은 왼쪽에, 큰 값은 오른쪽에 배치한다.
힙 정렬
- '힙'이라는 자료 구조를 이용, 완전이진 트리 형태를 가지고 있는 각 노드
값이 자식 노드들의 값보다 적지 않아야 한다.
병합 정렬
- 셀 정렬의 반대 개념으로 자료를 2개씩 하나의 그룹으로 묶어 그룹 내부
를 정렬한 후, 다시 그룹 두개씩을 묶어 정렬한다.
출처 : http://blog.naver.com/s2miniwish?Redirect=Log&logNo=158638753
2.다익스트라 알고리즘
(1)정의
1) 출발점에서 시작하여 거리가 최소인 정점을 선택해 나가면 최단 경로를 구할 수 있다는
greedy 알고리즘의 일종이다.
(2)사용
1) 시작 정점에서 인접한 정점 중 가장 비용이 최소인 정점을 선택하여 지나온 경로 S에 포
함 시킨다.
9. 2) 미 선택 정점 중에서 선택한 최소 거리 정점 w 거리 Dist[w]는 S에서 w 까지의 최단경
로의 길이다.
3) 더 짧은 새로운 길을 발견 할 때 Dist[w]의 누적 길이를 갱신한다.
4) 갱신시에 지나온 경로를 역 추적 하기위해 previous[n] 배열에 이전 vertex를 기억한다.
(3)다익스트라 작동 원리
10. 3.벨만포드 알고리즘
(1) 정의
1) 간선의 가중치를 음의 값을 허용
2) 음의 cycle은 허용하지 않음
:cycle의 가중치의 합이 <0 일 경우 여러 번 수행 할수록 비용이 감소
결국 -∞의 최단 경로 생성되므로 최단 경로의 의미가 없음.
(2) 개요
1) 간선을 최대 1개 사용하는 최단 경로
2) 간선을 최대 2개 사용하는 최단 경로
3) 간선을 최대 3개 사용하는 최단 경로
4) 정점의 개수( |v|-1 ) 만큼 반복
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* 알고리즘
(1)개요
A*(에이 스타) 알고리즘은 1968년에 만들어진 것으로, 탐색을 수행하는데 있어 매우 효과적인
알고리즘이며 다양한 종류의 문제들을 해결하는데 사용되어 왔다. A* 알고리즘은 출발지점에서
목표지점까지 가장 비용이 낮은(보통 가장 짧은) 경로를 찾는데, 다음과 같이 'f = g + h'
계산값을 사용하여 다음으로 이동할 경로를 결정한다.
g는 goal(목표)로서, 시작노드로부터 이 노드까지 오는 데 드는 비용이다. 시작노드에서 이
위치까지 오는 경로들은 여러 개가 있을 수 있는데, 이 노드는 그 경로들 중 특정한 하나를
의미한다.
h는 heuristic(휴리스틱)으로, 이 노드에서 목표까지 가는데 드는 '추정된' 비용이다. 이때 h는
휴리스틱을 의미하며, 휴리스틱이란 '경험에 기초한 추측'을 뜻한다. 이것이 '추측된' 비용인
이유는 목표까지의 실제 비용을 아직은 알지 못하기 때문이다. 휴리스틱을 계산하는데 여러
11. 가지 방법이 있을 수 있지만, 일반적으로 현재 위치에서 목표까지의 일직선 거리값을
사용한다.
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);
12. 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 filenamen" , 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("%dn",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;
}
19. -잘된 점
각자 역할에 맞게 할 일들을 잘 처리해 주었기에 이번 프로젝트도 무사히 마칠 수가 있었다.
-잘 못된 점
처음부터 문제를 파악하기 힘들었다. 모든 노드를 정의하고 사용자가 임의로 지정한 시작 노
드와 끝 노드 사이의 최단 패스3개를 출력하는 프로그램을 짜려했으나 잘 못된 판단이었고, 시
간을 소비했다.
-고쳐야 할 점
각자 이때까지 조에서 나름대로의 역할을 수행해 왔기 때문에 역할에 맞는 일처리가 알맞게 이
루어 졌으나 문제파악에 대한 부족함이 보였다. 그로인해 아까운 시간을 많이 허비하게 되었
다. 다음 프로젝트에서는 첫 회의 때에 문제파악부터 제대로 이루어 져야 할 것이다.