10
C 1 조 Project #1 조조조조 조조조 C1 2012-03-17

자료구조 Project1

Embed Size (px)

Citation preview

Page 1: 자료구조 Project1

C 1 조

Project #1

파스칼의 삼각형

C12012-03-17

Page 2: 자료구조 Project1

목차1. 프로젝트 수행 결과 보고서...............................................................................................2

프로젝트의 목적....................................................................................................................2

프로젝트의 내용....................................................................................................................3

프로젝트의 진행 방법............................................................................................................3

프로젝트 결과.......................................................................................................................3

참고문헌 및 웹......................................................................................................................3

2. 프로젝트 수행 일지............................................................................................................3

3 월 6 일 프로젝트 착수.........................................................................................................4

3 월 10 일 일정계획 및 진행방법 토의......................................................................................4

3 월 13 일 업무 분담 및 1 차 소스 작성.....................................................................................5

3 월 15 일 2 차 소스 작성.......................................................................................................6

3 월 18 일 소스 완료 및 최종보고서 작성..................................................................................7

3 월 20 일 최종 소스 작성 및 최종보고서 검토.........................................................................10

1.프로젝트 수행 결과 보고서

프로젝트의 목적

- 배열의 사용법을 안다.- 프로그램의 시간,공간 복잡도를 계산할 수 있다.

프로젝트의 내용

Page 3: 자료구조 Project1

- 배열을 이용하여 파스칼의 삼각형을 출력하는 프로그램을 작성하고, 시간 복잡도와 공간복잡도를 이용하여 보다 빠르고 메모리 손실이 작은 프로그램을 만들자.

프로젝트의 진행 방법

- 전체적인 프로젝트 진행은 팀원들과의 협동을 통해 진행되며 각자의 역할을 분담하여 프로젝트 진행 속도와 완성도를 높이는 방향으로 진행된다.

프로젝트 결과

- 50 행 이하의 파스칼의 삼각형 출력에는 문제가 없으나 그 이상의 행에서는 소수점 이하의 오차가 발생하는 프로그램이 완성되었다.

- 최종 검토 과정에서 생각지 못한 오류와 불필요한 메모리 손실이 발견되어 재 수정을 거쳤고 오차와 메모리손실을 줄였다.

참고문헌 및 웹http://10albatross.tistory.com/27http://carstart.tistory.com/122http://skmagic.tistory.com/164http://qwe1qwe.tistory.com/880C 로 쓴 자료구조론_HOROWITZ,Sahni,Anderson-Freed 저 , wikepedia.org , httpispkorea.com ,

2. 프로젝트 수행 일지

3 월 6 일 프로젝트 착수

- 조 편성 및 프로젝트 문제 인식

- 문제 인식 : 배열을 이용하여 파스칼의 삼각형을 문제에서 요구하는 대로 출력 해야한다. 사실상 파스칼의 삼각형 출력은 어려운 것이 아니다.하지만, 자료형 제한과 메모리와 시간의 균형을 맞추는 것이 매우 어려울 것이다.

- 파스칼의 삼각형이란?

Page 4: 자료구조 Project1

3 월 10 일 일정계획 및 진행방법 토의

- 일정계획 및 진행방법 토의

- 일정계획: 3 월 13 일 2 차 미팅 – 업무 분담 및 1 차 소스 작성3 월 15 일 3 차 미팅 – 2 차 소스 작성 및 오차 수정3 월 18 일 4 차 미팅 – 소스 완료 및 최종 보고서 작성3 월 19 일 5 차 미팅 – 최종보고서 검토 및 프로젝트 완료3 월 20 일 6 차 미팅 – 최종보고서 검토내용 적용 및 소스 수정3 월 22 일 프로젝트 마감 제출 발표

- 진행방법:토론과 토의를 바탕으로 프로젝트를 수행하며, 팀 내에서 업무분담을 통해 작업의 효용성을 높이며 토의와 수정을 거쳐 완성도 높은 프로젝트 결과물을 도출한다.소스 작성에 있어서는 배열을 먼저 선언하고 출력 하는 방법을 고려한다.

3 월 13 일 업무 분담 및 1 차 소스 작성

- 업무분담 : 조장 : 09 학번 최고봉 – 최종보고서작성, 발표팀원 : 08 학번 고충욱 – 자료조사, 보고서작성

11 학번 서상현 – 보고서작성, 스케쥴링 11 학번 김성진 – 소스작성, 자료조사 11 학번 김지환 – 자료조사, 스케쥴링

- 1 차 소스 작성당초 생각했던 배열을 먼저 선언하고 출력하는 방식은 메모리손실이 크고 시간이 오래 걸릴것으로 예상되므로 재귀함수를 이용하는 방법을 이용하기로 했다.

#include <stdio.h>

int Sum (int n, int m, int *sum); // Sum 함수선언

Page 5: 자료구조 Project1

int Sum (int n, int m, int *sum) // Sum 함수정의 (n-1)(m-1)+(n-1)(m)을 이용한다.

{If (m < = 1 ) // m 이 1 이되면 값은 무조건 1 이기 때문에 , 걸러준다.

{ sum += 1; // 조건에 걸릴경우 sum 에 1 을 더해주어 값을 더한다. Break ; }

If(n<m)Break; // m 이 n 보다 커지는경우가 발생하면 바로 종료시켜준다.Sum(n-1,m-1,sum); // (n-1)(m-1)에 해당하는 부분이다.Sum(n-1,m,sum); // (n-1)(m)에 해당하는 부분이다.

}Int main (void){Int n,m,sum;+Sum = 0;Scanf(“%d %d”, &n , &m);Sum(n,m,sum); //(n,m)을 함수에 대입시킨다.Printf(“%d”, sum);Return 0;

}

이 방법은 자료형 제한과 시간적인 결함으로 인해 보완할 점이 많다. 라는 결론을 내렸다.

3 월 15 일 2 차 소스 작성

- 3 월 13 일 작성한 소스가 자료형의 제한에 걸리는 동시에 시간이 오래 걸린다는 오점이 있었고, 그래서 우리는 공식을 저장하고 그 공식에 입력 받은 값을 대입하여 값을 얻어내는 방법을 이용한 소스를 작성하기로 하였다. 하지만 새로운 소스는 메모리 손실이 크다는 오점이 있다.

#include <stdio.h>

Int main(void){

Int n,m,sum,p,r,I,k; //연산을 위한 변수와 숫자를 대입받을 변수선언Scnaf(“%d %d”, &n,&m); // n 과 m 을 대입받는다.

P = r = 1; //곱셈연산을 하기위해 초기값을 1 로 설정For(i=1; i<m; i++) // r! 을 구한다.

r *= i;k = m-1; for(i=n-1;;i--) // nPr 을 구한다.{

If(k==0)Break;

k--;p *= i;

}sum = p/r; // nPr / r! 을 연산한다.

Printf(“%d”, sum); // 출력.

Page 6: 자료구조 Project1

Return 0;}

3 월 18 일 소스 완료 및 최종보고서 작성

- 우리는 메모리보다는 실행시간에 중점을 두고 프로젝트를 진행 해왔고, 앞서 작성한 두 소스 (재귀함수이용,공식대입)중에 공식대입소스를 이용하기로 하였다. 소스 검토 과정 중에 마주한 어려움으로는 자료형의 크기제한으로 인한 오류와 연산의 어려움 이였다. 이를 해결하기 위하여 배열을 크게 선언하여 공간을 확보하여 배열에 결과값을 저장하는 방식을 통해 결과값을 출력하기로 하였고 연산의 어려움을 해결하기 위해 곱과 분을 따로 하기로 하였다 아래와 같은 소스를 완성하였다.( 추가 설명은 각주에서).

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

double sum[400]; //계산한값을 받을 더블형 배열int size; //반복문에서 사용될 배열의 크기, 배열은 위의 크기로 선언되나 반복문에서는

필요한부분만 사용하여 연산int m,n; //입력받을 값의 변수

void Calculation(){ //답을 구하는 방법은 공식을 사용. 공식은 nCm = n!/m!/(n-m)! = (n*(n-1)*(n-2)*...*(n-m+1)/m! 이며 오른쪽 식을 사용하여 답을

구하도록했다. double a,b; //계산에필요한 변수 int c; //배열번호를 담당하는 변수 double buffer,temp; //연산에서 임시로 저장할 변수 int s=0; buffer=0; for(a=n-1,b=m-1;a>=(n-m+1)||b>0; ){ c=size-1; if(a>=(n-m+1)){ //공식의 분자부분. n*(n-1)*(n-2)*...*(n-m+1)를 수행한다 while(c>=0){ //sum[c]에 값을 곱했을때 값이 일정값을 넘으면 sum[c+1]에 넘치는 값을

넘기도록 했다. sum[c]=sum[c]*a;//sum[0]은 기본적으로 1 이다. 다른 값은 0 이다. if(sum[size-1]!=0) //반복문을 돌리는 배열중 최상위 배열이 0 이 아닐때 사용하는 배열을 늘린다.

기본적으로 sum[0]과 sum[1] 두개를 사용한다 size++; if(sum[c]>=1e+9){ //값이 9 자리를 넘을때 넘치는 값을 나누어 다음 배열에 넘기는 부분이다. temp=(unsigned)(sum[c]/(1e+9)); sum[c+1]=sum[c+1]+temp; sum[c]=sum[c]-(temp*(1e+9)); } c--; } a--; } else if(b>0&&a==(n-m)){ //위의 분자부분 연산이 끝나면 분모부분의 연산을 수행한다. 여기서는

매숫자마다 값을 나누어주어 저장하는 식으로 진행한다. while(c>=0){

Page 7: 자료구조 Project1

if(sum[c]!=0&&s==0) //값이 존재하는 배열이 나올때까지 연산을 하지않기위해 이 구문을 넣었다.

s=1; if(s==1){ //연산은 최상위 배열값 부터 나누어 내려가며

나눈값 소수점이하 부분에 1e+9(1000000000)를 곱하여

if(sum[c]/b>=1){ //buffer 변수에 저장한다. temp=(sum[c]/b)+buffer; //배열에 buffer 를 더하고(첫 buffer 는 0 이다.) 연산할 값을

나눈후 임시값에 저장한다. sum[c]=(unsigned)temp; //나눈값은 소수점이 있을 수 있으므로 소수점이하는 버리고

정수부분만 저장시킨다. buffer=(temp-sum[c])*(1e+9); //버퍼에 배열을 나누값의 정수부분을 뺀 나머지 소수부분에

1e+9 를 곱해준다. if(c==0){ //최하위 배열의 경우 연산후 다음 연산을 위해

버퍼에 0 을 저장한다. buffer=0; s=0; } } else{ //배열값을 나눴을때 1 미만일 경우 배열에 0 을 저장하고

나머지값은 buffer 에 저장한다. buffer=sum[c]/b*(1e+9); sum[c]=0; } } if(sum[c]>=1e+9){ //만약 배열에 저장된값이 1e+9 보다 클때 넘치는 값을 윗

배열로 넘긴다. temp=(unsigned)(sum[c]/(1e+9)); sum[c+1]=sum[c+1]+temp; sum[c]=sum[c]-(temp*(1e+9)); } c--; } b--; } }}void main(){ int x; int y=0; printf("열을 입력해주세요 : "); scanf("%d",&n); printf("행을 입력해주세요 : "); scanf("%d",&m); size=2; for( x=0 ; x<400 ; x++ ){ //값을 계산할 배열 값을 초기화.

첫번째 배열만 1 로 선언하고 나머지는 모두 0 으로 선언 if( x==0 ){ sum[x]=1; continue; } sum[x]=0; } Calculation(); //값을 구하기 위한 계산함수 printf("%d 번째 행의 %d 번째 열의 숫자는 ",n,m);

Page 8: 자료구조 Project1

for( x=size-1 ; x>=0 ; x-- ){ //답을 출력하는 반복문. 계산과정에서 값을 저장하는 자료형의 크기의 한계를 극복하기 위해

if(sum[x]!=0||y==1){ //일정 값을 넘어가면 넘치는 부분을 다음 배열에

저장하도록 하였기 때문에 결과값이 나누어져 있어 if(y==0){ //한번에 출력할 수 없어 부득이 반복문을 사용하였다. printf("%.f",sum[x]); //배열이 0 일때는 출력하지 않도록 했고 결과값이 나오면

그 밑의 값은 모두 출력하도록 했다. y=1; continue; } printf("%09.f",sum[x]); } } printf("입니다.\n"); _getch();

- 위 코드에는 치명적인 결함이 있다. 오차가 생기는 점이다. 그 이유는 값을 나누는 과정에서 자료형의 소수점 정밀도 때문이다. 따라서 결과값의 정확한 자릿수 정도는 구할 수 있을지 모르나 정확한 결과 값을 기대하긴 어렵다. 단 50 행 이하의 적은 숫자는 정확한 값을 구할 수 있다.

3 월 20 일 최종 소스 작성 및 최종보고서 검토- 배열크기가 불필요하게 커서 400 - >160 으로 축소 하였고, 연산 과정에서 오류가 발생해서

최종 수정을 했다. (sum[0]가ㅏ 0 이됬을 때 나눗셈 과정에서 숫자를 들여오지 못하는 오류)#include <stdio.h>#include <stdlib.h>

double sum[160]; //계산한값을 받을 더블형 배열int size; //반복문에서 사용될 배열의 크기,배열은 위의 크기로 선언되나

반복문에서는 필요한부분만 사용하여 연산int m,n; //입력받을 값의 변수

void Calculation();void main(){ int x; int y=0; printf("열을 입력해주세요 : "); scanf("%d",&n); printf("행을 입력해주세요 : "); scanf("%d",&m); size=2; for( x=0 ; x<160 ; x++ ){ //값을 계산할 배열 값을 초기화. 첫번째 배열만

if( x==0 ){ //로 선언하고 나머지는 모두 0 으로 선언 sum[x]=1;

continue; } sum[x]=0; } Calculation(); //값을 구하기위한 계산함수 printf("%d 번째 행의 %d 번째 열의 숫자는 ",n,m); for( x=size-1 ; x>=0 ; x-- ){ //답을 출력하는 반복문. 계산과정에서 값을

//저장하는 자료형의 크기의 한계를 극복하기위해 if(sum[x]!=0||y==1){ //일정 값을 넘어가면 넘치는 부분을 다음 배열에

Page 9: 자료구조 Project1

//저장하도록 하였기 때문에 결과값이 나누어져있어 if(y==0){ //한번에 출력할수없어 부득이 반복문을 사용하였다. printf("%.f",sum[x]); //배열이 0 일때는 출력하지 않도록 했고 결과값이

//나오면 그 밑의 값은 모두 출력하도록했다. y=1; continue; } printf("%09.f",sum[x]); } } printf("입니다.\n"); getch();

//이 코드에는 치명적인 결함이 있는데 값을 나누는 과정에서 자료형의 소수점 정밀도에 의해 오차가 생긴다는 점이다. //따라서 결과값의 정확한 자릿수 정도는 구할 수 있을지 모르나 정확한 결과값을 기대하긴 어렵다 //다만 50 행 이하의 적은 숫자는 정확한 값을 구할 수 있다.}void Calculation(){ //답을 구할때에는 공식을 사용했다.

//공식은 aCb = a!/a!/(a-b)! = (a*(a-1)*(a-2)*...*(a-b+1)/b! 이다 double a,b; //계산에필요한 변수 int c; //배열번호를 담당하는 변수 double buffer,temp; //연산에서 임시로 저장할 변수 int s=0; buffer=0; for(a=n-1,b=m-1;a>=(n-m+1)||b>0; ){ c=size-1; if(a>=(n-m+1)){ //공식의 분자부분. n*(n-1)*(n-2)*...*(n-m+1)를 수행한다 for(;c>=0;c--){ //sum[c]에 값을 곱했을때 값이 일정값을 넘으면

//sum[c+1]에 넘치는 값을 넘기도록 했다. sum[c]=sum[c]*a; //sum[0]은 기본적으로 1 이다. 다른 값은 0 이다. if(sum[c]>=1e+9){ //값이 9 자리를 넘을때 넘치는 값을 나누어 다음 배열에 넘기는 부분이다. temp=(unsigned)(sum[c]/(1e+9)); sum[c+1]=sum[c+1]+temp; sum[c]=sum[c]-(temp*(1e+9)); } if(sum[size-1]!=0) //반복문을 돌리는 배열중 최상위 배열이 0 이 아닐때 사용하는 배열을 늘린다. size++; } a--; } else if(b>0&&a==(n-m)){ //위의 분자부분 연산이 끝나면 분모부분의 연산을 수행한다.

//여기서는 매숫자마다 값을 나누어주어 저장하는 식으로 진행한다. for(;c>=0;c--){ if(sum[c]!=0&&s==0) //값이 존재하는 배열이 나올때까지 연산을 하지않기위해 이 구문을 넣었다. s=1; if(s==1){ //연산은 최상위 배열값 부터 나누어 내려가며 나눈값의

//수점이하 부분에 1e+9(1000000000)를 곱하여 if(sum[c]/b>=1){ //buffer 변수에 저장한다. temp=(sum[c]/b)+buffer; //배열에 buffer 를 더하고(첫 buffer 는 0 이다.) 연산할 값을 나눈후 임시값에 저장한다. sum[c]=(unsigned)temp; //나눈값은 소수점이 있을 수 있으므로 소수점이하는 버리고 정수부분만

Page 10: 자료구조 Project1

저장시킨다. buffer=(temp-sum[c])*(1e+9); //버퍼에 배열을 나누값의 정수부분을 뺀 나머지 소수부분에 1e+9 를 곱해준다.

} else if(sum[c]==0) sum[c]=buffer; else{ //배열값을 나눴을때 1 미만일 경우 배열에 0 을 저장하고 나머지값은 buffer 에 저장한다. buffer=sum[c]/b*(1e+9); sum[c]=0; } } if(c==0){ buffer=0; //최하위 배열의 경우 연산후 다음 연산을 위해 버퍼에 0 을 저장한다. s=0; } if(sum[c]>=1e+9){ //만약 배열에 저장된값이 1e+9 보다 클때 넘치는 값을 윗 배열로 넘긴다. temp=(unsigned)(sum[c]/(1e+9)); sum[c+1]=sum[c+1]+temp; sum[c]=sum[c]-(temp*(1e+9)); } } b--; } }}