자료구조 프로젝트

72
프로젝트 보고서 프로젝트 파스칼의 삼각형 #1 소속 컴퓨터 공학과 : 조명:A1 조원 김형오 오승원 정상혁 강수현 : , , ,

Upload: rkr300

Post on 03-Nov-2014

41 views

Category:

Documents


3 download

DESCRIPTION

창원대학교 자료구조 수업에서 일학기동한 진행을 하였던 프로젝트입니다.

TRANSCRIPT

Page 1: 자료구조 프로젝트

프로젝트 보고서프로젝트 파스칼의 삼각형#1

소속 컴퓨터 공학과:

조 명 : A1

조원 김형오 오승원 정상혁 강수현: , , ,

Page 2: 자료구조 프로젝트

프로젝트 목적

배열의 사용법을 안다.⇒

프로그램의 시간 공간 복잡도 계산 할 수 있다, .⇒

조원별 업무파악

조장 김형오 공간복잡도에 대한 조사 출력부분에 대해서 조사: ,

오승원 전체적인 코딩 회의를 통해 의견 수렴 후 소스 수정: ,

정상혁 시간복잡도에 대한 조사 과 을 입력 받는 부분에 대해서 조사: , n m

강수현 보고서 구성 작성 배열과 파스칼의 삼각형에 대한 내용 조사: & ,

반성

무작정 소스를 구현을 한다는 목적만을 가지고 프로젝트를 진행을 하는 것보다는 주어진 문제에 대해서 많

은 정보를 수집을 하고 수집된 자료와 참고 서적을 가지고와서 논의를 하다가 모르는 부분이 있으면 바로바로

확인을 하고 해결을 하여 프로젝트에 대한 회의가 원활히 진행이 될 수 있도록 해야 한다 회의를 하면서 수.

정했던 내용 어떤 부분에 대해 논의 했는지 모든 내용들을 메모해서 보고서에 포함시켜야 할 것이다, .

배열

둘 이상의 변수를 모아놓은 것 동일한 자료형의 변수를 여러 개 선언하여 사용하는 것- . .

여러 개의 변수가 모여서 배열을 이루기 때문에 여러 개의 값을 저장할 수 있다- .

예-( ) int array[4];

형 변수 개로 이뤄진 배열을 선언하되 그 배열의 이름을 로 한다int 4 , array !!⇒

배열을 이루는 요소 변수 의 자료형int : ( )⇒

배열의 길이[4] :⇒

배열 길이가 인 형 차원 배열array( 4 int 1 )⇒

-arr[idx]=20;

배열 의 번째 요소에 을 저장해라arr idx+1 20 !!⇒

예-( ) arr[0]=10;

배열 의arr⇒ 첫 번째 요소에 을 저장해라10 !!

인덱스 값-[ ]

배열의 위치 정보를 명시하는 인덱스 값은 이 아닌1⇒ 에서부터 시작0 .

int int int int

Page 3: 자료구조 프로젝트

배열을 선언과 동시에 초기화하는 방법-

예 순차적으로 로 초기화 함( 1) int arr1[5]=1, 2, 3, 4, 5 1,2,3,4,5 .⇒

예 컴파일러에 의해서 자동으로 이 삽입됨( 2) int arr2[ ]=1,2,3,4,5,6,7; 7 .⇒

초기화리스트가 선언되면 배열의 길이정보를 생략할 수 있다 컴파일러가 초기. 화 리스트의

수를 참조하여 길이정보를 채워주기 때문이다.

예 번째 배열요소는 으로 채워짐( 3) int arr3[5]=1,2; 3,4,5 0 .⇒

배열의 인덱스번호는 항상 부터 시작- 0

배열이 차지하는 총 메모리 공간은 배열의 크기 자료형의 크기- *

배열의 크기는 반드시 상수로 지정해야 함-

배열의 범위를 검사하지 않음-

파스칼의 삼각형

(x+y)^0 = 1

(x+y)^1 = 1x + 1y

(x+y)^2 = 1x^2y^0 + 2x^1y^1 + 1x^0y^2

(x+y)^3 = 1x^3y^0 + 3x^2y^1 + 3x^1y^2 + 1x^0y^3

.

.

n

(x+n)^n = =∑ nCk*x^k*y^(n-k)

k=1

0C0x

1C0x + 1C1y

2C0x^2y^0 + 2C1x^1y^1 + 2C2x^0y^2

3C0x^3y^0 + 3C1x^2y^1 + 3C2x^1y^2 + 3C3x^0y^3

.

.

n-1Cr-1 + n-1Cr = nCr → p(n,m)=p(n-1,m-1)+p(n-1,m)

1 2 3 4 5

1 2 3 4 5 6 7

1 2 0 0 0

Page 4: 자료구조 프로젝트

파스칼의 삼각형 코딩< 1>

#include <stdio.h>

int main(void)

int i,j;

int arr[[100][102];

int n,m;

을 이용해서 을 구한다printf("n , m p(n,m) \n"); 안내// 1

과 을 입력하라 은 이하이다printf("n m n 1000 \n"); 안내// 2

printf("n = "); 입력 유도// n

scanf("%d",&n);

printf("m = "); 입력유도// m

scanf("%d",&m);

아래 파스칼 삼각형 계산// .

for(i=0;i<100;i++)

for(j=0;j<102;j++)

arr[i][j]=0;

arr[0][1]=1;

for(i=1;i<100;i++)

for(j=1;j<102;j++)

if(arr[i-1][j-1]==0 && arr[i-1][j]==0)

break;

arr[i][j]=arr[i-1][j-1]+arr[i-1][j];

if(arr[n-1][m]==0)

잘못 입력하셨습니다printf(" .\n");

else

printf("p ( %d , %d ) = %d\n", n, m, arr[n-1][m]); 값 확인// p(n,m)

Page 5: 자료구조 프로젝트

return 0;

파스칼의 삼각형 코딩 수정< 1- >

위의 코딩은 간단하게 작성한 파스칼의 삼각형 초안이다 이 아닌 을 배열 공간으로 잡아서 구성해. 1000 100

보았다 하지만 지역변수로 선언을 할 경우에 함수 내에서 이용가능한 메모리를 넘어서 지역변수가 아닌. main

전역변수로 선언을 하기로 결정을 했다.

로 배열공간을 확보하였다 배열을 모두 으로 채운 후에 문을 통해 수들을 채워가는int arr[1000][1002]; . 0 for

방법을 이용했다.

로 수정함int arr[[100][102]; int arr[1000][1002];→

파스칼의 삼각형 코딩< 2>

#include <stdio.h>

int arr[1000][1002];

int main(void)

int i,j,n,m;

을 이용해서 을 구한다printf("n, m p(n,m) .\n");

과 을 입력하라 은 이하이다printf("n m . n 1000 .\n");

printf("n= ");

scanf("%d", &n);

printf("m= ");

scanf("%d", &m);

for (i=0; i<1000; i++)

for(j=0; j<1002; j++)

arr[i][j]=0;

arr[0][1]=1;

for(i=1; i<1000; i++)

for(j=1; j<1002; j++)

if(arr[i-1][j-1]==0 && arr[i-1][j]==0)

Page 6: 자료구조 프로젝트

break;

arr[i][j]=arr[i-1][j-1]+arr[i-1][j];

if(arr[n-1][m]==0)

잘못 입력하셨습니다printf(" .\n");

else

printf("p(%d,%d)=%d\n", n, m, arr[n-1][m]);

return 0;

파스칼의 삼각형 코딩 수정< 2- >

1 1

배열로 표현하기 용이하도록1 1 ( 1 1

왼쪽 옆으로 밀착1 2 1 ) 1 2 1

1 3 3 1 -------------------------> 1 3 3 1

. .

의 값을 찾아내기 위해서는 우선 적으로 파스칼의 삼각형이 구현 되어져 있어야 한다고 생각하였다p(n,m) .

그리고 왼쪽 끝 쪽에서 아래로 쭉 있는 도 을 적용시켜 구현하기 위해서1 p(n,m) = p(n-1,m-1) + p(n-1,m)

양쪽에 을 붙여주었다0 .

0 1 0

0 1 1 0

0 1 2 1 0

0 1 3 3 1 0

구현 방법에 대해선

을 반복문으로 반복시키기 때문에p(n,m)=p(n-1,m-1)+p(n-1,m)

파스칼 삼각형의 맨 위쪽의 만 지정해주면 아래로 내려가며 계산이 된다1 .

다음 행으로의 행 변환은 문을 통해서 을 구하는 과정에서if p(n,m)

과 의 값을 판단해서 둘 다 일 때 다음 행으로 내려가는 것으로 설정하였다 그 이유p(n-1,m-1) p(n-1,m) 0 .

는 파스칼 삼각형에서 이 나올 이유가 없으므로 계산해야할 위의 행의 값들이 둘 다 인 순간이 계산하던0 0

행의 끝부분에 왔음을 알려주도록 구현을 했다.

배열을 까지 지정하지 않고 입력한 값까지만 계산하도록 하면 공간을 줄일 수 있지 않을까라는 의견이1000

나왔다 그래서 문의 와 의 범위를 수정하였다. for i j .

for(i=1; i<1000; i++) → for(i=1; i<n; i++)

Page 7: 자료구조 프로젝트

for(j=1; j<1002; j++) → for(j=1; j<m; j++)

파스칼의 삼각형 코딩< 3>

#include <stdio.h>

double arr[1000][1000]; 파스칼 삼각형이 구현될 배열//

int main(void)

int i,j;

int n,m;

을 이용해서 을 구한다printf("n , m p(n,m) \n"); 입력 안내// 1

과 을 입력하라 은 이하이다printf("n m n 1000 \n"); 입력 안내// 2

printf("n = "); 입력 유도// n

scanf("%d",&n);

printf("m = "); 입력유도// m

scanf("%d",&m);

arr[0][0]=1; 파스칼 삼각형 꼭대기에 시작하는 을 잡아줌// 1 p(1,1)=1

파스칼 계산 을 이용// p(n,m)=p(n-1,m-1)+p(n-1,m)

for(i=1;i<n;i++)

for(j=0;j<m;j++)

if(arr[i-1][j-1]==0 && arr[i-1][j]==0)

break;

arr[i][j]=arr[i-1][j-1]+arr[i-1][j];

if(arr[n-1][m-1]==0) 파스칼 삼각형에서 이 나올리 없으므로 값이 이 나오면 에 따른// 0 p(n,m) 0 n

의 입력이 잘못된것임m

값 잘못됨 범위이탈printf("m , \n"); 값에 대해 의 입력이 잘못 되었음을 안내//n m

else

printf("p ( %d , %d ) = %.0f\n",n,m,arr[n-1][m-1]); 의 값을 출력// p(n,m)

Page 8: 자료구조 프로젝트

return 0;

파스칼의 삼각형 코딩 수정< 3- >

그리고 파스칼의 삼각형이 하단부로 내려갈수록 값이 얼마나 커질 것인가에 대해 생각해보지 않았던 것이 문

제가 되었다 을 을 로 입력을 했을 때 의 값이 이상한 음수가 되어서 출력이 되었다 이. n 1000, m 5 p(n,m) .

유는 형이 기억할 수 있는 값의 범위를 초과해서였다 그래서int . int arr[1000][1002]; → unsigned int

로 수정을 했지만 결과 값이 잘려서 나왔다 그래서arr[1000][1000]; . unsigned int arr[1000][1000]; →

double 로 더욱 표현 범위를 확장을 해주었다 열혈강의 언어 참고arr[1000][1000]; . ( C p115 )

시간 복잡도(time complexity)

프로그램을 실행시켜 완료하는데 필요한 컴퓨터 시간의 양-

입력 값에 따른 실행 연산의 빈도수-

실제 걸리는 시간 값이 달라지기 쉽다 명령문이 몇 번 실행된지 센 결과- ( .)+

실행시간을 알고 싶을 경우에는 시스템 클럭을 이용하는 것이 좋다- .

초기값이 인 전역변수 를 정의하여 단계수를 알수있다- 0 count .

사용량을 말한다- CPU .

공간 복잡도(space complexity)

프로그램을 실행시켜 완료하는데 필요한 공간의 양-

고정 공간 요구 입출력의 횟수나 크기와 관계 없는 공간 단순 변수 상수들을 위한공간- : ( , )

가변 고정 요구 함수가 순환호출을 할 경우 요구되는 추가 공간- :

의 사용량으로 소스에서 최대로 사용된 공간- RAM

필요 필요 할때 가 배 효율성이우수하다- A(1MB ),B(1KB ) B 1024

점근 표기법

빅오

최악의 경우 알고리즘 수행시간-

시간복잡도 함수에서 가장 큰 영향력을 주는 입력 개수 에 대한 항만을 표시- n( )

최고차항 선택 후 계수 제거 시간복잡도 함수에서 이 커질 경우 가장 큰 영향을 주는 것이 최고차- : n

항이다.

이 증가할수록 보다 항상 스케일이 큰 를 찾는 것- n f(n) g(n)

오메가

최선의 경우를 나타낸다- .

는 적어도 함수 만큼 빠르게 증가하는 함수- (g) gΩ

이 증가할수록 보다 항상 스케일이 작은 를 찾는 것- n f(n) g(n)

Page 9: 자료구조 프로젝트

세타

오메가와 빅오의 교집합 즉 평균적이다- , .

제일 정확하다- .

는 함수 와 같은 비율로 증가하는 함수- (g) gΘ

작성한 소스에서의 공간복잡도와 시간복잡도

공간 복잡도 : double 을 지정을 하여서 이 된다arr[1000][1000] 1000*1000*8=8000000 .

시간 복잡도 입력 받을 값이 이라고 생각을 했다: <n,m> .

처음 문에서 번이 실행이 된다1. for n-1 .

그 다음 문에서는 번 실행이 되지만 이중 문으로 인해서2. for m , for m(n-1)

번 실행이 된다.

처음 문에서는 번이 실행이 된다3. if n*m .

위에서 진행이 된 문에서 실행이 되고 나온 값을 판단을 하기 때문에4. if

번이 실행이 된다m*n .

최고 차항을 찾으면 차가 된다5. 2 .

참고 자료

http://skmagic.tistory.com/164

빅오 표기법http://blog.naver.com/anjindago?Redirect=Log&logNo=150119261447

빅오 분석법http://openparadigm.tistory.com/20

로 쓴 자료구조론 책 참고C p27~34

http://10albatross.tistory.com/27

http://numgo.tistory.com/20

로 쓴 자료구조론 책 참고C p24~27

Page 10: 자료구조 프로젝트

조 자료구조A2

프로젝트 보고서말 의 여행[Project #2 : ( ) ]馬

조장 김형오:

조원 민영지:

박다솔

박우용

Page 11: 자료구조 프로젝트

과제수행일지소속 조장 김형오: 조원 민영지 박다솔 박우용:

A2자료조사 :김형오 박우용,민영지 박다솔,

프로그래밍 :김형오 박우용,

보고서 작성 :박다솔

과제수행기간 일 시간12 8

계획의 작성I.

연구제목 말 의 여행( )馬

연구배경

말의 여행을 통해서 스택 큐 백트래킹의 원리를 알고, , 말이 움직인 행적 지나간 자리( )

을 표시하여 장기판을 다 돌게 하는 프로그램의 알고리즘을 작성 프로그램 소스 코딩,

을 해 보면서 스택 큐 백트래킹에 대해 적용을 할 수 있다, , .

참고자료

참고 서적

윤성우의 열혈 자료구조 언어를 이용한 자료구조 학습서 윤성우 지음(C ) /

오렌지 미디어/

열혈강의 자료구조 이상진 지음 프리렉/ /

언어로 쉽게 풀어쓴 자료구조 천인국 공용해 지음 생능C / , /

참고 URL

http://www.winapi.co.kr/

http://lwove.egloos.com/

http://internet512.chonbuk.ac.kr/datastructure/stack/stackq.htm#/

계획의 실행II.

첫째 날 년 월 일 화요일2012 3 27

오늘의 작업 조원의 업무 분담과 학습할 내용 및 과제에 대한 이해와 숙지

토의 내용

조장 김형오:

자료조사 민영지 박다솔: ,

프로그래밍 김형오 박우용: ,

위와 같이 조원의 업무를 분담했다 프로그래밍과 자료조사를 조원들끼리 나누어서 하.

는 게 효율성은 좋지만 이 프로젝트를 하기 위해서는 스택 큐 백트래킹에 대해 개념, , ,

을 다 알고 이해해야 했기 때문에 효율성보다는 효과성을 택했다 그래서 이 프로젝트.

Page 12: 자료구조 프로젝트

에 대한 소스도 각자 생각해오고 하기로 하였다.

과제준비에서

느낀 점

새로운 프로젝트가 제시가 되고 새로운 조를 편성을 함에 따라 새로 정해야하는 것들이

생겨났고 이러한 것들을 빨리 해결을 하는 것과 동시에 프로젝트의 문제를 파악하고 적

절하게 임무를 분담을 하였다.

둘째 날 년 월 일 토요일2012 3 31

오늘의 작업 각자 조사해온 내용에 대한 토의

토의 내용

말의 여행 프로젝트를 수행하기 위해서는 가장 먼저 이해해야 할 스택과 큐 백드래킹,

을 중심적으로 설명하고 토의를 하였다, .

Stack•

정의 여러 개의 데이터 항목들이 일정한 순서로 나열된 자료 구조- ;

먼저 삽입된 것은 나중에 삭제되고 나중에 삽입된 것이 먼저 삭제된다 한쪽 끝에서만- , .

새로운 항목을 삽입하거나 기존의 항목을 삭제할 수 있도록 고안된 것

실생활의 예 동전을 넣고 뺄 수 있도록 되어 있는 동전 케이스- :

주차장에 주차한 자동차 나보다 나중에 들어온 차들 때문에 나갈 수가 없다 결국 나중( ,

에 들어온 차들이 모두 나갈 때까지 기다린 후에 차를 뺄 수 있다)

*Back traking

검색 공간의 모든 가능한 배치 방법에 대해 어떤 작업을 반복하기 위한 조직적인 방법-

백트래킹은 용도에 맞게 개별적으로 구현해서 써야 하는 범용알고리즘 기법-

함수가 실행되는 것과 비슷한 방식으로 컴퓨터 내부에서 실행이 됨 함수안의 함수- ( )

Queue•

정의 리스트의 한쪽 끝에서는 원소들이 삭제되고 반대쪽 끝에서는 원소들이 삽입만- :

가능하게 만든 순서화된 리스트

실생활의 예 은행에서 순서대로 번호표를 뽑게 하고 일을 처리해주는 예- :

버스정류장에서 먼저 온 순서대로 탑승하는 예

물건을 구매할 때 줄을 서서 계산대에서 계산을 기다리는 예

서로 각자가 공부를 해오고 모르는 것을 서로에게 질문하였고 교수님께서 말씀하신 스,

택과 큐 백트래킹이 실생활에 어디에 사용되는지 생각해보라고 하셔서 조원들이 함께,

생각해보고 교수님께 추가적인 설명들을 듣고 하였다, .

과제준비에서

느낀 점

스택과 큐와 백트래킹에 대해서 찾아보았지만 백트래킹에 대한 내용이 스택과 큐에 비

해서 많이 적었다 그래서 도서관에 가서 자료구조에 대한 정리가 되어있는 책들을 찾.

아보고 백트래킹에 대한 개념을 찾아내긴 했지만 아직 확실하게는 파악을 못하였고 이

로 인해서 백트래킹에 대해서는 다시 한 번 더 조사를 하기로 하였다.

Page 13: 자료구조 프로젝트

셋째 날 년 월 일 화요일2012 4 3

오늘의 작업 말의 여행 소스에 대한 토론

토의 내용

조원들과 함께 이번 프로젝트에서 공부해야 할 개념들을 같이 공부하였고 이제 소스에,

대해 같이 토론하였다 장기판에서 직선으로 한번 갔다가 대각선으로 움직이는 말을 빠.

짐없이 장기판을 다 돌도록 하는 소스에 대해서 같이 고민해보았다 같이 머리를 맞대.

고 고민을 해본 결과 무조건 시계방향으로 돌리고 만약 다시 지나왔던 좌표라면 다시,

백트래킹을 하여서 시계반대방향으로 한번 움직이고 또 다시 시계방향으로 돌리면 되지

않을까 라는 의견과 다른 의견으로는 각 좌표마다 움직일 수 있는 경우의 수를 놓고?

가장 작은 수로 말이 움직이게 하고 그 좌표에서 또 다른 말이 갈 수 있는 가장 작은

경우의 수의 방향으로 움직이다 보면 장기판의 좌표를 다 돌 수 있지 않을까 라는 의?

견과 장기판의 좌표를 랜덤으로 난수를 정해서 돌리면 어떨까 라는 의견이 나왔다? .

과제준비에서

느낀 점

하나의 프로젝트이지만 조원들의 개개인 다른 소스에 대한 생각에 대해 들어보고 같이,

토론하니깐 각자가 생각했던 문제를 보고 파악하는 관점에 넓게 보지 못하고 약간 한정

된 생각을 한다고 느껴졌었는데 서로의 의견에 대해 수정할 부분은 이렇게 수정해 보는

게 어떨까 하면서 서로 의견을 주고받고 하는 과정에서 내가 생각하지 못했던 관점으?

로 문제를 해결하려는 부분이 있었기 때문에 서로가 생각했던 것에 조금 더 플러스 효

과를 본 것 같았다.

넷째 날 년 월 일 토요일2012 4 7

오늘의 작업 말의 여행에 필요한 추가적인 자료 조사 설명과 토의,

토의내용

말의 여행에서 주된 자료조사는 스택 큐 그리고 백트래킹이었다 하지만 수업시간에, .

교수님께서 말씀하셨던 중위표기법과 후위표기법 중위식을 후위식으로 쉽게 바꾸는 방,

법에 대해 추가적으로 자료 조사를 하고 조원들과 함께 이해하며 더 나아가 사람과 컴,

파일러의 계산방식까지 같이 공부하며 토의했다.

중위표기법* (infix expression)

연산자 를 피연산자 가운데 놓는 방법이다1. (operator) (operand) .

피연산자 연산자 피연산자2. 3 * 5 => ( ) ( ) ( )

후위표기법* (postfix notation)

후위표기법은 연산자를 피연산자의 뒤에 놓는 방법이다1. .

후위표기법으로 놓으면 괄호 없이도 계산 순서가 일정하다2. .

괄호가 필요 없으면 계산 순서를 생각할 필요가 없어서 편하다3. .

피연산자 피연산자 연산자4. 3 5 * => ( ) ( ) ( )

괄호가 없어도 우선 순위를 쉽게 알수가 있고 연산자의 우선순위도 생각할 필요가5. ,

없어서 컴파일러가 성호를 하는 방식이다.

예 1) 3 * 5 + 4

Page 14: 자료구조 프로젝트

중위 표기법 -> 3 * 5 + 4

후위 표기법 -> 3 5 * 4 +

예 2) 3 * ( 5 + 4 )

중위 표기법 괄호가 필요하다 를 먼저 계산하려면-> 3 * (5 + 4) => .(5+4 )

후위 표기법 괄호가 필요 없다-> 3 5 4 + * => .

중위식을 후위식으로 쉽게 바꾸는 방법*

중위식에 괄호를 친 다음 연산자를 괄호 뒤로 옮긴 후 괄호를 지운다1. .

피연산자는 출력한다2. (1) .

연산자는 앞 연산자 스택의 맨 위 를 살펴서 출력하거나 대기한다 스택에(2) ( ) .(

넣는다, 대기 된 자료들은 나중에 대기 된 연산자가 먼저 나온다 스택을 이용, )

연산자의 대기 스택에 여부는 연산자간의 우선순위에 따른다(3) ( push) .

괄호 가 있는 경우3. (parenthesis)

왼쪽괄호 무조건 스택에 넣는다(1) .–

오른쪽 괄호의 처리 왼쪽 괄호가 나올 때까지 스택에서 한다(2) pop .–

예 수식 후위표기법으로 변환 후) “a*(b+c)*d ”-> “abc+*d* ”

사람과 컴파일러의 계산방식< >

사람-

연산자의 우선 순위를 정한다 우선순위가 같으면 왼쪽부터인지 오른쪽부터인지1. .

정한다.

연산자는 왼쪽부터이지만 지수 연산자는 오른쪽부터이다(/,*.+,- , .)

복잡하면 괄호를 사용하여 계산하며 중간 결과를 저장한다2. .

(((A/(B**C))+(D*E))-(A*C))

컴퓨터로 수식의 계산-

사람이 하는 방법대로 계산할 수도 있지만 연구 결과 중간 과정을 줄이고 한번에1.

왼쪽에서 오른쪽으로 계산할 수 있는 방법을 개발하였다.

수식을 후위 표기법 으로 바꾼다2. (postfix notation) .

계산하는 방법은 연산자가 나올 때까지 읽어서 연산자의 앞에 있는 피연산자 두개를3.

이용하여 계산하고 그 자리에 저장한다.

과제준비에서

느낀 점

사람이 계산하기에 익숙한 중위표기법과 조금은 생소한 후위표기법에 대해서 자료를 조

사하고 예를 들어서 간단한 문제로 후위표기법을 조금은 이해할 수 있었다.

다섯째 날 년 월 일 일요일2012 4 8

오늘의 작업 말의 여행 초안 소스에 대한 토의

설계 방법

말이 어떠한 방향으로 이동을 해야할까 에 대해서 많은 고민을 했었습니다? .

그러다가 난수를 설정을 하여서 임의로 가도록 해보기도 했지만 결국은 모든 좌표를,

돌아다니지를 못하였습니다 그래서 다른 방법을 고안을 하여 말이 움직이는 방향을 정.

하여서 이곳으로만 이동을 하도록 하는 것보다는 갈수 있는 방향을 제시만을 해주고 범

위에서 벗어나지 않도록만 설정을 하여서 갈수 있는 방향을 찾아가도록 하였다.

Page 15: 자료구조 프로젝트

그리고 더 이상 가지 못하는 경우가 발생하는 것은 갈 수 있는 방향이 가지이니 지정8

해준 범위에서 벗어난 것이 개 이면 더 이상 갈 수가 있는 곳이 없는 거로 설정을 하8

였고 스택에 들어가 있는 좌표을 시켜주어서 새로운 방향을 찾아가도록 하였다, pop .

#include<stdio.h>

#include<stdlib.h>

#define SIZE 9

지나가는 모든곳#define MAX 200//

실제 지나가는곳#define MAXX 90//

지나간 곳을 표기#define MA 90//

int st[MA];

int stackk[MAXX];

int stack[MAX];

int top;

int topp;

int to;

int array[SIZE+1][SIZE];

갈수 인지를 판단int push(int x, int y);//

갈수 있는 모든곳을 푸시int pushh(int x, int y);//

int pushhh(int z);//

int pu(int x);//

int pop(void);

int popp(void);

int poppp(void);

struct element

int h;

int r;

el;

struct countt

int c;

int cc;

int ccc;

카운터용 구조체tmp;//

void init_stack()

스택 포인트 초기화top = -1; //

topp = -1;

to = -1;

Page 16: 자료구조 프로젝트

초안

int main()

int aa,b;

int i,j;

int a,c,d,e,z;

int x,y;

문이 한번 진행이 될 때 마다 하나의 좌표를 가니 카운터를int count=0;//while

해서 조건설정

의 값을 반환받음int re,rr=0;//result

시작행을 입력printf(" : ");

scanf("%d",&aa);

el.r = aa;

시작열을 입력printf(" : ");

scanf("%d",&b);

el.h = b;

시작printf(" : <%d,%d>\n",aa,b);

for(i=0; i<SIZE+1; i++)

for(j=0; j<SIZE; j++)

array[i][j] = (i*10)+j;

배열에 값을 넣어줌//

는 실제로 갈 수 있는 모든 좌표 즉 실제로 이동을 하while(topp != 89)//topp

는 곳

x=el.h; y=el.r;

z= array[x][y];

비교를 할 스택pu(z);// (st)

push(x+1,y+2);

push(x+2,y+1);

push(x+2,y-1);

push(x+1,y-2);

push(x-1,y-2);

push(x-2,y-1);

push(x-2,y+1);

push(x-1,y+2);

모든 길로 갈수가 없을 때re = tmp.c + tmp.cc;// /

if(re == 8)

Page 17: 자료구조 프로젝트

스택 실제로 지나가는 곳poppp();//st[to] ( )

스택 나중에 나타내기 위한 스택popp();//stackk[topp] ( )

갈 수 있는 모든 곳이 저장된 다음 그중 제일 위에 있는a = pop();//

좌표

el.h = a/10;

된 값을 행과 열로 변환el.r = a%10;//return

스택에 저장pushhh(a);//stackk

초기화tmp.c=tmp.cc=0;//

마지막에 나타내기 위해서for(i=topp; i>0; i--)//

c = stackk[i]/10;

d = stackk[i]%10;

printf("<%d, %d> ",d,c);

return 0;

int push(int x, int y)

int i;

int c=0,co=0;

확실히 갈수가 없는 곳들if(x<0 || y<0 || x>SIZE || y>SIZE-1)//

c++;

tmp.c = tmp.c+c;

return;

for(i=0; i<=to; i++)

실제로 가는 곳이 저장이 된 스택과 비교if(array[x][y] == st[i])//

co++;

tmp.cc = tmp.cc+co;

return;

pushh(x,y);

Page 18: 자료구조 프로젝트

int pushh(int x, int y)

스택이 오버 플로우인지 체크if(top >= MAX-1) //

넘침printf("Stack .\n");

return -1;

else

top++;

stack[top] = array[x][y];

return;

int pop(void)

if(top < 0)

스택이 비어있습니다printf(" \n");

exit(1);

return stack[top--];

실제로 가는 곳int pushhh(int z)//

값을 골라 낼 필요는 없다// .

topp++;

stackk[topp] = z;

return stackk[topp];

현재의 위치를 저장int pu(int x)//

to++;

st[to] = x;

return st[to];

Page 19: 자료구조 프로젝트

int popp(void)

if(topp < 0)

스택이 비어printf(" \n");

exit(1);

return stackk[topp--];

int poppp(void)

to--;

return st[to];

문제점더이상 갈 곳이 없을 경우 백트래킹은 하지만 확실한 길을 찾아 가지를 못해서 중복되

는 좌표가 생긴다.

해결방안백트래킹을 하는 좌표를 따로 스택에 저장을 시키고 실제 이동할 거리를 비교를 하면서

되돌아왔던 곳으로 더이상 가지 않도록 한다.

결과III.

최종 프로그램

소스

#include<stdio.h>

#include<stdlib.h>

#define SIZE 9

지나가는 모든곳#define MAX 500//

실제 지나가는곳#define MAXX 90//

지나간 곳을 표기#define MA 90//

int st[MA];

int stackk[MAXX];

int stack[MAX];

int sta[100];

int top;

int topp;

int to;

int t;

int array[SIZE+1][SIZE];

갈수 인지를 판단int push(int x, int y);//

갈수 있는 모든곳을 푸시int pushh(int x, int y);//

Page 20: 자료구조 프로젝트

int pushhh(int z);//

int pu(int x);//

int pop(void);

int popp(void);

int poppp(void);

int pud(void);

int pus(int x);

struct element

int h;

int r;

el;

struct countt

int c;

int cc;

int ccc;

int cccc;

int ccccc;

카운터용 구조체tmp;//

void init_stack()

스택 포인트 초기화top = -1; //

topp = -1;

to = -1;

t = -1;

int main()

int aa,b;

int i,j;

int a,c,d,e,z;

int x,y;

문이 한번 진행이될때 마다 하나의 좌표를가니 카운터를 해int count=0;//while

서 조건설정

의 값을 반환받음int re,rr=0,cc=0;//result

시작행을 입력printf(" : ");

scanf("%d",&aa);

el.r = aa;

시작열을 입력printf(" : ");

scanf("%d",&b);

Page 21: 자료구조 프로젝트

el.h = b;

시작printf(" : <%d,%d>\n",aa,b);

for(i=0; i<SIZE+1; i++)

for(j=0; j<SIZE; j++)

array[i][j] = (i*10)+j;

배열에 값을 넣어줌//

는 실제로 갈수있는 모든 좌표 즉 실제로 이동을 하는while(topp != 89)//topp

x=el.h; y=el.r;

z= array[x][y];

비교를 할 스택pu(z);// (st)

push(x+2,y+1);

push(x+1,y+2);

push(x+1,y-2);

push(x+2,y-1);

push(x-2,y-1);

push(x-1,y-2);

push(x-2,y+1);

push(x-1,y+2);

모든길로 갈수가 없을떄re = tmp.c + tmp.cc +tmp.ccccc ;// /

if(re == 8)

a = popp();

pus(a);

poppp();//st

rr++;

tmp.ccc = tmp.ccc +rr;

pop();

else

if(tmp.ccc == 2)

pop();

tmp.ccc=0 , rr=0;

Page 22: 자료구조 프로젝트

갈수있는 모든 곳이 저장된다음 그중 제일위에있a = pop();//

는 좌표

tmp.c = tmp.cc = tmp.ccccc=0;

el.h = a/10;

된 값을 행과열로 변환el.r = a%10;//return

스택에 저장pushhh(a);//stackk

마지막에 나타내기 위해서for(i=topp; i>0; i--)//

c = stackk[i]/10;

d = stackk[i]%10;

printf("<%d, %d> ",d,c);

return 0;

int push(int x, int y)

int i,j;

int c=0,co=0,cc=0;

확실히 갈수가 없는곳들if(x<0 || y<0 || x>SIZE || y>SIZE-1)//

c++;

tmp.c = tmp.c+c;

return;

for(i=0; i<=to; i++)

실제로 가는 곳이 저장이된 스택과 비교if(array[x][y] == st[i])//

co++;

tmp.cc = tmp.cc+co;

return;

for(j=0; j<=t; j++)

Page 23: 자료구조 프로젝트

if(array[x][y] == sta[j])

cc++;

tmp.ccccc = tmp.ccccc+cc;

return;

pushh(x,y);

int pushh(int x, int y)

스택이 오버 플로우인지 체크if(top >= MAX-1) //

넘침printf("Stack .\n");

return -1;

else

top++;

stack[top] = array[x][y];

return;

int pop(void)

if(top < 0)

스택이 비어있습니다printf(" \n");

exit(1);

return stack[top--];

실제로 가는곳int pushhh(int z)//

값을 골라 낼 필요는 없다// .

topp++;

stackk[topp] = z;

Page 24: 자료구조 프로젝트

return stackk[topp];

현재의 위치를 저장int pu(int x)//

to++;

st[to] = x;

return st[to];

int popp(void)

if(topp < 0)

스택이 비었습니다printf(" .\n");

exit(1);

return stackk[topp--];

int poppp(void)

to--;

return st[to];

int pus(int x)

t++;

sta[t] = x;

return sta[t];

int pud(void)

t--;

return sta[t];

반성.Ⅳ

과제를 마치면서

느낀 점

각자 조원들이 자료를 조사해오고 같이 토의하면서 모르는 것을 질문하고 가르쳐 줌으

로써 스스로 공부해오고 알아가는 프로젝트 과제의 장점을 느낄 수 있었다 개개인이.

조사해오는 자료마다 조금씩 달라서 조원이 다 같이 이해하고 정보를 습득 하는 데에서

는 시간이 지체되었고 살짝 어려움이 있었다 하지만 이 부분도 프로젝트의 단점이라고, .

Page 25: 자료구조 프로젝트

생각 할 수 있겠지만 어떻게 보면 장점이라고 생각 할 수도 있었다 프로젝트를 언어. C

로 코딩을 해야 하는 점에서 아직 조원들이 많이 부족하다는 것을 느낄 수 있었고조금,

더 공부하고 더 연습해야겠다는 것을 몸소 느꼈고 매 수업시간마다 그리고 온라인으로,

만나는 시간마다 회의를 할 때 회의록을 작성하여서 보고서의 질을 좀 더 높일 수 있었

을 텐데 라는 아쉬움이 남았다.…

Page 26: 자료구조 프로젝트

프로젝트 보고서B0 #3

조장 오승원09

팀원 김형오09

장진승09

성주희11

정상혁11

문제 파악*

링크드 리스트를 이용하여 다항식 를 다루는 프로그램을 작성 시간 공간복잡도를 구함P(x) , /

링크드 리스트의 정의 밑 사용법에 대한 이해-

만든 프로그램에서의 시간 공간복잡도에 대한 이해- /

일정*

일 월 화 수 목 금 토

일12 일13 일14

로쓴 자료구조론 리스트 다항식C ( , )

부분 익히기 자료조사하기,

일15 일16 일17 일18 일19 일20 일21

각자 알고리즘 구상15,16 /

변수명 통일 파트분담17 / ,각자 파트 코딩 보고서 구상,

코드

통합

일22 일23 일24

최종점검보고서

완성최종발표

참고자료* 로작성한 실용자료구조 경문사 로쓴 자료구조론 교보문고 그림으로 배우는: C ( ) , C ( ) , easy언어 영진닷컴C ( )http://internet512.chonbuk.ac.kr/datastructure/link/list8.htmhttp://blog.naver.com/pjy9954?Redirect=Log&logNo=70128298541http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Database/DataStructure/LinkedList

역할 분담 팀원

자료조사 및 이해오승원 김형오 장진승09 , ,

성주희 정상혁11 ,

코딩오승원 김형오09 ,

보고서 장진승09

Page 27: 자료구조 프로젝트

링크드 리스트란?

링크드 리스트는 각 데이터를 서로 연결해서 관리하며 이때 각각의,

데이터를 노드 라고 불리우는 에 넣어서 관리한다 스택이나 큐와 같은 경우(node) Unit .

각 위치에 데이터자체가 저장되는 것과는 약간다르다 이처럼 데이터를 노드에 넣어.

서 관리하는 이유는 데이터의 리스트를 유지하기 위해서 데이터외에도 다음 데이터의

위치를 나타낼수 있는 어떤 부가적인 정보가 필요하기 때문이다.

링크드 리스트의 종류

싱글 링크드리스트 단일 연결리스트1) ( )

각 노드는 저장하고자할 데이터와 다음 노드를 가리키는 포인터를 포함한다 싱글링.

크드리스트에서 각 노드는 다음노드의 위치를 가리키기 때문에 우리는 반드시 시작,

노드의 위치를 알고 있어야만 할것이다 또한 이전노드의 위치는 알수없도록 되어 있.

다.

이중 연결리스트2)

다음노드를 가리키는 하나의 포인터만 가지고 있는 싱글링크드리스트와는 달리 이전

노드를 가리키는 포인터도 가지고 있다 전방향 후방향어느 쪽으로든지 순환이 가능. ,

한 링크드리스트이다.

환형 연결리스트3)

환형 연결 리스트에서는 노드의 시작과 끝을 구별하지 않음으로써 마지막 노드와 처

음 노드가 연결되어 있음으로 임의의 노드에서 다른 모든 노드로의 접근이 가능하여

임의 노드의 검색이 가능하게 된다 단순 연결 리스트의 경우 정보가 끊어지면 그 다.

음은 찾을 수가 없는데 환형 연결 리스트는 그것을 극복할 수 있다.

링크드 리스트의 구조

데이터의 위치를 나타내기 위해서 사용할수 있는것은 가 될것이다 즉 노드는pointer .

데이터와 함께 다음 데이터의 위치정보를 가지고 있는 포인터 를 포함하게 된다" " .

리스트의 구현방법

배열을 이용장점 구현이 간단하다:

단점 크기에 제한이 있다 삽입과 삭제시 오버헤드가 발생한다: ,

포인터를 이용장점 크기에 제한이 없다:

단점 구현이 복잡하다:

배열 스택 큐 과( , )

비교되는

링크드 리스트의

특징

배열의 경우 연속적인 공간에 위치함으로 특정위치에 있는 데이터에 접근하고자 할때

의 시간이 소모된다 링크드리스트의 경우 의 시간이 소모된다 처음노드부O(1) . O(N) .

터 순환을 해야하기 때문이다.

배열의 경우 처음과 마지막에 데이터를 삽입하는건 매우 쉽고 효율적이지만 중간에

있는 데이터를 삭제하거나 삽입하는건 상대적으로 어렵고 비효율적이다 링크드 리스, .

트는 이러한 경우 매우 효율적이다.

배열의 경우 일단 만들어진 사이즈를 조정할 수 없으나 링크드리스트는 자유롭게 사

이즈를 조정할 수 있다.

링크드리스트의

장단점

장점 새로운 노드의 추가 삽입 삭제가 쉽고 빠르다, ,

단점

다음 링크를 가리키는 포인터가 씩 잡아먹는다4Byte

첫 노드부터 마지막 노드까지 순서대로 검색을 하기 때문에 최악의 경우 배,

열보다 자료를 검색하는데 들어가는 시간이 더 걸릴 수 있다.

Page 28: 자료구조 프로젝트

일정별 토의 내용*날짜 토의 내용

목4/12( )

이번 프로젝트의 조장을 정함*

이번 프로젝트를 할 때 전체적인 일정을 정함*

토의 일정을 화 목 시부터 수업시간 전까지로 정하고 따로 한 번- , 9

더 만 날 일이나 토의할 내용이 있으면 네이트온을 통해서 만나기

로 결정

다음 모임 전까지 각자 링크드 리스트에 대해 공부를 하고 공부를 하*

면서 봤던 자료 중 정리가 잘 돼있다고 생각되는 자료를 공유하기로

결정

화4/17( )

목요일부터 링크드리스트에 대해 각자 조사 했던 것을 공유*

각자 다항식에 대해 구상했었던 알고리즘에 대한 토의*

변수명을 와 는 각각 라 두고 계수와 차수에 대해서는- P(x) S(x) P,S

각각 으로 하기로 결정a1,n1

덧셈 뺄셈 곱셈은 덧셈으로 모아지는 모양새를 발견함- , ,

나눗셈에 대한 결론은 내리지 못하였음-

입력 부분에 대해서는 각자 소스를 짜보면서 각자 생각한대로 해-

보기로 결정

식 전체를 입력 받고 그 식에서 계수와 차수를 추출 연산에 사용하* ,

는 방식을 사용하기로 결정

각 파트별로 역할을 결정*

덧셈 성주희 뺄셈 김형오 곱하기 오승원 나눗셈 정상혁- : 11 , : 09 , : 09 , : 11

보고서 작성 장진승- : 09

목4/19( )

사칙 연산에 대해 각자 파트를 나눠 구상 작성 하기로 하였으나 입력* /

부분이 해결되지 않아서 인지 어떻게 해결하고 작성해야 하는지에 대

한 구상은 일정부분 고민을 많이 해온 듯 하지만 작성까지 진행 되지

못하였음

입력 부분에서 생각의 전환이 생김*

김형오가 전체를 입력 받고 계수와 차수를 추출하여 이용하는 입- 09

력 부분 코딩 구상

오승원이 계수와 차수만을 입력 받는 부분의 입력 코딩 구상 작- 09 /

교수님의 조언에 따라 다항식 전체를 입력받고 그 입력 받은 부분-

에서 필요한 부분을 추출 해내는 방식에서 계수와 차수 이 두 가지

를 받는 쪽으로 변경함 다항식의 변수 같은 경우는 누구나 다 아는( x

일반적인 사실이므로 결국 실질적으로 계산되는 계수와 차수만을

입력 받으면 되는 것이고 출력에서는 까지 나타나는 완벽한 다항x

식을 출력하면 되는 것)

입력 부분을 확실히 정하였으므로 남은 기간 입력 부분과 연계하여*

각 파트에 대한 코딩을 완성시키기로 결정

Page 29: 자료구조 프로젝트

소스코드*

파트별-

입력부분

while(1) 첫 번째 식//

printf( 입력" 1 : ");

scanf("%d %d",&a,&n); 계수 와 차수 를 입력// (a) (n)

if(a==0) break

node(&list1,a,n); 입력받은 계수와 차수로 리스트 생성//

printf("\n");

while(1) 두 번째 식//

printf( 입력" 2 : ");

scanf("%d %d",&a,&n); 계수 와 차수 를 입력// (a) (n)

if(a==0) break;

node(&list2,a,n); 입력받은 계수와 차수로 리스트 생성//

arra(&list1, &list3);

arra(&list2, &list4); 식을 차수를 통해 내림차순 정렬//

리스트 생성리스트를 생성하는 함수//

void node(ListHeader *plist, int a, int n)

ListNode *temp = (ListNode *)malloc(sizeof(ListNode));

if(temp == NULL)

printf( 메모리할당에러" ");

exit(1);

temp->a1 = a;

temp->n1 = n;

temp->link = NULL;

if(plist->tail == NULL)

plist->head = plist->tail = temp;

else

plist->tail->link = temp;

plist->tail = temp;

Page 30: 자료구조 프로젝트

덧셈덧셈을 하는 함수//

void add(ListHeader *plist1, ListHeader *plist2, ListHeader *plist3)

ListNode *a = plist1->head;

ListNode *b = plist2->head;

int sum;

while(a != NULL && b != NULL)

if(a->n1 == b->n1) 차수비교//

sum = a->a1 + b->a1;

if(sum != 0)

node(plist3, sum, a->n1);

a=a->link;

b=b->link;

else if(a->n1 > b->n1)

node(plist3, a->a1, a->n1);

a=a->link;

else

node(plist3, b->a1, b->n1);

b=b->link;

위의 계산 후 남아 잇는 모든 항들을 다항식에 복사//

for(; a != NULL; a=a->link)

node(plist3, a->a1, a->n1);

for(; b != NULL; b=b->link)

node(plist3, b->a1, b->n1);

뺄셈뺄셈을 하는 함수//

void sub(ListHeader *plist1, ListHeader *plist2, ListHeader *plist3)

ListNode *a = plist1->head;

ListNode *b = plist2->head;

int sum;

while(a != NULL && b != NULL)

if(a->n1 == b->n1) 차수비교//

Page 31: 자료구조 프로젝트

sum = a->a1 - b->a1;

if(sum != 0)

node(plist3, sum, a->n1);

a=a->link;

b=b->link;

else if(a->n1 > b->n1)

node(plist3, a->a1, a->n1);

a=a->link;

else

node(plist3, -b->a1, b->n1);

b=b->link;

위의 계산후 남아 잇는 모든 항들을 다항식에 복사//

for(; a != NULL; a=a->link)

node(plist3, a->a1, a->n1);

for(; b != NULL; b=b->link)

node(plist3, -b->a1, b->n1);

곱셈곱셈을 하는 함수//

void mul(ListHeader *plist1, ListHeader *plist2, ListHeader *plist3)

ListNode *a = plist1->head;

ListNode *b = plist2->head;

int sum,summ;

for(;a != NULL; a=a->link)

for (; b != NULL; b=b->link)

sum = a->a1 * b->a1;

summ = a->n1 + b->n1;

node(plist3, sum, summ);

b = plist2->head;

나눗셈나눗셈을 하는 함수//

void dive(ListHeader *plist1, ListHeader *plist2, ListHeader *plist9, ListHeader

Page 32: 자료구조 프로젝트

*plist10, ListHeader *plist11, ListHeader *plist12)

ListNode *a = plist1->head;

ListNode *b = plist2->head;

int fu;

int fuu;

if((a->n1)>(b->n1)) 차수비교 가장 높은 차수끼리 나눗셈//

fu=(a->a1)/(b->a1);

fuu=(a->n1)-(b->n1);

node(plist9,fu,fuu);

node(plist12,fu,fuu);

mul(plist2,plist9,plist10);

sub(plist1,plist10,plist11);

else if((a->n1)<(b->n1)) 나머지 차수 비교//

return;

else if((a->n1)==(b->n1))

if((a->a1)<(b->a1))

return

else if((a->a1)>=(b->a1))

fu=(a->a1)/(b->a1);

fuu=(a->n1)-(b->n1);

node(plist9,fu,fuu);

node(plist12,fu,fuu);

mul(plist2,plist12,plist10);

sub(plist1,plist10,plist11);

if(plist11->head->n1 >= plist2->head->n1) 더 나누기 위한 작업//

plist1->tail=plist1->head;

plist1->tail=NULL;

plist1->head->a1=NULL;

plist1->head->n1=NULL;

plist1->head->link=NULL;

plist12->head=plist12->tail=NULL;

plist10->head=plist10->tail=NULL;

dive(plist11,plist2,plist9,plist10,plist1,plist12); 더 나누기 위한//

호출

co++;

Page 33: 자료구조 프로젝트

차수 비교를 통한 내림차순 정렬식을 차수를 통해 내림차순 정렬해주는 함수//

void arra(ListHeader *plist, ListHeader *plist1)

ListNode *a = plist->head;

int la=0;

int sum=0;

int count = 0 ;

for(; a != NULL; a = a->link)

if(la < a->n1)

la = a->n1;

a = plist->head;

while(la >= 0)

for(; a != NULL; a=a->link)

if(la == a->n1)

sum = a->a1 + sum;

count++;

if(count > 0)

node(plist1,sum,la);

a = plist->head;

count=0;

sum=0;

la--;

출력void print(ListHeader *plist)

ListNode *p=plist->head;

for(;p != NULL; p=p->link)

printf("%d %d\n",p->a1,p->n1);

Page 34: 자료구조 프로젝트

전체-#include<stdio.h>

#include<string.h>

#include<stdlib.h>

int co=0;

typedef struct ListNode

int a1;

int n1;

struct ListNode *link;

ListNode; 노드에서의 종류//

typedef struct ListHeader

ListNode *head; 리스트 헤드//

ListNode *tail; 리스트 꼬리//

ListHeader; 리스트의 앞과 뒤를 고려//

void init(ListHeader *plist); 초기화//

void node(ListHeader *plist, int a, int n); 리스트생성//

void print(ListHeader *plist); 결과를 출력//

void mul(ListHeader *plist1, ListHeader *plist2, ListHeader *plist3); 곱하기//

void add(ListHeader *plist1, ListHeader *plist2, ListHeader *plist3); 더하기//

void sub(ListHeader *plist1, ListHeader *plist2, ListHeader *plist3); 빼기//

void dive(ListHeader *plist1, ListHeader *plist2, ListHeader *plist9, ListHeader *plist10, ListHeader

*plist11, ListHeader *plist12); 나누기//

void arra(ListHeader *plist, ListHeader *plist1); 식을 차수를 통해 내림차순//

int main()

ListHeader list1;

ListHeader list2;

ListHeader list3;

ListHeader list4;

ListHeader list5;

ListHeader list6;

ListHeader list7;

ListHeader list8;

ListHeader list9;

ListHeader list10;

ListHeader list11;

ListHeader list12;

int a,n;

init(&list1);

init(&list2);

init(&list3);

init(&list4);

init(&list5);

Page 35: 자료구조 프로젝트

init(&list6);

init(&list7);

init(&list8);

init(&list9);

init(&list10);

init(&list11);

init(&list12);

while(1) 첫 번째 식 입력//

printf( 입력" 1 : ");

scanf("%d %d",&a,&n);

if(a==0) break;

node(&list1,a,n); 입력받은 계수와 차수로 리스트 생성//

printf("\n");

while(1) 두 번째 식 입력//

printf( 입력" 2: ");

scanf("%d %d",&a,&n);

if(a==0) break;

node(&list2,a,n); 입력받은 계수와 차수로 리스트 생성//

arra(&list1, &list3);

arra(&list2, &list4); 식을 차수를 통해 내림차순//

printf( 더하기"\n \n");

add(&list3,&list4,&list5); 정렬된 두 식의 덧셈//

print(&list5);

printf( 빼기"\n\n \n");

sub(&list3,&list4,&list6); 정렬된 두 식의 뺄샘//

print(&list6);

printf( 곱하기"\n\n \n");

mul(&list3,&list4,&list7); 정렬된 두 식의 곱셈//

arra(&list7,&list8);

print(&list8);

printf( 나누기"\n\n \n");

print(&list3);

dive(&list3,&list4,&list9,&list10,&list11,&list12); 정렬된 두 식의 나눗셈//

printf(" = ( ");

print(&list9);

printf(" ) * ( ");

print(&list4);

printf(" ) + ( ");

if(co%2==0)

print(&list3);

else

print(&list11);

Page 36: 자료구조 프로젝트

printf(" )");

return 0;

초기화 함수//

void init(ListHeader *plist)

plist->head = plist->tail = NULL;

결과 다항식을 출력하는 것//

void print(ListHeader *plist)

ListNode *p=plist->head;

for(;p != NULL; p=p->link)

if(p!=(plist->head) && (p->a1)>0)

printf(" + ");

if(p!=(plist->head) && (p->a1)<0)

printf(" ");

if((p->n1)!=0)

printf("%dx^%d",p->a1,p->n1);

else if((p->n1)==0)

printf("%d",p->a1);

리스트를 생성하는 함수//

void node(ListHeader *plist, int a, int n)

ListNode *temp = (ListNode *)malloc(sizeof(ListNode));

if(temp == NULL)

printf( 메모리할당에러" ");

exit(1);

temp->a1 = a;

temp->n1 = n;

temp->link = NULL;

if(plist->tail == NULL)

plist->head = plist->tail = temp;

else

plist->tail->link = temp;

plist->tail = temp;

Page 37: 자료구조 프로젝트

곱셈을 하는 함수//

void mul(ListHeader *plist1, ListHeader *plist2, ListHeader *plist3)

ListNode *a = plist1->head;

ListNode *b = plist2->head;

int sum,summ;

for(;a != NULL; a=a->link)

for (; b != NULL; b=b->link)

sum = a->a1 * b->a1;

summ = a->n1 + b->n1;

node(plist3, sum, summ);

b = plist2->head;

덧셈을 하는 함수//

void add(ListHeader *plist1, ListHeader *plist2, ListHeader *plist3) 더하기 계산//

ListNode *a = plist1->head;

ListNode *b = plist2->head;

int sum;

while(a != NULL && b != NULL)

if(a->n1 == b->n1) 차수비교//

sum = a->a1 + b->a1;

if(sum != 0)

node(plist3, sum, a->n1);

a=a->link;

b=b->link;

else if(a->n1 > b->n1)

node(plist3, a->a1, a->n1);

a=a->link;

else

node(plist3, b->a1, b->n1);

b=b->link;

위의 계산후 남아있는 모든 항들을 다항식에 복사//

for(; a != NULL; a=a->link)

node(plist3, a->a1, a->n1);

for(; b != NULL; b=b->link)

node(plist3, b->a1, b->n1);

식을 차수를 통해 내림차순정렬 해주는 함수//

Page 38: 자료구조 프로젝트

void arra(ListHeader *plist, ListHeader *plist1)

ListNode *a = plist->head;

int la=0;

int sum=0;

int count = 0 ;

for(; a != NULL; a = a->link)

if(la < a->n1)

la = a->n1;

a = plist->head;

while(la >= 0)

for(; a != NULL; a=a->link)

if(la == a->n1)

sum = a->a1 + sum;

count++;

if(count > 0)

node(plist1,sum,la);

a = plist->head;

count=0;

sum=0;

la--;

뺄셈을 하는 함수//

void sub(ListHeader *plist1, ListHeader *plist2, ListHeader *plist3)

ListNode *a = plist1->head;

ListNode *b = plist2->head;

int sum;

while(a != NULL && b != NULL)

if(a->n1 == b->n1) 차수 비교//

sum = a->a1 - b->a1;

if(sum != 0)

node(plist3, sum, a->n1);

a=a->link;

b=b->link;

Page 39: 자료구조 프로젝트

else if(a->n1 > b->n1)

node(plist3, a->a1, a->n1);

a=a->link;

else

node(plist3, -b->a1, b->n1);

b=b->link;

위의 계산후 남아 있는 항들을 다항식에 복사//

for(; a != NULL; a=a->link)

node(plist3, a->a1, a->n1);

for(; b != NULL; b=b->link)

node(plist3, -b->a1, b->n1);

나눗셈을 하는 함수//

void dive(ListHeader *plist1, ListHeader *plist2, ListHeader *plist9, ListHeader *plist10, ListHeader

*plist11, ListHeader *plist12)

ListNode *a = plist1->head;

ListNode *b = plist2->head;

int fu;

int fuu;

if((a->n1)>(b->n1)) 차수비교 가장 높은 차수끼리 나눗셈//

fu=(a->a1)/(b->a1);

fuu=(a->n1)-(b->n1);

node(plist9,fu,fuu);

node(plist12,fu,fuu);

mul(plist2,plist9,plist10);

sub(plist1,plist10,plist11);

else if((a->n1)<(b->n1)) 나머지 차수 비교//

return;

else if((a->n1)==(b->n1))

if((a->a1)<(b->a1))

return

else if((a->a1)>=(b->a1))

fu=(a->a1)/(b->a1);

fuu=(a->n1)-(b->n1);

node(plist9,fu,fuu);

node(plist12,fu,fuu);

mul(plist2,plist12,plist10);

sub(plist1,plist10,plist11);

Page 40: 자료구조 프로젝트

if(plist11->head->n1 >= plist2->head->n1) 더 나누기 위한 작업//

plist1->tail=plist1->head;

plist1->tail=NULL;

plist1->head->a1=NULL;

plist1->head->n1=NULL;

plist1->head->link=NULL;

plist12->head=plist12->tail=NULL;

plist10->head=plist10->tail=NULL;

dive(plist11,plist2,plist9,plist10,plist1,plist12); 더 나누기 위한 호출//

co++;

\

출력결과 00

Page 41: 자료구조 프로젝트

출력결과 01

출력결과 02

Page 42: 자료구조 프로젝트

활동 보고서B0 #4

조장 정상혁11

팀원 김형오09

오승원09

장진승09

박다솔11

문제 파악*

트리를 이용하여 상호참조 생성기를 만들고 시간 공간복잡도를 구한다/ .

트리의 정의 밑 사용법에 대한 이해-

만든 프로그램에서의 시간 공간복잡도에 대한 이해- /

일정*

일 월 화 수 목 금 토

일8 일9 일10 일11 일12

트리의 정의 및 종류에

대해 조사하기/

트리 소스 찾아보기

구조체

모양 통일

트리 완성하기11~13

보고서 구상/

일13 일14 일15 일17 일18

정렬 탐색, ,

출력 부분

완성하기

보고서

완성최종발표

참고자료* 로쓴 자료구조론 교보문고: C ( )http://blog.naver.com/hkn10004?Redirect=Log&logNo=20109208779http://blog.naver.com/rlakk11?Redirect=Log&logNo=60159303809http://lazypaul.tistory.com/222

역할 분담 팀원

자료조사 및 이해 장진승 박다솔09 11

코딩오승원 김형오09 ,

박다솔11

보고서 장진승 정상혁09 11

Page 43: 자료구조 프로젝트

트리*

트리란?

비선형 계층적 자료구조이다,

개 이상의 유한한 개수의 노드의 집합1

루트 노드와 개 이상의 겹치지 않는 하위 나무 구조들의 집합으로 이0

루어짐

와 로 구성Node Link

예)

트리의 용어

Node(=vertex

)정보를 나타냄

Link(=edge) 노드의 연결관계를 나타냄Root Node 부모가 없는 최상위 노드

Leaf Node 자식이 없는 최하위 노드 단말노드라고도 부름( )P-Node 부모 노드 어느 특정 노드의 상위에 있는 노드( )

C-Node 자식 노드 어느 특정 노드의 하위에 있는 노드( )Path 링크에 의해 연결된 노드들의 집합Sub tree 트리의 부분 집합 큰 에 속한 작은( tree tree)

Level부터 까지의 중첩되지 않은 의root node Leaf node path

개수node

Degree 하위 의 개수sub tree의 차Node

수트리에 있는 노드의 최대 차수

트리의 종류

이원 탐색트리 트리레드 블랙 트리 스플레이 트리AVL , - ,

다원 탐색트리 원 탐색 트리 트리 트리m- ,B- ,B⁺이진트리 트리,N-ary

이진 트리란? 자식 노드의 수가 최대 개인 트리2이진 트리의

성질

레벨이 일 때 최대 노드의 수는i 2i-1 이다(i 1) .≥⁺깊이가 일 때 최대 노드 수는k 2k 이다(k 1) .≥

이진 트리의

모양

편향 트리한쪽으로 기울어진 트리 리스트와 비슷하나 메모리를[

더 많이 잡아먹는다 시간복잡도가 이다, O(n) ]완전 이진트

마지막 레벨을 제외한 자식노드가 순차적으로 꽉 차

있는 트리포화 이진트

리마지막 레벨까지 완전한 모양을 유지하는 트리

Page 44: 자료구조 프로젝트

이진트리의 순회

중위 순회왼쪽자식 뿌리 오른쪽 자식 일반적으로 사용 되는-> -> (

식과 같은 방법으로 출력된다) ex) A/B*C*D

전위 순회뿌리 왼쪽 자식 오른쪽 자식 순 전위 표기법으로 출-> -> (

력이 된다) ex) +**/ABCD

후위 순회왼쪽자식 오른쪽 자식 뿌리 후위 표기법으로 출력이-> -> (

된다) ex) AB/C*D*레벨순서순회 노드의 순서대로 방문 ex) **D/CAB

트리AVL

트리는 와 에 의해 년에 제안된 트AVL Adelson-Velskii Landis 1962

리로서 각 노드에서 왼쪽 서브 트리의 높이와 오른쪽 서브 트리의 높

이 차이가 이하인 이진 탐색 트리를 말한다 트리는 트리가 비1 . AVL

균형 상태로 되면 스스로 노드들을 재배치하여 균형 상태로 만든다.

시간 복잡도가 이 된다O(log n) .₂

균형인수란 왼쪽서브트리의 높이 오른쪽 서브트리의 높이 로 정의( - )

된다 모든 노드의 균형인수가 이하이면 트리이다. ±1 AVL .

트리에서AVL

회전 방법

새로 삽입된 노드를 가장 가까우면서 균형인수가 가 된 조상 노N, ±2

드를 라고 할 때A

타입 이 의 왼쪽 서브트리의 왼쪽에 삽입되는 경우 노드(1)LL : N A (A

의 왼쪽노드의 왼쪽에 삽입)

타입 이 의 왼쪽 서브트리의 오른쪽에 삽입되는 경우(2) LR : N A (A

노드의 왼쪽노드의 오른쪽에 삽입)

타입 이 의 오른쪽 서브트리의 오른쪽에 삽입되는 경우(3) RR : N A (A

노드의 오른쪽노드의 오른쪽에 삽입)

타입 이 의 오른쪽 서브트리의 왼쪽에 삽입되는 경우 노(4) RL : N A (A

드의 오른쪽노드의 왼쪽에 삽입)

LL RR,LR RL↔ ↔

불균형 트리를

균형 트리로

만드는 법

탐색 순서를 유지하면서 부모와 자식 원소의 위치를 교환하면 된다.

회전 부터 까지의 경로상의 노드들을 오른쪽으로 회전LL : A N

회전 부터 까지의 경로상의 노드들을 왼쪽 오른쪽으로 회전LR : A N -

회전 부터 까지의 경로상의 노드들을 왼쪽으로 회전RR : A N

회전 부터 까지의 경로상의 노드들을 오른쪽 왼쪽으로 회전RL : A N -

단일 회전 불균형을 바로 잡는 변환: LL,RR

이중 회전 불균형을 바로 잡는 변환: RL,LR

레드 블랙트리-

성질

모든 노드는 빨간색 아니면 검은색이다.

루트 노드는 검은색이다.

잎 노드는 검은색이다.

빨간 노드의 자식들은 모두 검은색이다 하지만 검은색 노드의 자식이.

빨간색일 필요는 없다.

루트 노드와 모든 잎 노드 사이에 있는 검은색 노드의 수는 모두 동

트리B-

성질모든 리프 노드는 같은 깊이를 갖는다

키가 개 있으면 이 노드의 자식은 개이다n , n+1

검색

기본적으로 이진검색트리에서의 검색과 같다

이진검색트리에서는 검색 키가 노드의 키와 일치하는 것이

있는지 확인하는 반면 트리에서는 노드의 여러 키 중 검, B-

색 키와 일치하는 것이 있는지 확인한다

Page 45: 자료구조 프로젝트

일정별 토의 내용*날짜 내용

5/8

이번 프로젝트의 조장을 정함*

이번 프로젝트를 할 때 전체적인 일정을 정함*

일요일에 한번 만나기로 하고 화요일 날 아침 시에 만나기로 함- 10

따로 토의할 내용이 있을 경우에는 네이트온을 통해서 만나기로 결정

트리의 정의 및 종류 소스들을 찾아보고 다음 토의 때 각자 찾아온 자료* ,

들을 정리 및 공유하기로 함

5/10

각자 조사한 내용을 바탕으로 알고리즘에 대한 토의를 나눔*

김형오가 데이터를 입력 받았을 때 먼저 정렬을 하고 난 후에 트리- 09

속으로 집어넣는 방법을 이야기 함

정렬 트리 생성 탐색 부분으로 나눠서 역할을 분담하려고 하였으나- , ,

트리 생성이 시급한 것으로 판단 트리 생성을 일요일까지 완료하기로,

결정하였음

구조체의 형태는 밑의 형태로 정함*

LINK 단어DATA( ) DATA(LINE) LINK

프로젝트를 함에 있어서 역할을 결정*

소스 김형오 오승원 박다솔 정상혁- : 09 ,09 ,11 ,11

보고서 장진승- : 09

5/13이진 탐색 트리를 사용하여 상호 참조 생성기를 만드는 것을 구상*

5/15

상호 참조 생성기를 이진 탐색 트리를 사용하여 만들었으나 교수님의 요*

구사항인 트리를 사용하지 않고 만든 트리이므로 트리를 사용하AVL AVL

여서 다시 만들기로 결정함.

5/16프로젝트 마무리를 하기 위해서 마지막으로 만나서 보고서구상 및 트리*

에 대한 내용을 정리하면서 토론을 하였습니다.

소스*파일 입출력 부분*

파일

입출력

#include <stdio.h>

#include <string.h>

Page 46: 자료구조 프로젝트

부분

#include <stdlib.h>

int main()

FILE *fin;

char fname[100];

char buf[256];

char c[100]=0;

char data[1000][100];

char Line[1000][100];

int i, l, n,q,w,e,Li=0;

int co = 1, z=0;;

파일이름printf(" : ");

scanf("%s", fname);

fin=fopen(fname, "r");

if(fin==NULL)

파일을 읽을수 없습니다printf("%s .", fname);

return 1;

i=0; w=0; e=0; Li = 0;

while(1)

q=fgetc(fin);

if(q!=32)

if(q!=EOF)

if((char)q=='\n')

q=32;

라인을 세어주는역활co++;//

else

대문자일 경if(q<97) q+=32; //

우 소문자로 바꾸어준다.

buf[i++]=q;

else if(q==EOF)

buf[i]=0;

strcpy(data[w++],buf);

총 단어의 수z++;//

정수를 문자열로 변환itoa(co, c, 10);//

strcpy(Line[Li++],c);

e++;

for(l=0;l<i;l++)

Page 47: 자료구조 프로젝트

buf[l]=0;

i=0;

break;

아스키 스페이스//32

if(q==32 && i!=0)

e++;

buf[i]=0;

strcpy(data[w++],buf);

z++;

정수를 문자열로 변환itoa(co, c, 10);//

strcpy(Line[Li++],c);

for(l=0;l<i;l++)

buf[l]=0;

c[l]=0;

i=0;

n=e;

fclose(fin);

return 0;

Page 48: 자료구조 프로젝트

*초안 이진 탐색 트리로 작성( )

초안

이진(

탐색

트리로

작성)

void node(TreeNode **root, element key)

는 부모노드 는 자식노드TreeNode *p, *t;//p , t

은 새로운 노드TreeNode *n;//n

t = *root;

탐색을 먼저 수행p = NULL;//

while(t != NULL)

if(strcmp(key.word, t->key.word) == 0)

t->key.count++;

strcat(t->key.L1, key.L1);

return;

p = t;

if(strcmp(key.word, t->key.word)<0)

t = t->left;

else

t = t->right;

실제로 노드가 생성이 될 위치를 검색하면서 중복을 찾아내는//

기능

트리안에 없으므로 삽입가능//

n = (TreeNode *)malloc(sizeof(TreeNode));

if(n == NULL)

return;

n->key = key;

n->left = n->right = NULL;

부모 노드의 링크 연결if(p != NULL)//

if(strcmp(key.word, p->key.word)<0)

p->left = n;

else

p->right = n;

else *root = n;

void display(TreeNode *p)

if(p != NULL)

display(p->left);

printf("%10s %d % s \ n " , p - > k e y . w o r d ,

p->key.count, p->key.L1);

display(p->right);

Page 49: 자료구조 프로젝트

* 트리AVL

트리AVL

void node(TreeNode **root, element key)

는 부모노드 는 자식노드TreeNode *p, *t;//p , t

은 새로운 노드TreeNode *n;//n

t = *root;

p = NULL;

탐색을 먼저 수행//

while(t != NULL)

if(strcmp(key.word, t->key.word) == 0)

t->key.count++;

strcat(t->key.L1, key.L1);

return;

p = t;

if(strcmp(key.word, t->key.word)<0)

t = t->left;

else

t = t->right;

실제로 노드가 생성이 될 위치를 검색하면서 중복을 찾아내는//

기능

트리안에 없으므로 삽입가능//

n = (TreeNode *)malloc(sizeof(TreeNode));

if(n == NULL)

return;

데이터 복사//

n->key = key;

n->left = n->right = NULL;

부모 노드의 링크 연결//

if(p != NULL)

if(strcmp(key.word, p->key.word)<0)

p->left = n;

balance_tree(root);

else

p->right = n;

balance_tree(root);

Page 50: 자료구조 프로젝트

else *root = n;

void display(TreeNode *p)

if(p != NULL)

display(p->left);

printf("%10s %d % s \ n " , p - > k e y . w o r d ,

p->key.count, p->key.L1);

display(p->right);

int height(TreeNode *root)

int height1=0;

if(root != NULL)

if(height(root->left) > height(root->right))

height1 = 1+height(root->left);

else

height1 = 1+height(root->right);

return height1;

int get_balance(TreeNode *root)

if(root == NULL)

return 0;

return height(root->left) - height(root->right);

void balance_tree(TreeNode **root)

int e,r;

int h=0;

h = get_balance(*root);

Page 51: 자료구조 프로젝트

e = get_balance((*root)->left);

r = get_balance((*root)->right);

왼쪽 서브트리의 균형을 맞춘다if(h > 1) //

if(e > 0)

*root = rotate_LL(*root);

else

*root = rotate_LR(*root);

오른쪽 서브트리의 균형을 맞춘다else if(h < -1) //

if(r < 0)

*root = rotate_RR(*root);

else

*root = rotate_RL(*root);

return ;

TreeNode* rotate_LL(TreeNode *parent)

TreeNode *child = parent->left;

parent->left = child->right;

child->right = parent;

return child;

TreeNode* rotate_RR(TreeNode *parent)

TreeNode *child = parent->right;

parent->right = child->left;

child->left = parent;

return child;

TreeNode* rotate_RL(TreeNode *parent)

TreeNode *child = parent->right;

parent->right = rotate_LL(child);

return rotate_RR(parent);

Page 52: 자료구조 프로젝트

TreeNode* rotate_LR(TreeNode *parent)

TreeNode *child = parent->left;

parent->left = rotate_RR(child);

return rotate_LL(parent);

프로그램

실행 시

Page 53: 자료구조 프로젝트
Page 54: 자료구조 프로젝트

이번 프로젝트의 목적은 자료구조의 의 내용을 학습하고 이의 내용을 활용하여 최단 거리를Graph

구하는 프로그램을 만드는 것이 이번 프로젝트의 목표입니다.

그래프의 개요.

그래프 는 개의 집합 정점의 집합 과 집합 간선의 집합 으로 구성되어- G 2 V(vertex, ) E(edge, )

있다 그래프는 년에 오일러가 다리를 건너는 문제를 해결하기위해 사용한 것으로. 1736

기록되어 있습니다.

이 분야는 오일러 행로 라는 최초의 응용이후로 전기 회로의 분석 최단(Eulerian walk) ,

경로 탐색 통계적 기계학 등 여러 가지 분야에서 응용되어 사용되고 있습니다, .

무방향 그래프.(undirected graph)

-무방향 그래프란 간선을 나타내는 정점의 쌍에 순서가 없는 것으로 말그대로 방향성이

제시되어 있지 않은 그래프이다 이와 반대되는 개념으로는 방향 그래프로 만약 정점의.

쌍 와 가 있다면 무방향 그래프 같은 경우는 이 둘을 같은 간선 로 보고(u,v) (v,u) , (edge) ,

방향성 그래프 같은 경우에는 서로 다른 간선 로 보게 된다(edge) .

인접행렬(adjacency matric)

개의 꼭지점 을 갖는 다중 그래프 점 에서 행렬-n V1,V2,...,Vn G=(V,E( )) N*N의 그래프 간단히 설명하자면 한 지점과 다른 지점과의 관계나 경로A(G)=(aij)N*N . ,

파악을 알아보기 위해 이용되는 행렬이라고 생각하면 된다 여기서 표시할 때 연결이.되어있을 땐 을 지정하고 연결이 되어 있지 않을 땐 으로 표시한다1 , 0 .플로이드 알고리즘

최단 거리를 구하는 알고리즘으로서 모든 정점을 출발해서 출발한 정점을 제외한 모든- ,

정점을 도착점으로 하는 최단거리를 구하는 알고리즘 방식이다.

Page 55: 자료구조 프로젝트

위의 그래프에서 번 정점에서 번 정점으로 이동을 할 때 최단 경로를 찾아낸다고 하면 그 방법에 있어서1 3

번 정점에서 번 정점으로 직접 연결하면 최단 거리가 이 되지만 번 정점에서 번 정점을 거치고 번 정1 3 6 , 1 2 3

점을 연결하면 최단거리가 가 되는 것을 알 수 있다, 5 .

위와 같은 원리로 각 정점 사이의 최단 거리를 테이블로 표현한 후 다른 테이블에는 각 정점의 어떠한 경로,

로 왔는지에 관한 테이블을 생성합니다 뒤의 테이블을 이용하여 각 정점의 최단 경로가 어떠한 경로로 형성.

이 되었는지에 관하여 추적 할 수 있습니다.

예제 그래프.

점1 2 3 4 5 6

1 0 9 3 18 20 232 ∞ 0 ∞ ∞ ∞ 30

3 ∞ 6 0 15 21 244 ∞ 25 ∞ 0 6 9

5 ∞ ∞ ∞ ∞ 0 36 ∞ ∞ ∞ ∞ ∞ 0

점1 2 3 4 5 6

1 0 3 1 3 1 52 ∞ 0 ∞ ∞ ∞ 2

3 ∞ 3 0 3 4 54 ∞ 4 ∞ 0 4 5

5 ∞ ∞ ∞ ∞ 0 56 ∞ ∞ ∞ ∞ ∞ 0

각 정점간의 최단 거리 테이블 경로 테이블< > < >

위의 플로이드 알고리즘을 활용하여 이번 프로그램을 만들게 되었습니다.

Page 56: 자료구조 프로젝트

일정 화요일5.29( )

회의

내용.

http://air.changwon.ac.kr/wp-content/uploads/2012/01/2012-DS-p

roject-05.pdf

위의 내용을 통해서 이번 과제의 문제에 대해 회의를 하였으며,

수업시간의 교수님의 추가적인 내용을 토대로 이번 과제를 해결하기

앞서 각자 맡을 업무를 분담하였습니다, .

회의결과 및토의

이번 회의 결과 조장은 다음 모임 까지 개별적으로 이번, ,프로젝트를 위한 자료를 구하고 자료 조사팀에서는 그래프에,대한 기본 성질에 대해서 자료를 구하고 프로그램을 맡은,사람은 이번 프로젝트를 인접 행렬과 인접 리스트 방식 중,인접 행렬로 기본적인 틀을 만들어 오기로 결정하였습니다.

일정 목요일5.31( )

회의

내용.

저번 회의 때 각자 맡은 업무를 확인하고 자료조사팀과 조장이 구한,

자료 및 서적의 내용을 통해 그래프에 대해서 서로 토의를 하고,

부족한 부분을 조사팀이 질의응답을 해주는 식으로 토의 하였습니다.

그리고 프로그래밍을 한 조원이 구한 알고리즘을 토대로 이것을 서로

토의 하고 이해하는 식으로 이번 회의를 마쳤습니다.

회의결과및

이번 회의 결과 플로이드 알고리즘을 토대로 프로그램을,완성 시키는 것으로 결정하였고 다음 주 월요일까지.

Page 57: 자료구조 프로젝트

토의코딩을 완성 시켜서 부족한 부분에 대해서 토의를 하고,완성된 프로그램을 토대로 회의를 하기로 결정하였습니다.

일정 월요일6.04( )

회의

내용

결과

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#define M 10000

void make(int x, int y, int data[]);

void test(int n);

void print(int x, int y);

int path(int q,int r);

행렬int A[100][100];//

int B[100][100];

int ar[100];

int main()

FILE *fin;

char fname[100];

char buf[256];

int data[1000];

char* p;

int q;

int i=0,n=0,Line=0,ad;

파일이름printf(" : ");

scanf("%s", fname);

fin=fopen(fname, "r");

if(fin==NULL)

파일을 읽을수 없습니다printf("%s .", fname);

return 1;

Page 58: 자료구조 프로젝트

while(!feof(fin))

fgets(buf, 255, fin);

p = strtok(buf, "," );

++Line;

if(Line == 1)

ad = atoi(buf);

else

while(p != NULL)

if((i+1)%3 != 0)

q = (int)(*p)-64;//A = 1로바꿈.....

data[i] = q;

p = strtok(NULL, "," );

i = i+1;

else

data[i] = atoi(p);

p = strtok(NULL, "," );

i = i+1;

n=i;

fclose(fin);

make(ad,n,data);

return 0;

void make(int x, int y, int data[])

int i,j,k,a,b,n,nn;

int c=0;

for(i=0; i<x; i++)

for(j=0; j<x; j++)

if(i != j)

A[i][j] = M;

else

A[i][j] = 0;

B[i][j] = -1;

Page 59: 자료구조 프로젝트

nn = y/3;

for(i=0; i<nn; i++)

a = data[c];

b = data[c+1];

A[a-1][b-1] = data[c+2];

A[b-1][a-1] = data[c+2];

c = c+3;

n=x;

for(k=0; k<n; k++)

for(i=0; i<n; i++)

for(j=0; j<n; j++)

if (A[i][k]+A[k][j] < A[i][j])

A[i][j] = A[i][k]+A[k][j];

경유한경우의B[i][j] = k;//값을 저장

test(x);

void test(int n)

int i,j,a,b,k=0,tem,tem1;

int temp = 10000;

int count=0;

for(i=0; i<n; i++)

for(j=0; j<n; j++)

if(i<j)

if(A[i][j]<temp)

ar[k] = i;

ar[k+1] = j;

모든 행과열을k = k+2;//저장을 한다.

for(j=0; j<k; j=j+2)

for(i=0; i<k-2; i=i+2)

if(A[ar[i]][ar[i+1]] >=A[ar[i+2]][ar[i+3]])

tem = ar[i]; tem1 = ar[i+1];

ar[i] = ar[i+2]; ar[i+2] = tem;

Page 60: 자료구조 프로젝트

ar[i+1] = ar[i+3]; ar[i+3] =tem1;

배열을 가중치순서대로 정렬//

while(count != 6)

print(ar[count],ar[count+1]);

count = count+2;

void print(int x, int y)

최단 경로printf(" : ");

printf("%c -> ",x+1+64);

path(x,y);

printf("%c \n",y+1+64);

가중치printf(" : %d\n",A[x][y]);

int path(int q,int r)

중간에 지나온길의 유무를 확인if(B[q][r] != -1)//

그다음 지점에서 지나온 길의path(q,B[q][r]);//유무를 확인

printf("%c -> ",B[q][r]+1+64);

path(B[q][r],r);

위의 프로그래밍한 조원이 완성시키고 구현을 한 조원의 설명을,통해서 이번 과제에서의 기본적인 알고리즘에 대해서 배우게,되었습니다.

Page 61: 자료구조 프로젝트
Page 62: 자료구조 프로젝트

다익스트라 알고리즘이란(1) ?

그리디 알고리즘은 전후 상황을 파악하지 않고 현재 시점에서 가장 최적의 상황을 찾아 경로를 파악해 나- ,

가는 것이다 즉 최적 해를 구하는 데에 사용되는 근사적인 방법으로 여러 경우 중 하나를 결정해야 할 때마. ,

다 그 순간에 최적이라고 생각되는 것을 선택해 나가는 방식으로 진행하여 최종적인 해답에 도달하게 된다.

그리디 알고리즘을 기본적 원리로 두어 최단경로를 구해내는 방법이 다익스트라 알고리즘이다 여기서 다익- .

스트라는 만든 사람의 이름을 딴 것이다.

다익스트라 알고리즘의 원리(2)

다익스트라 알고리즘을 구체적으로 적용하기 전에 해결과정을 정리해 보면 다음과 같다- .

가중치인접행렬에서는 직접 연결된 것이 없으면 무한대 연결된 간선은 가중치를 표현한다, .①

두개의 집합 와 를 만들어 에는 출발점을 초기값으로 는 출발점을 제외한 모든 정점을 초기값으로S C S , C②

한다.

에서 정해진 초기값으로부터 의 각 정점에 대한 최단 경로 를 구한다S C dist[i] .③

의 기록 중에서 최단 경로를 택하여 해당 정점 를 에서 제거 후 에 넣는다dist[i] v C S .④

의 초기 정점과 에 직접 이르는 거리와 안의 모든 정점을 거친 후 에 이르는 거리중 최단 경로를S C S C⑤

로 한다dist[w] .

의 과정을 가 공집합이 될 때까지 반복한다- C .⑥ ➃ ➄

Page 63: 자료구조 프로젝트
Page 64: 자료구조 프로젝트

이번 프로젝트의 목적은 사전에서 단어를 검색하여 틀린 글자가 나올시 표시후 적절한 단어를 추천하는,

프로그램을 제작하여 과 에 대해 학습하는 것이 이번 과제의 목표입니다, heap deap, hash .

이란Heap ?

완전이진 트리의 방식중 하나로서 각각의 노드는 유일한 키 값을 가진다 은 여러개의 노드 중 가장 큰.heap

키 값 을 가지는 노드나 가장 작은 키 값을 가지는 노드를 가장 빠른 시간 내에 찾아내(Max Heap) (Min Heap)

도록 만들어진 자료 구조 방식이다 이것 말고도 방식이 있는데 이것은 각 층당 레벨에서는. ,min-max heap 1

다름 레벨에선 를 반복하여 생성한 것입니다min max,min max .

이란Deap ?

은 의 변환된 형태로서 맨처음 루트에는 빈 루트를 만들어주고 왼편에는 오른Deap Min-Max heap , , min heap,

편에는 방식으로 넣어준다max heap .

란Hash ?

가지는 테이블 항목을 검색하기 위해 특정한 변환 함수를 이용하여 키 값을 항목의 주소로 직접 바꾸어 검색

하는 방법을 라고 한다 이때 변환하는 함수를 함수라고 한다Hash . hash .

를 이용하면 함수에서 받은 키 값을 해당 주소로 바로 변환해 주므로 매우 빠른 검색이 가능하다hash hash .

<min-heap> <Max-heap> <Min-Max heap>

Page 65: 자료구조 프로젝트

<Hash>

일정 화요일6.5( )

회의

내용.

http://air.changwon.ac.kr/wp-content/uploads/2012/01/2012DS_Pr

oject06.pdf

위의 내용을 통해 이번 과제에서 어떠한 것을 학습해야 하는 지와,

문제를 어떻게 해결할지에 대해서 토의를 하였습니다.

회의결과 및토의

토의 결과 이번 과제의 핵심인 에 관련된 자료Hash,Deap,Heap조사를 명이서 하는 것으로 결정하였고 한명은 소스를 담당하2 ,고 조장 명으로 역할 분담하는 것으로 결정하였습니다, 1 .그리고 다음 시간 까지 최소 과 에 관련된 자료를, Heap Deap조사팀에서 조사해 오는 것으로 결정하였습니다.

일정 목요일6.7( )

회의

내용.

지난번의 과제에 대한 문제를 해결하려고 하였는 데 결과적으로,

부족한 부분이 많아서 수업 시간에 설명 하였던 방식이 세가지가,

있었는데 그 중에서 어떠한 방식을 이용해서 이번 프로젝트를 실행할

것인지와 자료 조사팀에서 조사한 과 에 관련된 것을 주로Heap Deap

하였습니다.

*Heap,Deap.

완전이진 트리의 방식중 하나로서 각각의 노드는 유일한 키 값을 가진

다 은 여러개의 노드 중 가장 큰 키 값 을 가지는 노드.heap (Max Heap)

Page 66: 자료구조 프로젝트

나 가장 작은 키 값을 가지는 노드를 가장 빠른 시간 내에(Min Heap)

찾아내도록 만들어진 자료 구조 방식이다 이것 말고도. ,min-max heap

방식이 있는데 이것은 각 층당 레벨에서는 다름 레벨에선1 min

를 반복하여 생성한 것입니다max,min max .

의 삽입과 삭제* Min-heap .

삽입- .

1. 은 완전 이진 트리이므로 새로운 노드는 완전 이진 트리min heap의 마지막 노드 다음 위치에 삽입된다.

2. 삽입된 노드와 그 부모 노드의 키 값을 비교한다 삽입된 노드의 키.값이 부모 노드의 키 값보다 작으면 두 노드의 위치를 바꾼다.

3. 삽입된 노드의 키 값이 자신의 부모 노드 키 값보다 작으면 두 노드의 위치를 바꾼다.

4. 삽입된 노드의 키 값이 자신의 부모 노드 키 값보다 커질 때까지 2단계를 반복한다.

삭제- .

의 루트에는 가장 작은 키 값을 가지는 노드가 들어있으1. min heap므로 루트 노드를 삭제한다.빈 루트 노드 자리에는 완전 이진 트리의 마지막 노드를 삽입한다2. .삽입된 노드의 그 자식 노드의 키 값을 비교한다 삽입된 노드의 키3. .값이 자식 노드의 키 값보다 크면 두 노드의 위치를 바꾼다.삽입된 노드의 키 값이 자신의 자식 노드 키 값보다 작아질 때까지4.단계를 반복한다3 .

의 삽입과 삭제*Max-heap .

삽입- .

은 완전이진 트리이므로 새로운 노드는 완전이진 트리1. max heap의 마지막 노드 다음 위치에 삽입된다.삽입된 노드와 그 부모 노드의 키 값을 비교한다 삽입된 노드의 키2. .값이 부모 노드의 키 값보다 크면 두 노드의 위치를 바꾼다.삽입된 노드의 키 값이 자신의 부모 노드 키 값보다 작아질 때까지3.단계를 반복 한다2 .

삭제- .

의 루트에는 가장 큰 키 값을 가지는 노드가 들어있으므1. max heap로 루트 노드를 삭제한다.빈 루트 노드 자리에는 완전 이진 트리의 마지막 노드를 삽입한다2. .삽입된 노드와 그 자식 노드의 키 값을 비교한다 삽입된 노드의.키 값이 자식 노 드의 키 값보다 작으면 두 노드의 위치를 바꾼다.삽입된 노드의 키 값이 자신의 자식 노드 키 값보다 커질 때까지3. 3단계를 반복한 다.

회의결과및토의

이번 회의 결과 위의 내용을 개인적으로 복습하고 이것을 소스에, ,어떠한 방식으로 적용할 것인지에 대해 다음 시간 까지 정하는것으로 결정하였고 자료 조사팀에서는 에 관해서 조사해 오는, Hash것으로 결정하였습니다.

Page 67: 자료구조 프로젝트

일정 화요일6.12( )

회의

내용.

이번 회의에서는 주로 에 관하여 자료조사 팀에서 조사한 것을Hash보고 학습하는 것에 집중을 하였고 이것을 어떻게 프로젝트에서,활용할 것인지에 대해서 회의를 하였습니다.

*Hash

은 하나의 문자열을 원래의 것을 상징하는 더 짧은 길이의Hashing값이나 키로 변환하는 것이다 키를 사용하여 항목을 찾으면. Hash원래의 값을 이용하여 찾는 것보다 더빠르기 때문에 항목을 색인하고검색하는데 이용을 많이 한다.

함수의 특성및 용어*Hashing .

레코드 키들의 집합을 버켓주소에 대응시킨다는 의미에서 사상함수라고도 하며 가장 이상적인 해싱 함수는 키 집합의 한 레코드와,버켓 주소 집합의 한 레코드가 대응 하여 해시 테이블에 정해진1:1범위에 고르게 분포되어 있어서 충돌을 최소화 하도록 하는것입니다.

의 조건-Hashing .

주소 계산이 빠르게 구해져야된다1. .서로 다른 레코드의 계산된 값이 가급적으로 중복 되지 않아야2.된다.

• 해시 테이블 레코드의 저장을 위한 자료구조로써(hash table) - 해상함수로부터 계산된 함수값에 해당하는 위치에 각 레코드를 한개 이상 보관할 수 있는 버켓 들로 구성된 기억 공간이며(bucket) ,주어진 값을 가지고 해당 레코드를 빠르게 검색하기 위한 수단key을 제공하며 레코드의 삽입과 삭제를 용이하게 한다.

• 버켓 해싱함수에 의해 계산된 주소인 홈 주소(bucket) - (home혹은 버켓 주소에 레코드 키를 저장하기 위해 마련된 기address)

억장소를 말하며 대개 한 개 또는 여러 개의 레코드를 저장할 수,있는 슬롯 으로 구성된다(slot)

함수의 방식*Hashing .

제산법1.

나머지 연산자를 사용하여 테이블 주소를 계산하는 방식 가장 간단- .한 해싱 함수 방식.

제산법의 주소 계산법< >

해시 테이블의 홈주소를 결정하는 양의 정수 값의 잘못된 선택은 상-당한 충돌을 유발할수 있으므로 선정에 신중을 기해야된다.

제곱법2. .

레코드 키 값을 제곱한 후 결과 값의 중간부분에 있는 몇 비트를 선- ,택하여 홈주소로 사용하는 방식.

제곱된 결과의 중간 비트는 대개 레코드의 모든 문자에-의존하므로 레코드를 구성하는 문자가 같을 지라도 서로 다른 레코드, ,키는 다른 홈주소를 갖게될 확률이 높다.

Page 68: 자료구조 프로젝트

숫자 분석법3. .

레코드 키를 구성하는 수들이 모든 키들 내에서 각 자리 별로 어떤-분포인지를 조사하여 비교적 고른 분포를 나타내는 자릿수를 필요한만큼 선택하여 레코드의 홈주소로 사용하는 방식, .

삽입과 삭제가 빈번히 발생하는 경우는 비효율적- .

폴딩법4. .

레코드의 키를 마지막 부분을 제외한 모든 부분의 길이가 동일하게-여러부분으로 나누고 이들 부분을 모두 더하거나 배타적 논리 합, ,

을 취하여 해시 테이블의 홈주소로 이용하는 방법(XOR) , .

이동 폴딩 방식< >

경계 폴딩 방식< >

회의결과및토의

이번 회의 결과 사전을 만드는 부분에서 함수를 이용해, Hash검색할수 있도록 활용할 계획이고 에 관해서 개인적으로, Hash학습하는 것으로 결정하였습니다 그리고 부족한 부분은 더.조사하기로 결정하였습니다.

Page 69: 자료구조 프로젝트

일정 목요일6.14( )

회의

내용.

저번 시간에 이어서 해시에 관해서 조사한 부분을 학습하고,소스를 만드는 방식을 해시의 어떠한 방식을 이용해 만들것인지결정하고 에 관하여 주로 어떠한 방식으로 행동하는 지에, Deap대하여 학습하였습니다.

의 충돌 발생시 레코드를 저장하기 위한 기억장소 검색 방법*Hash , .

선형 검색법1. .

선형 검색법은 충돌을 피하는 가장 간단한 방법으로 충돌 발생시 새- ,로운 레코드 키를 저장할 위치를 충돌이 발생한 위치에서 하나하나 찾아가는 방식 하지만 만약 검색과정에서 테이블 끝에 도달 할 때까지. ,빈공간이 존재하지 않을시 처음 번지로 돌아가서 다시 검색한다. .

장점은 해시 테이블의 구조가 간단하지만 충돌이 발생시 최악의 경- ,우 해시 테이블 전체를 검색해야 되는 경우가 생기므로 비효율적이다.

차 검색법2.2 .

차 검색법은 선형 검색법에서 생기는 제 밀집 문제를 제거하는 방-2 1법 기대되는 충돌함수는 이차식인 이 된다, f(i)=i^i .

원래 테이블 주소로부터 다음 주소를 결정하는 거리 가 과d 1,4,9,16...같이 떨어진 영역을 차례대로 검색하여 처음으로 발견되는 빈 영역에해당 레코드를 저장함으로써 충돌을 해결하는 방법이다.

체인 이용법3. .

체인 이용법< >

위의 그림과 같은 방식으로 해시 테이블 자체는 포인터 배열로 만들고 같은 버켓에 할당되는 레코드 들을 체인으로 만들어 연결한다, .

충돌 발생시 명칭들 만으로 연결리스트에서 검색해 주면 되므로 속도- ,가 빠르고 삽입 가능한 명칭의 수가 해시 테이블크기에 영향을 받지,않는다는 장점이 있지만 구조가 복잡하고 기억장소 소모량이 많아진,다.

회의결과및토의

이번 회의 결과 프로그램을 만드는 방식을 체인 방식을 이용하여,사전을 만든 다음에 검색하는 방식으로 결정하였고 전체적인,레코드를 와 같은 식으로 색인을 만든 후 사전을 만들기로aa,ab,결정하였습니다.

Page 70: 자료구조 프로젝트

일정 수요일6.22( )

회의

내용

결과

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

void hash(char x, char y);

char hashtable[100000][20];

void init()int i,j;for(i=0; i<100000; i++)

for(j=0; j<20; j++)hashtable[i][j] == 0;

int main()FILE *fin;

char fname[100];char buf[256];char data[1000][100];

char array[20];int q,l;int i=0,w=0;int a=0,b=0,c=0,d=0,sum;

int m=0,n=0,count=0;

파일이름printf(" : ");scanf("%s", fname);

fflush(stdin);fin=fopen(fname, "r");

if(fin==NULL) 파일을 읽을수 없습니다printf("%s .", fname);

return 1;

init();///////////////////////////////////while(!feof(fin))

q = fgetc(fin);엔터if(q != '\n')//

대문자일 경우 소문자로if(q<97) q+=32; //

buf[i++]=q;else

buf[i]=0;strcpy(data[w],buf);여기에서 해싱을 사용을 해서 하나씩 해시 테이블을//

만들어야할듯//strcpy(p.key, data[w]);//hash(data[0][0],data[0][1]);while(n != strlen(data[w]))

Page 71: 자료구조 프로젝트

a = (data[w][n]-96)*(n+1);c = a+c;n++;//printf("%d",n);

if(hashtable[c][0] == 0)

strcpy(hashtable[c], data[w]);else

while(1)

c++;if(hashtable[c][0] == 0)

strcpy(hashtable[c],data[w]);

break;if(c == 100000) break;

//printf("%s %d\n",hashtable[21], c);n=0;c=0;

for(l=0;l<i;l++)

buf[l]=0;data[0][i]=0;

i=0;

단어를 입력하세요printf(" ");gets(array);while(m != strlen(array))

b = (array[m]-96)*(m+1);d = b+d;m++;//printf("%d\n",m);

//printf("%d\n",d);while(d != 100000)

sum = strcmp(hashtable[d],array);

if(sum == 0)찾음printf(" \n");

count++;d++;

d=0;if(count==0)

없음printf(" \n");//printf("%s",hashtable[d]);

Page 72: 자료구조 프로젝트