이산수학 c1 프로젝트 4

15

Click here to load reader

Upload: pkok15

Post on 19-Jun-2015

241 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: 이산수학 C1 프로젝트 4

project #4

Syntax of languages

이산치수학 C1조

20083458 민영지20093474 박구남20093526 정준용20093530 최고봉

Page 2: 이산수학 C1 프로젝트 4

순서

•조원별 업무분담

•일정 계획

•문제 파악

•소스구현

•느낀점

Page 3: 이산수학 C1 프로젝트 4

정준용 최종 보고서 작성 및 프로젝트 총괄 및 자료 조사

민영지 알고리즘 구상 및 자료 조사

박구남 알고리즘 구상 및 소스 구현

최고봉 알고리즘 구상 및 소스 구현

04.25~04.30 과제에 대한 자료 조사 및 업무분담 일정 계획

04.30~05.07 MST를 만들기 위한 알고리즘 구성

05.07~05.09구성된 알고리즘을 기반으로 소스 구현 및 문제점 탐색과 해결에 대한 토의

05.09~05.11 최종 소스 확인 및 최종보고서 작성

1)조원별 업무 분담

2)일정계획

Page 4: 이산수학 C1 프로젝트 4

3)문제파악Syntax of languages -그래프가 주어질 경우 MST를 출력하라

-입력 6 AB 5 BC 5 AD 10 BD 10 CD 20 BE 20 DE 20 CF 30 EF 10

출력 : AB, BC, AD, BE, EF

Page 5: 이산수학 C1 프로젝트 4

※과제에 대한 참고자료

◉Minimum Spanning Tree

최소 비용 신장 트리는 가중 그래프의 신장 트리 중에서 가중치의 합이 최소인 신장 트리를 말한다.

최소 비용 신장 트리를 현실의 예로 들어 설명하면 쉽게 이해할 수 있다. 위의 그림에서 각 도시(노드)를 연결하는 통신망을 구축 할 때 가장 적은 비용이 드는 길을 찾을 때 사용할 수 있다. 서울에서 부산까지 통신망을 구축하기 위해서 갈수 있는 경로는 총 (서울->대구->부산), (서울->부산), (서울, 대전, 부산) 3개가 존재 한다. 먼저 (서울->대구->부산)을 보면 부산까지 가기 위해서 드는 비용(간선의 가중치 값) 11이다. (서울->부산)은8, (서울->대전->부산)은 7이다. 즉, 가장 적은 비용으로 서울과 부산간의 통신망을 구축하기 위해서는(서울->대전->부산)으로 연결하는 것이다. 이렇듯. 최소 비용 신장 트리는 가중치의 합이 최소인 트리를 말한다.

[출처] 신장 트리 & 최소 비용 신장 트리(Minimum Cost Spanning Tree)http://blog.naver.com/songsmir?Redirect=Log&logNo=100117549438

Page 6: 이산수학 C1 프로젝트 4

◉Prim 알고리즘

Prim 알고리즘은 트리를 확장시켜 최소 비용 신장 트리를 만드는 방법이다. Kruskal 알고리즘이 가중치가 낮은 간선의 우선 연결 이였다면, Prim 알고리즘은 현재 신장 트리와 연결될 간선 중에서 가장 적은 비용을 가지는 간선을 선택한다는 것이다.

위 그림에서 보듯이Prim 알고리즘은 처음에 임의의 노르를 선택하여 연결된 간선의 비용이 가장 적은 곳으로 이동 하게 된다. 이렇듯 연결된 각각의 노드의 간선들중 가장 적은 가중치 값을 가진 간선을 선택하는 방식이다.

[출처] Kruskal 알고리즘 & Prim 알고리즘http://blog.naver.com/songsmir?Redirect=Log&logNo=100117549438

Page 7: 이산수학 C1 프로젝트 4

◉Kruskal 알고리즘

Kruskal 알고리즘은 그래프의 모든 간성을 비용 순으로 정렬한 다음, 낮은 비용을 가지는 간선을 차례대로 선택하여 신장 트리를 완성해 가는 방법이다. 아래의 그림을 보면 간단히 이해를 할 수 있다.

위 그림에서 보면 원래의 그래프에서 간선의 가중치가 가장 적은 값들을 중심으로 노드를 연결해 나가고 있다. 여기서 조심 해야 할 부분은 간선(E,F)에서 간선의 가중치 값은4 이지만 만약 연결하게 된다면 트리에 순환이 생기므로 트리의 특성을 가질 수 없게 된다. 이럴 때는 이 부분을 연결 하지 않고 다음 가중치 값을 연결 하게 된다.

[출처] Kruskal 알고리즘 & Prim 알고리즘http://blog.naver.com/songsmir?Redirect=Log&logNo=100117549438

Page 8: 이산수학 C1 프로젝트 4

5)소스 구현

#include <stdio.h>#include <stdlib.h>

typedef struct Node {char name;int link_len;struct Node *next;struct Node *prev;

}Node;

typedef struct Edge {char name1;char name2;int link_len;

}Edge;

Node **graph;

void InitGraph(int n);Node *AppendNode(Node *Target, Node *aNode);int DeleteNode(Node *Target);void UnInitGraph(int n);

void main() {int n, i, j, r, a, b;char name[3];int len, x;Node *Now, temp;Edge *edge_list,*result;char *rst_Node;Edge min;

Page 9: 이산수학 C1 프로젝트 4

temp.link_len = 0; temp.name = 0;temp.next = NULL; temp.prev = NULL;min.link_len = 0; min.name1 = 0;min.name2 = 0;

printf("노드의 개수를 입력해주세요.\n");scanf("%d",&n);rst_Node = (char *)malloc(n*sizeof(char));for( i = 0 ; i < n ; i++ ) rst_Node[i] = 0;edge_list = (Edge *)malloc(n*n*sizeof(Edge));result = (Edge *)malloc((n-1)*sizeof(Edge));InitGraph(n);printf("Edge의 명칭과 길이를 입력해주세요.(예, AB 5)\n입력을 끝내시려면 0

을 입력하세요.\n");while(1) {

scanf("%s",name);if( name[0] == '0' ) break;scanf("%d",&len);for( x = 0 ; x < n ; x++ ) {

Now = graph[x];if( graph[x]->name == name[0] ) {

temp.name = name[1];temp.link_len = len;AppendNode(Now,&temp);break;

}else if( graph[x]->next == NULL ) {

graph[x]->name = name[0];temp.name = name[1];temp.link_len = len;AppendNode(Now,&temp);break;

}

Page 10: 이산수학 C1 프로젝트 4

}for( x = 0 ; x < n ; x++ ) {

Now = graph[x];if( graph[x]->name == name[1] ) {

temp.name = name[0];temp.link_len = len;AppendNode(Now,&temp);break;

}else if( graph[x]->next == NULL ) {

graph[x]->name = name[1];temp.name = name[0];temp.link_len = len;AppendNode(Now,&temp);break;

}}

}rst_Node[0] = graph[0]->name;r = 1;while( r < n ) {

Now = graph[0]->next;for( i = 0, x = 0, j = 1 ; i < n*n ; ) {

if( Now == NULL ) {if( j == n-1 ) break;if( rst_Node[j] == 0 ) break;x++;Now = graph[x]->next;j++;continue;

}edge_list[i].name1 = graph[x]->name;edge_list[i].name2 = Now->name;edge_list[i].link_len = Now->link_len;

Page 11: 이산수학 C1 프로젝트 4

Now = Now->next;i++;

}i--;min.link_len = edge_list[i].link_len;min.name1 = edge_list[i].name1;min.name2 = edge_list[i].name2;for( i-- ; i >= 0 ; i-- ) {

if( min.link_len >= edge_list[i].link_len ) {min.link_len = edge_list[i].link_len;min.name1 = edge_list[i].name1;min.name2 = edge_list[i].name2;

}}rst_Node[r] = min.name2;result[r-1].name1 = min.name1;result[r-1].name2 = min.name2;r++;for( x = 0 ; x < n ; x++ ) {

if( graph[x]->name == min.name1 ) {Now = graph[x]->next;while(1) {

if( Now->name == min.name2 ) {DeleteNode(Now);break;

}Now = Now->next;

}}if( graph[x]->name == min.name2 ) {

Now = graph[x]->next;while(1) {

if( Now->name == min.name1 ) {DeleteNode(Now);

Page 12: 이산수학 C1 프로젝트 4

break;}Now = Now->next;

}}

}for( a = 0, b = 1 ; a < r ; b++ ) {

for( x = 0 ; x < n ; x++ ) {if( graph[x]->next == NULL ) continue;if( graph[x]->name == rst_Node[a] ) {

Now = graph[x]->next;while(1) {

if(Now->name == rst_Node[b] ) {DeleteNode(Now);break;

}if( Now->next == NULL ) break;Now = Now->next;

}}if( graph[x]->name == rst_Node[b] ) {

Now = graph[x]->next;while(1) {

if( Now->name == rst_Node[a] ) {DeleteNode(Now);break;

}if( Now->next == NULL ) break;Now = Now->next;

}}

}if( b >= r-1 ) {

Page 13: 이산수학 C1 프로젝트 4

a++;b = a;

}}

}for( i = 0 ; i < n-1 ; i++ ) {

printf("%c%c",result[i].name1,result[i].name2);if( i != n-2 )

printf(", ");}free(edge_list);free(rst_Node);free(result);UnInitGraph(n);printf("\n계속하시려면 아무키나 누르세요....");getch();

}

void InitGraph(int n) {int i;graph = (Node **)malloc(n*sizeof(Node *));for( i = 0 ; i < n ; i++ ) {

graph[i] = (Node *)malloc(sizeof(Node));graph[i]->next = NULL;graph[i]->prev = NULL;

}}

Node *AppendNode(Node *Target, Node *aNode) {Node *New;Node *Right;Node *tail;New = (Node *)malloc(sizeof(Node));for(tail=Target;tail->next;tail=tail->next);

Page 14: 이산수학 C1 프로젝트 4

*New = *aNode;Right = tail->next;New->next = Right;New->prev = tail;tail->next = New;if (Right) {

Right->prev = New;}return New;

}

int DeleteNode(Node *Target) {Node *Left, *Right;if( Target == NULL )

return 0;Left = Target->prev;Right = Target->next;Left->next = Right;if (Right)

Right->prev = Left;free(Target);return 1;

}

void UnInitGraph(int n) {int i;for( i = 0 ; i < n ; i++ )

while(DeleteNode(graph[i]->next));free(graph);graph = NULL;

}

Page 15: 이산수학 C1 프로젝트 4

6)느낀점 프로젝트를 할 때 알고리즘을 스스로 생각해보고 하라고 하셨는데 저희가 생각해봐도 힘들어서 인터넷에서 알고리즘을 참고했습니다. 저희 조는 Prim알고리즘을 사용했는데 처음에는 스패닝 트리를 만드는 소스를 구현하는데 어려움을 느꼈으나 조원들과의 회의를 통해 해결하였습니다.