Your SlideShare is downloading. ×
자료구조01
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

자료구조01

492
views

Published on

파스칼 삼각형 구현

파스칼 삼각형 구현


0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
492
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
3
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. C3조 과제물 발표
  • 2. 과제수행일지 조원소개 조장 박태원소 속 C3 조 자료조사 김슬기, 김남희 프로그래밍 정준용, 허규준과제수행기간 13 일 312 시간 주 제 연구제목 배열을 이용한 파스칼의 삼각형 n행 m열의 값, P(n,m) 계산하기 배열을 이용해 파스칼의 삼각형을 구성하는 숫자들의 행렬값 n, m을 입력받아 해당 행렬 에 존재하는 숫자의 값을 계산해 출력하는 프로그램의 알고리즘을 작성하고, 해당 알고리 연구배경 즘의 프로그램 소스를 작성해 시간 복잡도와 공간 복잡도를 직접 계산해 봄으로써 배열의 사용법과 시간 복잡도, 공간 복잡도에 관한 내용을 이해하고 프로그램 개선에 응용할 수 있는 능력을 기를 수 있다. 참 고 자 료참고 서적 C로 쓴 자료구조론(저자 : 이석호, 교보문고 2nd) http://skmagic.tistory.com/164 : 시간 복잡도의 정의와 유형, 계산법 소개 http://blog.naver.com/cat8815?Redirect=Log&logNo=60005751431 : 시간, 공간 복잡도의 정의와 계산법 소개 http://loudon23.blog.me/20017968979?Redirect=Log&from=postView : 알고리즘의 복잡도표 http://www.scienceall.com/dictionary/dictionary.sca?todo=scienceTermsView&classid= &articleid=256188&bbsid=619&popissue참고 URL : 파스칼의 삼각형의 형태와 규칙 소개 http://blog.naver.com/wilber96?Redirect=Log&logNo=124490423 : C언어 2차 배열을 이용한 파스칼 삼각형의 구현 http://whoknowwhat.blog.me/30039570929 : 배열을 이용한 무한 자리수의 출력 http://cafe.naver.com/cafec.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=9373 : 무한자 리수 출력 알고리즘을 이용한 팩토리얼 계산기(해당 url질문글에 대한 카페스탭 itoma님의 답변내 용) http://blog.daum.net/glsgnphoenix220/498 : c언어를 이용한 nCr값 계산기 소스 과제의 수행 첫째날 2012 년 3 월 8 일 목요일회의 주제 조원 자기소개 및 역할분담, 과제 파악 조장 : 박태원회의 내용 자료조사 : 김남희, 김슬기 프로그래밍 : 정준용, 허규준
  • 3. 이상과 같이 이번 프로젝트의 역할분담을 실시했습니다. 서로가 준비한 자료가 그리 많지 않았기에 프로젝트 내용이 제시된 pdf파일에 제시된 파스 칼의 삼각형 성질을 토대로 어떻게 하면 n행 m열에 존재하는 숫자값을 출력할 수 있을지 에 대해 논의를 시작했습니다. ∘파스칼의 삼각형은 P(n,m)으로 나타낼 수 있음. 여기서 n은 행이고 m은 열이다. - m=1 or m=n일 때, P(n,m) = 1 - P(n,m)=P(n-1,m-1)+P(n-1,m) PDF에 제시된 위의 두 가지 내용을 힌트를 사용해 배열을 가지고 어떻게 하면 파스칼의 삼각형 n행 m열의 숫자값을 구할 수 있을까에 대해 논의를 하던 중 파스칼의 삼각형을 배 열을 이용해 나타내는 방법을 이해하기 위해 우선 다른 사람들이 파스칼의 삼각형을 나타 내기 위해 어떤 방법을 사용했는지에 대해 프로그래밍 팀과 알아보기로 했습니다. http://blog.naver.com/wilber96?Redirect=Log&logNo=124490423 (2차 배열을 이용한 파스칼의 삼각형 구현 소스) 우선, 그 당시에 찾은 2차 배열을 이용한 파스칼의 삼각형 구현 소스를 응용해서 행렬값 [P(n,m)]을 구할 수 있지 않겠냐는 의견에 따라 아래와 같은 형태의 방법으로 P(n,m)을 구 할 수 있는 방법을 함께 생각해 봤습니다. 1000x1000사이즈의 배열을 지정한다 ↓ 파스칼의 삼각형 행렬의 값인 P(n, m)을 구하기 위한 n, m을 입력한다. ↓ m=1이거나 m=n이라면 1을 출력한다. 그렇지 않다면, 아래로 진행한다. ↓ 지정된 배열값에 파스칼의 삼각형의 행렬이 들어가도록 이중 for문을 이용한 파스칼의 삼각형 형태 구현 ↓ n행 m열에 해당하는 배열의 계산이 끝난 경우 n행 m열에 해당하는 배열값 [P(n,m)] 출력 프로그래밍 팀은 위처럼 간략하게 만들어진 알고리즘을 바탕으로 다음 수업시간까지 프로 그램 소스를 작성해 어떤 문제점이 발생하는지 찾아보기로 했습니다. 한편, 교재에 수록된 공간 복잡도(space complexity)와 시간 복잡도(time complexity)를 설명하는 내용만으로는 복잡도에 대해 조원들이 완벽하게 이해하기 어렵다고 판단해 직접 계산하는 자료조사팀인 남희와 슬기가 과정이 담긴 예제와, 이해하기 쉽게 내용이 정리된 자료를 찾기로 했습니다. - 복잡도(complexity)에 대한 이해부족문제점 - 파스칼의 삼각형에 대한 이해부족반성 정해진 수업 내용을 듣고 그저 암기하는 것이 아니라 과제 수행에 필요한 내용을 직접 찾 - 2 -
  • 4. 아서 익히고 응용해야 한다는 점에서 이전까지 해왔던 수업 방식에 비해 까다롭고, 어렵게 느껴졌습니다. 첫 수업이다 보니 과제 해결에 대한 준비도 많이 미흡했고 서로의 역할을 분담하는데 만도 오랜 시간을 사용해 버려서 과제의 요지를 파악하고 이를 해결할 수 있는 알고리즘을 구상하는데 필요한 시간을 제대로 분배하지 못했습니다. 다음 회의 전에는 좀 더 많은 자료들을 준비해서 알고리즘의 구상과 그 개량에 중점을 둘 수 있게 준비하도록 했습니다. 둘째날 2012 년 3 월 13 일 목요일회의주제 시간, 공간 복잡도에 대한 조사내용 발표, 프로그램 소스 초안 발표 및 개량방안 제시 슬기와 남희가 조사해온 복잡도에 관한 내용을 함께 공부하고 주말간 제작해 온 프로그램 소스의 시간, 공간 복잡도를 직접 계산해 보기로 했습니다. 시간 복잡도의 정의 - 어떤 알고리즘을 실행하는데 얼마나 오랜 시간이 걸리는가 - CPU성능과 관계가 있습니다. 시간 복잡도의 세가지 표기법 - 세타[Θ(~)] 표기법 : 알고리즘 실행 시간의 평균적인 결과를 나타내는 표기법. - 오메가[Ω(~)] 표기법 : 알고리즘 실행 시간에 있어서 최선의 결과를 나타내는 표기법. - 빅오[O(~)] 표기법 : 알고리즘 실행 시간에 있어서 최악의 결과를 나타내는 표기법으로 가장 보편화되어 사용되고 있습니다. 빅오[O(~)] 표기법이 주로 쓰여지는 이유 - 평균적으로 10의 수행시간을 가지는 프로그램 소스라도 최악의 경우 100의 수행시간을 가지게 된다면 평균적으로 20의 수행시간을 가졌지만 최악의 경우에도 20의 수행시간을회의내용 유지할 수 있는 프로그램 소스에 비해 우수하다고 할 수 없기 때문입니다. 시간 복잡도의 계산 예제 해당 명령의 실행 횟수를 계산해 오른쪽에 적습니다. 사례) void Func(int *a, n) { int i=0, j=0; // 1 for (i = 0 ; i < n-1 ; i++) // n for(j=i+1; j<n ; j++) // (n-1) * n if (a[i] == a[j]) a[j] = 0 ; // (n-1) * (n-1) } 이상과 같이, 계산된 명령의 실행 횟수를 모두 더해보면 이 명령이 최악의 경우 2n^2 – 2n + 2회 실행된다는 사실을 알 수 있습니다. 이것을 빅오 표기법으로 적으면 O(2n^2 – 2n + 2)가 되고 상수항을 없앤 후 최고차항만 남기면 O(n^2)가 되는데 이 것이 위 프로그램 소스의 시간 복잡도가 되는 것입니다. (출처 : http://skmagic.tistory.com/164) - 3 -
  • 5. 시간 복잡도의 유형(아래쪽에 표시된 유형일수록 성능이 낮습니다)(출처: http://loudon23.blog.me/20017968979?Redirect=Log&from=postView )공간 복잡도의 정의- 알고리즘을 실행하는데 필요한 메모리 사용량- RAM성능과 관계가 있습니다.공간 복잡도의 구성- 고정 공간 요구 : 프로그램 코드를 저장하기 위한 공간과, 프로그램을 수행하기 위해 시 스템이 필요로 하는 공간 등이 이곳에 해당합니.- 가변 공간 요구 : 알고리즘의 특성과 밀접한 관계가 있는 부분이다. 문제를 해결하기 위 한 변수와 순환 스택 등이 포함된다. 일반적으로 알고리즘의 공간 복잡도를 계산하라고 하면 이 가변 공간 요구량을 계산하는 것으로 알고리즘이 문제를 해결하기 위해 필요한 공간만을 계산합니다.공간 복잡도의 계산 예제 float Sum(float a[], int n) { float s = 0.0; for(int i = 1; i < = n; i++) s += a[i]; return s; } 해당 사례의 소스가 명령을 수행하는데 필요한 공간은 아래와 같습니다. - 배열 a[]가 저장될 공간 : 배열 a[]가 n개만큼 만들어지므로 n - 변수 n, i, s가 저장될 공간 : 각각 하나씩의 공간을 차지하므로 3 그러므로 해당 소스의 공간 복잡도는 n+3이 됩니다.(출처 : http://blog.naver.com/cat8815?Redirect=Log&logNo=60005751431 ) - 4 -
  • 6. 이상의 조사 내용을 바탕으로 조원들에게 복잡도에 대해 설명함으로써 조원들이 복잡도의개념에 대해 이해할 수 있게 되었으며 규준이와 준용이가 제작한 아래 소스를 통해 직접시간 복잡도와 공간 복잡도를 계산해 볼 기회를 얻었습니다.P(n,m)의 계산 소스 초안 #include<stdio.h> #define LINE 101 int main(void) { int i,j,k,n,m; //변수 지정 unsigned long long a[LINE][LINE]={0,}; //2차 배열의 지정 for(i=1;i<LINE;i++) //열의 값이 행과 같거나 1일 때, 1을 출력하도록 { a[i][i]=1; a[i][1]=1; } for(i=3;i<LINE;i++) //3행 이후부터 2 이상의 수가 파스칼의 삼각형에 나오므로 3행부터 계산 { k=1; for(j=2;j<LINE;j++) //P(n,r) = P(n-1, m-1) + P(n-1, m) { a[i][j] = a[i-1][k] + a[i-1][k+1]; k=k+1; } a[i][i]=1; } for(;;) // 출력 { printf("P( N(행의 수) , M(열의 수) ) 를 입력 하시오)"); printf(" N = "); scanf("%d",&n); printf(" M = "); scanf("%d",&m); printf("P(%d.%d) = %llu ",n,m,a[n][m]); } return 0; }행(n)과 열(m)을 입력받아 P(n,m)을 출력하는 프로그램 소스의 초안입니다. 파스칼의 삼각형은 아래쪽으로 가면 갈수록 그 수가 기하급수적으로 커지기 때문에 unsigned longlong를 사용해 큰 값도 출력할 수 있도록 했습니다.처음 계획과 달라진 부분은 우선 처음 부분의 배열 크기(LINE)인데 1000x1000 크기의 배열을 만들려고 하던 기존의 계획은 100만개에 달하는 배열을 할당하면 파일의 공간 복잡도가 지나치게 커질뿐더러 지나치게 큰 배열의 크기를 컴퓨터가 오류로 인식하는 바람에 배열의 크기를 그 1/100정도로 작게 만들 수 밖에 없었습니다. 또한 60행이 넘어가면 long함수로도 출력하지 못할 크기의 숫자값들이 나타나 해당 P(n,m)값을 출력해낼 수 없다는단점도 있었습니다.또한 시간 복잡도의 형태가 O(n^2)이 되는데 큰 값이 입력될수록 수행시간이 기하급수적으로 커지는 나쁜 형태의 알고리즘이 되었다는 지적을 받아 이를 해결할 방법을 찾기 위해논의했지만 결국 그 해결책을 찾지 못한 채 마쳤습니다. - 5 -
  • 7. - 2차 배열의 크기문제로 기존에 구상한 알고리즘을 이용해 P(n,m)값을 구할 수 없다. - 시간 복잡도의 형태가 O(n^2)이 되어 그리 좋다고는 할 수 없는 형태가 되었다.문제점 - long함수로도 출력하지 못하는 커다란 숫자값을 출력할 방법이 없다. - 앞서 제시한 문제점을 전혀 깨닫지 못한 채 간과하고 있다가 드러난 문제들의 해결점을 찾 지 못한 채 흐지부지 원점으로 돌아갔다는 점에서 C언어에 대한 이해도가 좀 더 높았다면 어떤 결과가 나왔을지에 대한 아쉬움이 컸습니다. 반성 우선 시간 복잡도의 부분을 제쳐두고, 파스칼의 삼각형 1000행 까지의 값을 온전히 계산해 낼 수 있는 다른 방법과, 천문학적인 숫자로 계산되는 P(n,m)의 값을 온전히 출력할 수 있 는 방법을 찾는데 주력하기로 했습니다. 셋째날 2012 년 3 월 15 일 목요일회의주제 배열을 이용한 무한자리수 출력 소스에 대한 소개, 새로운 알고리즘 작성 2차 배열을 이용해 파스칼의 삼각형의 행렬값 P(n,m)을 계산해 출력해내는 방법으로의 과 제수행이 불가능하다 여겨졌기 때문에 조원들에게 새로운 방법을 제안했습니다. ‘P(n,m) = n-1Cm’의 성질을 이용해 해당 값을 구하고 이 결과를 배열을 통해 출력하는 방식인데 그 핵심은 아래와 같습니다. 배열을 통한 무한자리수의 저장 소스 for( i=0 ; i<n-1 ; i++ ) { while( a[i]>=100000 ) { a[i]-=100000; a[i+1]++;회의내용 } } (소스출처 : http://whoknowwhat.blog.me/30039570929 ) a[j]의 값이 10만이 넘으면 그 값에서 10만을 빼고, a[j+1]에 1을 더해주는 명령입니다. 예 를 들어 a[0]의 값에 123456의 값을 넣어줬다면 해당 명령을 거쳐 a[0]에는 23456의 값이, a[1]에는 1의 값이 저장되는 형태인데 이를 응용해 a[0]과 a[1]을 ‘a[1]a[0]’의 형태로 역순 출력하게 되면 ‘123456’이 된다는 점을 이용해 5자리 단위로 끊어 배열의 크기가 허락하는 한 커다란 단위의 숫자도 문제없이 출력할 수 있게 되는 것입니다. 위와 같은 방법을 이용해 P(n,m)의 값을 구해 배열에다 저장할 수 있다면 지난번 해결하지 못했던 배열의 크기 문제와 커다란 수를 출력하지 못하는 문제를 동시에 해결 할 수 있게 되었기에 조원들과 함께 아래와 같은 새로운 형태의 알고리즘을 구상하게 되었습니다. - 6 -
  • 8. scanf를 통해 파스칼의 삼각형의 행렬(n,m)을 입력한다 ↓ 입력한 형태의 값이 적절한가? no=>강재종료, 재입력 or yes-=>다음으로 진행 ↓ m=1 or m=n? yes=>1 출력 or no=>다음으로 진행 ↓ n-1Cm의 값을 배열 a[0]에 저장 ↓ 배열을 이용한 a[0]값의 저장 ↓ for문을 통한 배열 a[]의 역순 출력참고자료 – 팩토리얼 계산기 소스 #include <stdio.h> #define CboxAGE_MAX 5000 // 배열 최대값 지정 int main(void) { int a, i, j; unsigned long int block[CboxAGE_MAX]; // 배열 지정 block[0]=1; // 동기화 for (j=1; j<CboxAGE_MAX; j++) block[j]=0; printf("Input factorial numbern"); scanf("%d",&a); //계산하고자 하는 팩토리얼 값 입력 for(i=1; i<=a; i++) { for (j=0; j<CboxAGE_MAX; j++) block[j]*=i; /* 팩토리얼 계산 */ for (j=0; j<CboxAGE_MAX-1; j++) while (block[j]>=100000) {block[j+1]++; block[j]-=100000;} /* 5자리수 단위로 끊어 출력할 결과값을 배열에다 지정 */ } printf("nResult: %d! = n", a); for (j=CboxAGE_MAX-1; j>0; j--) //배열의 역순출력 if (block[j]>0) printf("%05d x10^%d +n", block[j], j*5); printf("%05dn", block[0]); return 0; }(소스출처: http://cafe.naver.com/cafec.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=9373해당 url질문글에 대한 카페스탭 itioma님의 답변내용 중 발췌)위의 팩토리얼 계산기의 소스를 참고로 해 조원들과 구상한 알고리즘을 통해 이전에 제작했던 프로그램 소스에 비해 훨씬 적은 공간을 사용하면서도 해당 과제물에서 가장 커다란 값으로 출력되 - 7 -
  • 9. 는 1000행 500열의 숫자값까지 이상없이 출력할 수 있게 될 것을 기대할 수 있었습니다.문제점 - n-1Cm 계산 알고리즘의 부재 거의 다 됐다고 생각했지만 n-1Cm의 계산을 수행하는 알고리즘의 세부적인 구상을 해결 반성 하지 못했다. 대신 얼마 남지 않은 기간이나마 과제를 해결하기 위한 최선의 방향을 잡아 냈으며 좀 더 세부적인 자료조사가 병행되면 문제를 해결 할 수 있을 것이라 생각된다. 넷째날 2012 년 3 월 19 일 월요일회의주제 파스칼의 행렬값 출력 프로그램 소스에 대한 소개, 개량안 제시 n-1Cm의 값을 배열에다 저장하는 방법으로 nCr = 1/(1*1) x 2/(2*2) x ... x (n-r)/(n-r)*(n-r) x (n-r+1)/(n-r+1) x r/r x ... x n의 형태로 구성되어 있다는 점을 이 용해 for문과 if문을 이용한 반복구문을 넣음으로서 해결했습니다. 이상의 내용을 바탕으로회의내용 규준이가 프로그램 소스를 작성했는데 그 내용은 아래와 같습니다. 파스칼의 삼각형 n행 m열의 값 P(n,m)을 구하는 프로그램 소스 (다음 쪽에서 이어짐) - 8 -
  • 10. #include <stdio.h> #define MAX 300 // 배열의 크기 300 int main(void) { int n,r, i, j,cnt=0,k=1,r2=0,nt,rt; unsigned long int box[MAX]; // 배열 지정 box[0]=1; //동기화 for (j=1; j<MAX; j++) box[j]=0; // 배열의 최대 크기 : MAX printf("파스칼의 삼각형 n행 m열의 값 P(n,m)을 구하기 위한 n의 값을 입력하시오 n"); scanf("%d",&n); printf("파스칼의 삼각형 n행 m열의 값 P(n,m)을 구하기 위한 m의 값을 입력하시오n"); scanf("%d",&r); //변수 입력 rt=r; //rt : 열의 값 nt=n-1; //nt : 행의 값 r=r-1; r2=r; if(nt/2>r) /*파스칼의 삼각형은 대칭의 형태를 이루고 있음을 이용해 계산 과정을 줄였다 .*/ { r=nt-r; } for(i=nt; i>r; i--) { for (j=0; j<MAX; j++) { box[j]=box[j]*i; } cnt=cnt+1; if(cnt<=nt-r) { box[0]=box[0]/k; k++; } for (j=0; j<MAX-1; j++) { while (box[j]>=100000) {box[j+1]++; box[j]-=100000;} } } /* 여기까지가 n행 m열의 값을 구해 배열에 입력하는 부분 */ printf("P(%d,%d)의 값은n", n,rt); for (j=MAX-1; j>0; j--) if (box[j]>0) printf("%05d x10^%d +n", box[j], j*5); printf("%05dn", box[0]); return 0; } //for문을 이용한 결과값의 출력 해당 소스는 팩토리얼 계산기의 소스를 응용해 for문을 통한 계산식 내부에서 n행 m열에 해당하는 결과값을 계산한 후 그 결과값을 배열 box[]에 10^5단위로 끊어 저장하고 해당 배열을 역순으로 출력함으로서 n행 m열의 값에 해당하는 P(n,m)을 출력할 수 있도록 하 는 형태를 하고 있습니다. 회의 중점은 해당 소스의 개량안과 공간복잡도의 계산에 대한 내용을 위주로 진행되었으며 회의 결과 if문을 이용한 구절을 추가해 잘못된 변수가 입력되었을 경우 프로그램이 강제 종료되도록 하고 그 외에 프로세스에 큰 영향을 미치지 못하는 불필요한 변수들을 제거하 는 것으로 프로그램의 개량에 대한 내용을 마치고 공간복잡도의 계산을 실시하도록 결정되 었습니다. - 공간복잡도에 대한 이해 미숙문제점 - 잘못되었거나 1000행 밖의 값이 입력되더라도 계산을 진행한다. - 9 -
  • 11. 2차 배열을 통해 파스칼의 삼각형의 P(n,m)값을 구하려 했던 이전의 방식에 비해 적은 메 반성 모리 사용량을 가지게 되었다고 예상하고 있으나 공간 복잡도에 대한 이해 미숙으로 해당 소스의 공간복잡도를 계산하지 못했습니다. 결과 발표 #include <stdio.h> #define MAX 300 int main(void) { int n,r, i, j,cnt=0,k=1; unsigned long int box[MAX]; box[0]=1; for (j=1; j<MAX; j++) box[j]=0; printf("P(n,m)에서 n값을 입력하시오 ( 조건 : n<=1000, r<=n )n"); scanf("%d",&n); printf("P(n,m)에서 m값을 입력하시오 ( 조건 : n<=1000, r<=n )n"); scanf("%d",&r); if(r==0||n<r||n>1000) { printf("해당하는 값이 없으므로 종료 합니다n"); return 0; } if(n==r||r==1) { printf("해당하는 값은n00001"); return 0; } n=n-1; r=r-1; if(n/2>r) { r=n-r; }프로그램 소스 for(i=n; i>r; i--) { for (j=0; j<MAX; j++) { box[j]=box[j]*i; } cnt=cnt+1; if(cnt<=n-r) { box[0]=box[0]/k; k++; } for (j=0; j<MAX-1; j++) { while (box[j]>=100000) { box[j+1]++; box[j]-=100000; } } } printf("해당하는 값은 n"); for (j=MAX-1; j>0; j--) if (box[j]>0) { printf("%05d x10^%d +n", box[j], j*5); } printf("%05d입니다.n", box[0]); return 0; } - 10 -
  • 12. 알고리즘 개요 시간 복잡도 - O(904+a(1000행 500열 출력시 while반복횟수))(n-r) + 917) = O(n)복잡도 계산 공간 복잡도 - 602n-602r+6 좀 더 시간을 두고 알고리즘을 개량 할 수 있었다면 더 좋은 결과를 낼 수 있었을 것 같아 아쉬움이 남습니다. 하지만 이번 프로젝트 중에 가장 아쉬웠던 점은 조원들의 C언어에 대 최종 반성 한 이해도가 전체적으로 낮다는 점인데 앞으로의 과제를 수행해 나가면서 좀 더 공부해 다 음 프로젝트부터는 좀 더 좋은 결과를 낼 수 있었으면 좋겠다고 생각합니다. - 11 -

×