SlideShare a Scribd company logo
1 of 72
Download to read offline
프로젝트 보고서
 프로젝트#1 파스칼의 삼각형




     소속 : 컴퓨터 공학과
     조 명 : A1
     조원 : 김형오, 오승원, 정상혁, 강수현
◎프로젝트 목적
        ⇒ 배열의 사용법을 안다.
        ⇒ 프로그램의 시간, 공간 복잡도 계산 할 수 있다.




◎조원별 업무파악

조장 김형오 : 공간복잡도에 대한 조사 , 출력부분에 대해서 조사
오승원 : 전체적인 코딩, 회의를 통해 의견 수렴 후 소스 수정
정상혁 : 시간복잡도에 대한 조사 , n과 m을 입력 받는 부분에 대해서 조사
강수현 : 보고서 구성 & 작성 , 배열과 파스칼의 삼각형에 대한 내용 조사




◎반성
  무작정 소스를 구현을 한다는 목적만을 가지고 프로젝트를 진행을 하는 것보다는 주어진 문제에 대해서 많
은 정보를 수집을 하고 수집된 자료와 참고 서적을 가지고와서 논의를 하다가 모르는 부분이 있으면 바로바로
확인을 하고 해결을 하여 프로젝트에 대한 회의가 원활히 진행이 될 수 있도록 해야 한다. 회의를 하면서 수
정했던 내용, 어떤 부분에 대해 논의 했는지 모든 내용들을 메모해서 보고서에 포함시켜야 할 것이다.


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


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


-(예) int array[4];
        ⇒ int형 변수 4개로 이뤄진 배열을 선언하되, 그 배열의 이름을 array로 한다!!
        ⇒ int : 배열을 이루는 요소(변수)의 자료형
        ⇒ [4] : 배열의 길이

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


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


-(예) arr[0]=10;
        ⇒ 배열 arr의 첫 번째 요소에 10을 저장해라!!


-[ 인덱스 값 ]
        ⇒배열의 위치 정보를 명시하는 인덱스 값은 1이 아닌 0에서부터 시작.
- 배열을 선언과 동시에 초기화하는 방법
       ⇒ (예1) int arr1[5]={1, 2, 3, 4, 5} 순차적으로 1,2,3,4,5로 초기화 함.
                 1       2   3   4   5


       ⇒ (예2) int arr2[ ]={1,2,3,4,5,6,7}; 컴파일러에 의해서 자동으로 7이 삽입됨.
            초기화리스트가 선언되면 배열의 길이정보를 생략할 수 있다. 컴파일러가 초기                                           화 리스트의
수를 참조하여 길이정보를 채워주기 때문이다.
                1        2   3   4       5     6        7


       ⇒(예3) int arr3[5]={1,2}; 3,4,5번째 배열요소는 0으로 채워짐.
                1        2   0   0   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>

#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 ) = %dn", n, m, arr[n-1][m]); // p(n,m) 값 확인
        }
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)
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)=%dn", 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++)
{
                   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 ) = %.0fn",n,m,arr[n-1][m-1]);// p(n,m) 의 값을 출력
}


       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)를 찾는 것
세타
- 오메가와 빅오의 교집합 즉, 평균적이다.
- 제일 정확하다.
- Θ(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 참고
A2조 자료구조
 프로젝트 보고서
[Project #2 : 말(馬)의 여행]




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


               자료조사 :
                                          프로그래밍 :                    보고서 작성 :
  A2         김형오, 박우용
                                         김형오, 박우용                        박다솔
             민영지, 박다솔


과제수행기간                                     12일 8시간

                               I. 계획의 작성

 연구제목     말(馬)의 여행



          말의 여행을 통해서 스택, 큐, 백트래킹의 원리를 알고 말이 움직인 행적(지나간 자리)
 연구배경     을 표시하여 장기판을 다 돌게 하는 프로그램의 알고리즘을 작성, 프로그램 소스 코딩
          을 해 보면서 스택, 큐, 백트래킹에 대해 적용을 할 수 있다.




                    윤성우의 열혈 자료구조(C언어를 이용한 자료구조 학습서) / 윤성우 지음
          참고 서적     / 오렌지 미디어
                    열혈강의 자료구조 / 이상진 지음 / 프리렉
                    C언어로 쉽게 풀어쓴 자료구조 / 천인국, 공용해 지음 / 생능
 참고자료



                    http://www.winapi.co.kr/
          참고 URL    http://lwove.egloos.com/
                    http://internet512.chonbuk.ac.kr/datastructure/stack/stackq.htm#/


                               II. 계획의 실행

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

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


         조장 : 김형오
         자료조사 : 민영지, 박다솔
         프로그래밍 : 김형오, 박우용
토의 내용

         위와 같이 조원의 업무를 분담했다. 프로그래밍과 자료조사를 조원들끼리 나누어서 하
         는 게 효율성은 좋지만, 이 프로젝트를 하기 위해서는 스택, 큐, 백트래킹에 대해 개념
         을 다 알고 이해해야 했기 때문에 효율성보다는 효과성을 택했다. 그래서 이 프로젝트
에 대한 소스도 각자 생각해오고 하기로 하였다.



         새로운 프로젝트가 제시가 되고 새로운 조를 편성을 함에 따라 새로 정해야하는 것들이
과제준비에서
         생겨났고 이러한 것들을 빨리 해결을 하는 것과 동시에 프로젝트의 문제를 파악하고 적
 느낀 점
         절하게 임무를 분담을 하였다.


 둘째 날                       2012년 3월 31일 토요일
오늘의 작업                   각자 조사해온 내용에 대한 토의


         말의 여행 프로젝트를 수행하기 위해서는 가장 먼저 이해해야 할 스택과 큐, 백드래킹
         을 중심적으로 설명하고, 토의를 하였다.


         •Stack
         -정의 ; 여러 개의 데이터 항목들이 일정한 순서로 나열된 자료 구조
         -먼저 삽입된 것은 나중에 삭제되고, 나중에 삽입된 것이 먼저 삭제된다. 한쪽 끝에서만
         새로운 항목을 삽입하거나 기존의 항목을 삭제할 수 있도록 고안된 것
         -실생활의 예 : 동전을 넣고 뺄 수 있도록 되어 있는 동전 케이스
         주차장에 주차한 자동차(나보다 나중에 들어온 차들 때문에 나갈 수가 없다, 결국 나중
         에 들어온 차들이 모두 나갈 때까지 기다린 후에 차를 뺄 수 있다)


         *Back traking
         -검색 공간의 모든 가능한 배치 방법에 대해 어떤 작업을 반복하기 위한 조직적인 방법
토의 내용
         -백트래킹은 용도에 맞게 개별적으로 구현해서 써야 하는 범용알고리즘 기법
         -함수가 실행되는 것과 비슷한 방식으로 컴퓨터 내부에서 실행이 됨 (함수안의 함수)


         •Queue
         -정의 : 리스트의 한쪽 끝에서는 원소들이 삭제되고 반대쪽 끝에서는 원소들이 삽입만
         가능하게 만든 순서화된 리스트
         -실생활의 예 : 은행에서 순서대로 번호표를 뽑게 하고 일을 처리해주는 예
         버스정류장에서 먼저 온 순서대로 탑승하는 예
         물건을 구매할 때 줄을 서서 계산대에서 계산을 기다리는 예


         서로 각자가 공부를 해오고 모르는 것을 서로에게 질문하였고, 교수님께서 말씀하신 스
         택과 큐, 백트래킹이 실생활에 어디에 사용되는지 생각해보라고 하셔서 조원들이 함께
         생각해보고, 교수님께 추가적인 설명들을 듣고 하였다.




         스택과 큐와 백트래킹에 대해서 찾아보았지만 백트래킹에 대한 내용이 스택과 큐에 비
과제준비에서   해서 많이 적었다. 그래서 도서관에 가서 자료구조에 대한 정리가 되어있는 책들을 찾
 느낀 점    아보고 백트래킹에 대한 개념을 찾아내긴 했지만 아직 확실하게는 파악을 못하였고 이
         로 인해서 백트래킹에 대해서는 다시 한 번 더 조사를 하기로 하였다.
셋째 날                               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
중위 표기법 -> 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일 일요일
오늘의 작업                          말의 여행 초안 소스에 대한 토의


         말이 어떠한 방향으로 이동을 해야할까?에 대해서 많은 고민을 했었습니다.
         그러다가 난수를 설정을 하여서 임의로 가도록 해보기도 했지만, 결국은 모든 좌표를
설계 방법
         돌아다니지를 못하였습니다. 그래서 다른 방법을 고안을 하여 말이 움직이는 방향을 정
         하여서 이곳으로만 이동을 하도록 하는 것보다는 갈수 있는 방향을 제시만을 해주고 범
         위에서 벗어나지 않도록만 설정을 하여서 갈수 있는 방향을 찾아가도록 하였다.
그리고 더 이상 가지 못하는 경우가 발생하는 것은 갈 수 있는 방향이 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;
 }
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)
                         {
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);
}


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];
}
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);//갈수 있는 모든곳을 푸시
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);
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;
                   }
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++)
        {
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;
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];
           }


                                          Ⅳ. 반성




과제를 마치면서   각자 조원들이 자료를 조사해오고 같이 토의하면서 모르는 것을 질문하고 가르쳐 줌으
  느낀 점     로써 스스로 공부해오고 알아가는 프로젝트 과제의 장점을 느낄 수 있었다. 개개인이
           조사해오는 자료마다 조금씩 달라서 조원이 다 같이 이해하고 정보를 습득 하는 데에서
           는 시간이 지체되었고, 살짝 어려움이 있었다. 하지만 이 부분도 프로젝트의 단점이라고
생각 할 수 있겠지만 어떻게 보면 장점이라고 생각 할 수도 있었다. 프로젝트를 C언어
로 코딩을 해야 하는 점에서 아직 조원들이 많이 부족하다는 것을 느낄 수 있었고,조금
더 공부하고 더 연습해야겠다는 것을 몸소 느꼈고, 매 수업시간마다 그리고 온라인으로
만나는 시간마다 회의를 할 때 회의록을 작성하여서 보고서의 질을 좀 더 높일 수 있었
을 텐데…라는 아쉬움이 남았다.
B0 프로젝트 보고서 #3
                                                                                조장 09 오승원
                                                                                팀원 09 김형오
                                                                                    09 장진승
                                                                                    11 성주희
                                                                                    11 정상혁

                           역할 분담                    팀원
                                         09 오승원, 김형오, 장진승
                         자료조사 및 이해
                                         11 성주희, 정상혁
                                         09 오승원, 김형오
                              코딩

                             보고서         09 장진승


* 문제 파악
링크드 리스트를 이용하여 다항식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.htm
  http://blog.naver.com/pjy9954?Redirect=Log&logNo=70128298541
  http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Database/DataStructure/LinkedList
링크드 리스트는 각 데이터를 서로 연결해서 관리하며 , 이때 각각의
              데이터를 노드(node)라고 불리우는 Unit에 넣어서 관리한다. 스택이나 큐와 같은 경우
링크드 리스트란?     각 위치에 데이터자체가 저장되는 것과는 약간다르다 . 이처럼 데이터를 노드에 넣어
              서 관리하는 이유는 데이터의 리스트를 유지하기 위해서 데이터외에도 다음 데이터의
              위치를 나타낼수 있는 어떤 부가적인 정보가 필요하기 때문이다.
              1)싱글 링크드리스트(단일 연결리스트 )
              각 노드는 저장하고자할 데이터와 다음 노드를 가리키는 포인터를 포함한다. 싱글링
              크드리스트에서 각 노드는 다음노드의 위치를 가리키기 때문에, 우리는 반드시 시작
              노드의 위치를 알고 있어야만 할것이다. 또한 이전노드의 위치는 알수없도록 되어 있
              다.

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

링크드 리스트의 종류   노드를 가리키는 포인터도 가지고 있다 . 전방향 , 후방향어느 쪽으로든지 순환이 가능
              한 링크드리스트이다.


              3)환형 연결리스트
              환형 연결 리스트에서는 노드의 시작과 끝을 구별하지 않음으로써 마지막 노드와 처
              음 노드가 연결되어 있음으로 임의의 노드에서 다른 모든 노드로의 접근이 가능하여
              임의 노드의 검색이 가능하게 된다 . 단순 연결 리스트의 경우 정보가 끊어지면 그 다
              음은 찾을 수가 없는데 환형 연결 리스트는 그것을 극복할 수 있다.




링크드 리스트의 구조
              데이터의 위치를 나타내기 위해서 사용할수 있는것은 pointer가 될것이다 . 즉 노드는
              데이터와 함께 다음 데이터의 위치정보를 가지고 있는 "포인터 "를 포함하게 된다.




                           장점 : 구현이 간단하다
              배열을 이용
                           단점 : 크기에 제한이 있다 , 삽입과 삭제시 오버헤드가 발생한다
리스트의 구현방법
                           장점 : 크기에 제한이 없다
              포인터를 이용
                           단점 : 구현이 복잡하다


              배열의 경우 연속적인 공간에 위치함으로 특정위치에 있는 데이터에 접근하고자 할때
              O(1)의 시간이 소모된다 . 링크드리스트의 경우 O(N)의 시간이 소모된다. 처음노드부
              터 순환을 해야하기 때문이다.
 배열(스택,큐)과
   비교되는       배열의 경우 처음과 마지막에 데이터를 삽입하는건 매우 쉽고 효율적이지만 중간에
링크드 리스트의      있는 데이터를 삭제하거나, 삽입하는건 상대적으로 어렵고 비효율적이다 . 링크드 리스
              트는 이러한 경우 매우 효율적이다.
    특징
              배열의 경우 일단 만들어진 사이즈를 조정할 수 없으나 링크드리스트는 자유롭게 사
              이즈를 조정할 수 있다.
              장점   새로운 노드의 추가, 삽입 ,삭제가 쉽고 빠르다
 링크드리스트의           다음 링크를 가리키는 포인터가 4Byte씩 잡아먹는다
              단점   첫 노드부터 마지막 노드까지 순서대로 검색을 하기 때문에 , 최악의 경우 배
   장단점
                   열보다 자료를 검색하는데 들어가는 시간이 더 걸릴 수 있다.
*일정별 토의 내용
  날짜                              토의 내용
           *이번 프로젝트의 조장을 정함
           *이번 프로젝트를 할 때 전체적인 일정을 정함
           - 토의 일정을 화,목 9시부터 수업시간 전까지로 정하고 따로 한 번
            더 만 날 일이나 토의할 내용이 있으면 네이트온을 통해서 만나기
 4/12(목)
            로 결정
           *다음 모임 전까지 각자 링크드 리스트에 대해 공부를 하고 공부를 하
           면서 봤던 자료 중 정리가 잘 돼있다고 생각되는 자료를 공유하기로
            결정
           *목요일부터 링크드리스트에 대해 각자 조사 했던 것을 공유
           *각자 다항식에 대해 구상했었던 알고리즘에 대한 토의
            - 변수명을 P(x)와 S(x)는 각각 P,S라 두고 계수와 차수에 대해서는
             각각 a1,n1으로 하기로 결정
            - 덧셈, 뺄셈, 곱셈은 덧셈으로 모아지는 모양새를 발견함
            - 나눗셈에 대한 결론은 내리지 못하였음
 4/17(화)    - 입력 부분에 대해서는 각자 소스를 짜보면서 각자 생각한대로 해
             보기로 결정
           *식 전체를 입력 받고 그 식에서 계수와 차수를 추출, 연산에 사용하
           는 방식을 사용하기로 결정
           *각 파트별로 역할을 결정
            - 덧셈 : 11성주희, 뺄셈 : 09김형오, 곱하기 : 09오승원, 나눗셈 : 11정상혁
             - 보고서 작성 : 09장진승
           *사칙 연산에 대해 각자 파트를 나눠 구상/작성 하기로 하였으나 입력
           부분이 해결되지 않아서 인지 어떻게 해결하고 작성해야 하는지에 대
           한 구상은 일정부분 고민을 많이 해온 듯 하지만 작성까지 진행 되지
           못하였음
           *입력 부분에서 생각의 전환이 생김
           - 09김형오가 전체를 입력 받고 계수와 차수를 추출하여 이용하는 입
            력 부분 코딩 구상
           - 09오승원이 계수와 차수만을 입력 받는 부분의 입력 코딩/구상 작
 4/19(목)    성
           - 교수님의 조언에 따라 다항식 전체를 입력받고 그 입력 받은 부분
            에서 필요한 부분을 추출 해내는 방식에서 계수와 차수 이 두 가지
            를 받는 쪽으로 변경함(다항식의 변수 x같은 경우는 누구나 다 아는
            일반적인 사실이므로 결국 실질적으로 계산되는 계수와 차수만을
            입력 받으면 되는 것이고 출력에서는 x까지 나타나는 완벽한 다항
            식을 출력하면 되는 것)
           *입력 부분을 확실히 정하였으므로 남은 기간 입력 부분과 연계하여
           각 파트에 대한 코딩을 완성시키기로 결정
*소스코드
-파트별


                                          입력부분

  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;
           }
  }
덧셈
// 덧셈을 하는 함수
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)//차수비교
                 {
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
*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++;
}
차수 비교를 통한 내림차순 정렬
// 식을 차수를 통해 내림차순 정렬해주는 함수
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 %dn",p->a1,p->n1);
        }
}
-전체
#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);
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("nn빼기n");
sub(&list3,&list4,&list6);// 정렬된 두 식의 뺄샘
print(&list6);

printf("nn곱하기n");
mul(&list3,&list4,&list7);// 정렬된 두 식의 곱셈
arra(&list7,&list8);
print(&list8);

printf("nn나누기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);
}
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;
         }
}
// 곱셈을 하는 함수
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);
}


// 식을 차수를 통해 내림차순정렬 해주는 함수
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;
}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);
                  }
        }
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
출력결과 01




출력결과 02
B0 활동 보고서 #4
                                                                                     조장 11 정상혁
                                                                                     팀원 09 김형오
                                                                                        09 오승원
                                                                                        09 장진승
                                                                                        11 박다솔

                              역할 분담                               팀원

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

                                              09 오승원, 김형오
                                 코딩
                                              11 박다솔
                                보고서           09 장진승 11 정상혁



* 문제 파악
트리를 이용하여 상호참조 생성기를 만들고 시간/공간복잡도를 구한다.
- 트리의 정의 밑 사용법에 대한 이해
- 만든 프로그램에서의 시간/공간복잡도에 대한 이해
* 일정

                       일           월            화           수           목       금        토
                                              8일     9일                 10일    11일      12일
                                            트리의 정의 및 종류에
                                                                       구조체     11~13트리 완성하기
                                               대해 조사하기/
                                                                       모양 통일     /보고서 구상
                                             트리 소스 찾아보기
                      13일         14일         15일   17일                 18일


                               정렬,탐색,
                                                          보고서
                               출력 부분                                   최종발표
                                                           완성
                                완성하기


  *참고자료 : C로쓴 자료구조론(교보문고)
  http://blog.naver.com/hkn10004?Redirect=Log&logNo=20109208779
  http://blog.naver.com/rlakk11?Redirect=Log&logNo=60159303809
  http://lazypaul.tistory.com/222
*트리
           비선형, 계층적 자료구조이다
           1개 이상의 유한한 개수의 노드의 집합
           루트 노드와 0개 이상의 겹치지 않는 하위 나무 구조들의 집합으로 이
           루어짐
           Node와 Link로 구성
           예)



  트리란?




           Node(=vertex
                          정보를 나타냄
           )
           Link(=edge)    노드의 연결관계를 나타냄
           Root Node      부모가 없는 최상위 노드
           Leaf Node      자식이 없는 최하위 노드(단말노드라고도 부름)
           P-Node         부모 노드(어느 특정 노드의 상위에 있는 노드)
           C-Node         자식 노드(어느 특정 노드의 하위에 있는 노드)
 트리의 용어    Path           링크에 의해 연결된 노드들의 집합
           Sub tree       트리의 부분 집합(큰 tree에 속한 작은 tree)
                          root node부터 Leaf node까지의 중첩되지 않은 path의
           Level
                          node 개수
           Degree         하위 sub tree의 개수
           Node의 차
                      트리에 있는 노드의 최대 차수
           수
           이원 탐색트리 AVL트리,레드-블랙 트리, 스플레이 트리
 트리의 종류    다원 탐색트리 m-원 탐색 트리,B-트리,B⁺트리
           이진트리,N-ary트리
 이진 트리란?   자식 노드의 수가 최대 2개인 트리
 이진 트리의    레벨이 i일 때 최대 노드의 수는 2i-1(i⁺≥1)이다.
   성질      깊이가 k일 때 최대 노드 수는 2k(k≥1)이다.
                        한쪽으로 기울어진 트리[리스트와 비슷하나 메모리를
           편향 트리
                        더 많이 잡아먹는다, 시간복잡도가 O(n)이다]
 이진 트리의    완전 이진트 마지막 레벨을 제외한 자식노드가 순차적으로 꽉 차
   모양      리               있는 트리
           포화      이진트
                           마지막 레벨까지 완전한 모양을 유지하는 트리
           리
왼쪽자식-> 뿌리-> 오른쪽 자식(일반적으로 사용 되는
           중위 순회
                    식과 같은 방법으로 출력된다) ex) A/B*C*D
                    뿌리->왼쪽 자식->오른쪽 자식 순(전위 표기법으로 출
           전위 순회
이진트리의 순회            력이 된다) ex) +**/ABCD
                    왼쪽자식->오른쪽 자식-> 뿌리(후위 표기법으로 출력이
           후위 순회
                   된다) ex) AB/C*D*
           레벨순서순회 노드의 순서대로 방문 ex) **D/CAB
           AVL트리는 Adelson-Velskii와 Landis에 의해 1962년에 제안된 트
           리로서 각 노드에서 왼쪽 서브 트리의 높이와 오른쪽 서브 트리의 높
           이 차이가 1이하인 이진 탐색 트리를 말한다. AVL 트리는 트리가 비
 AVL 트리    균형 상태로 되면 스스로 노드들을 재배치하여 균형 상태로 만든다.
           시간 복잡도가 O(log₂n)이 된다.
           균형인수란 (왼쪽서브트리의 높이 - 오른쪽 서브트리의 높이)로 정의
           된다. 모든 노드의 균형인수가 ±1 이하이면 AVL 트리이다.
           새로 삽입된 노드를 N,가장 가까우면서 균형인수가 ±2가 된 조상 노
           드를 A라고 할 때
           (1)LL타입 : N이 A의 왼쪽 서브트리의 왼쪽에 삽입되는 경우(A노드
           의 왼쪽노드의 왼쪽에 삽입)
           (2) LR타입 : N이 A의 왼쪽 서브트리의 오른쪽에 삽입되는 경우 (A
AVL 트리에서
           노드의 왼쪽노드의 오른쪽에 삽입)
 회전 방법
           (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 불균형을 바로 잡는 변환
           모든 노드는 빨간색 아니면 검은색이다.
           루트 노드는 검은색이다.
레드-블랙트리    잎 노드는 검은색이다.
   의       빨간 노드의 자식들은 모두 검은색이다. 하지만 검은색 노드의 자식이
  성질       빨간색일 필요는 없다.
           루트 노드와 모든 잎 노드 사이에 있는 검은색 노드의 수는 모두 동
           일
                모든 리프 노드는 같은 깊이를 갖는다
           성질
                키가 n개 있으면, 이 노드의 자식은 n+1개이다
                기본적으로 이진검색트리에서의 검색과 같다
  B-트리
                이진검색트리에서는 검색 키가 노드의 키와 일치하는 것이
           검색
                있는지 확인하는 반면, B-트리에서는 노드의 여러 키 중 검
                색 키와 일치하는 것이 있는지 확인한다
*일정별 토의 내용
 날짜                                      내용
         *이번 프로젝트의 조장을 정함
         *이번 프로젝트를 할 때 전체적인 일정을 정함
          - 일요일에 한번 만나기로 하고 화요일 날 아침 10시에 만나기로 함
  5/8
            따로 토의할 내용이 있을 경우에는 네이트온을 통해서 만나기로 결정
         *트리의 정의 및 종류, 소스들을 찾아보고 다음 토의 때 각자 찾아온 자료
         들을 정리 및 공유하기로 함
         *각자 조사한 내용을 바탕으로 알고리즘에 대한 토의를 나눔
          - 09김형오가 데이터를 입력 받았을 때 먼저 정렬을 하고 난 후에 트리
            속으로 집어넣는 방법을 이야기 함
          - 정렬, 트리 생성, 탐색 부분으로 나눠서 역할을 분담하려고 하였으나
            트리 생성이 시급한 것으로 판단, 트리 생성을 일요일까지 완료하기로
 5/10       결정하였음
         *구조체의 형태는 밑의 형태로 정함
           LINK               DATA(단어)    DATA(LINE)   LINK
         *프로젝트를 함에 있어서 역할을 결정
          - 소스 : 09김형오,09오승원,11박다솔,11정상혁
          - 보고서 : 09장진승
         *이진 탐색 트리를 사용하여 상호 참조 생성기를 만드는 것을 구상
 5/13

         *상호 참조 생성기를 이진 탐색 트리를 사용하여 만들었으나 교수님의 요
         구사항인 AVL트리를 사용하지 않고 만든 트리이므로 AVL트리를 사용하
 5/15
         여서 다시 만들기로 결정함.


         *프로젝트 마무리를 하기 위해서 마지막으로 만나서 보고서구상 및 트리
 5/16
         에 대한 내용을 정리하면서 토론을 하였습니다.




*소스
*파일 입출력 부분
 파일     #include <stdio.h>
 입출력    #include <string.h>
#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++)
{
                                             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;
}
*초안(이진 탐색 트리로 작성)
       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     %sn",p->key.word,
                                                p->key.count, p->key.L1);
                      display(p->right);
              }
       }
*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
 AVL트리
                                   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);
}
       else *root = n;
}
void display(TreeNode *p)
{
       if(p != NULL)
       {
                  display(p->left);
                  printf("%10s        %d    %sn",p->key.word,
                                           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);
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);
}
TreeNode* rotate_LR(TreeNode *parent)
       {
              TreeNode *child = parent->left;
              parent->left = rotate_RR(child);
              return rotate_LL(parent);
       }




프로그램
실행 시
이번 프로젝트의 목적은 자료구조의 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으로 표시한다.
플로이드 알고리즘
-최단 거리를 구하는 알고리즘으로서, 모든 정점을 출발해서 출발한 정점을 제외한 모든
정점을 도착점으로 하는 최단거리를 구하는 알고리즘 방식이다.
위의 그래프에서 1번 정점에서 3번 정점으로 이동을 할 때 최단 경로를 찾아낸다고 하면 그 방법에 있어서
1번 정점에서 3번 정점으로 직접 연결하면 최단 거리가 6이 되지만, 1번 정점에서 2번 정점을 거치고 3번 정
점을 연결하면, 최단거리가 5가 되는 것을 알 수 있다.


위와 같은 원리로 각 정점 사이의 최단 거리를 테이블로 표현한 후, 다른 테이블에는 각 정점의 어떠한 경로
로 왔는지에 관한 테이블을 생성합니다. 뒤의 테이블을 이용하여 각 정점의 최단 경로가 어떠한 경로로 형성
이 되었는지에 관하여 추적 할 수 있습니다.




         예제 그래프.


 정                               정
     1   2    3    4   5    6        1   2     3   4    5   6
 점                               점
 1   0   9    3   18   20   23   1   0   3     1   3    1   5
 2   ∞   0    ∞   ∞    ∞    30   2   ∞   0     ∞   ∞    ∞   2
 3   ∞   6    0   15   21   24   3   ∞   3     0   3    4   5
 4   ∞   25   ∞   0     6   9    4   ∞   4     ∞   0    4   5
 5   ∞   ∞    ∞   ∞     0   3    5   ∞   ∞     ∞   ∞    0   5
 6   ∞   ∞    ∞   ∞    ∞    0    6   ∞   ∞     ∞   ∞    ∞   0

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




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




        http://air.changwon.ac.kr/wp-content/uploads/2012/01/2012-DS-p
회의      roject-05.pdf
        위의 내용을 통해서 이번 과제의 문제에 대해 회의를 하였으며,
내용.     수업시간의 교수님의 추가적인 내용을 토대로 이번 과제를 해결하기
        앞서, 각자 맡을 업무를 분담하였습니다.




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




 일정    5.31(목요일)




        저번 회의 때 각자 맡은 업무를 확인하고, 자료조사팀과 조장이 구한
        자료 및 서적의 내용을 통해 그래프에 대해서 서로 토의를 하고,
        부족한 부분을 조사팀이 질의응답을 해주는 식으로 토의 하였습니다.
 회의     그리고 프로그래밍을 한 조원이 구한 알고리즘을 토대로 이것을 서로
        토의 하고 이해하는 식으로 이번 회의를 마쳤습니다.
내용.




 회의     이번 회의 결과, 플로이드 알고리즘을 토대로 프로그램을
 결과
  및     완성 시키는 것으로 결정하였고. 다음 주 월요일까지
코딩을 완성 시켜서, 부족한 부분에 대해서 토의를 하고
토의   완성된 프로그램을 토대로 회의를 하기로 결정
     하였습니다.




일정   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;
         }
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;
                 }
}
    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;
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("가중치 : %dn",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);
         }
}

위의 프로그래밍한 조원이 완성시키고, 구현을 한 조원의 설명을
통해서, 이번 과제에서의 기본적인 알고리즘에 대해서 배우게
되었습니다.
(1) 다익스트라 알고리즘이란?
- 그리디 알고리즘은 전후 상황을 파악하지 않고, 현재 시점에서 가장 최적의 상황을 찾아 경로를 파악해 나
가는 것이다. 즉 최적 해를 구하는 데에 사용되는 근사적인 방법으로, 여러 경우 중 하나를 결정해야 할 때마
다 그 순간에 최적이라고 생각되는 것을 선택해 나가는 방식으로 진행하여 최종적인 해답에 도달하게 된다.
- 그리디 알고리즘을 기본적 원리로 두어 최단경로를 구해내는 방법이 다익스트라 알고리즘이다. 여기서 다익
스트라는 만든 사람의 이름을 딴 것이다.


(2) 다익스트라 알고리즘의 원리
- 다익스트라 알고리즘을 구체적으로 적용하기 전에 해결과정을 정리해 보면 다음과 같다.
① 가중치인접행렬에서는 직접 연결된 것이 없으면 무한대, 연결된 간선은 가중치를 표현한다.
② 두개의 집합 S와 C를 만들어 S에는 출발점을 초기값으로, C는 출발점을 제외한 모든 정점을 초기값으로
한다.
③ S에서 정해진 초기값으로부터 C의 각 정점에 대한 최단 경로 dist[i]를 구한다.
④ dist[i]의 기록 중에서 최단 경로를 택하여 해당 정점 v를 C에서 제거 후 S에 넣는다.
⑤ S의 초기 정점과 C에 직접 이르는 거리와 S안의 모든 정점을 거친 후 C에 이르는 거리중 최단 경로를
dist[w]로 한다.
⑥ ➃-➄의 과정을 C가 공집합이 될 때까지 반복한다.
이번 프로젝트의 목적은 사전에서 단어를 검색하여 틀린 글자가 나올시 표시후, 적절한 단어를 추천하는
프로그램을 제작하여, heap과 deap, hash에 대해 학습하는 것이 이번 과제의 목표입니다.




Heap이란?
완전이진 트리의 방식중 하나로서 각각의 노드는 유일한 키 값을 가진다.heap은 여러개의 노드 중 가장 큰
키 값(Max Heap)을 가지는 노드나 가장 작은 키 (Min Heap)값을 가지는 노드를 가장 빠른 시간 내에 찾아내
도록 만들어진 자료 구조 방식이다. 이것 말고도,min-max heap방식이 있는데 이것은 각 층당 1레벨에서는
min 다름 레벨에선 max,min max를 반복하여 생성한 것입니다.




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




Deap이란?
Deap은 Min-Max heap의 변환된 형태로서, 맨처음 루트에는 빈 루트를 만들어주고, 왼편에는 min heap,오른
편에는 max heap방식으로 넣어준다.
Hash란?
가지는 테이블 항목을 검색하기 위해 특정한 변환 함수를 이용하여 키 값을 항목의 주소로 직접 바꾸어 검색
하는 방법을 Hash라고 한다. 이때 변환하는 함수를 hash 함수라고 한다.
hash를 이용하면 hash함수에서 받은 키 값을 해당 주소로 바로 변환해 주므로 매우 빠른 검색이 가능하다.
<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)을 가지는 노드
자료구조 프로젝트
자료구조 프로젝트
자료구조 프로젝트
자료구조 프로젝트
자료구조 프로젝트
자료구조 프로젝트
자료구조 프로젝트

More Related Content

What's hot

Chap04 les-algorithme-de-tri-et-de-recherche
Chap04 les-algorithme-de-tri-et-de-rechercheChap04 les-algorithme-de-tri-et-de-recherche
Chap04 les-algorithme-de-tri-et-de-rechercheRiadh Harizi
 
Les listes simplement chaînées en langage C
Les listes simplement chaînées en langage CLes listes simplement chaînées en langage C
Les listes simplement chaînées en langage CMohamed Lahby
 
Sélection de contrôles avec correction
Sélection de contrôles avec correctionSélection de contrôles avec correction
Sélection de contrôles avec correctionJaouad Dabounou
 
Chap III : Cours de Modélisation & Simulation des systèmes
Chap III : Cours de Modélisation & Simulation des systèmesChap III : Cours de Modélisation & Simulation des systèmes
Chap III : Cours de Modélisation & Simulation des systèmesMohammed TAMALI
 
Constructions Et Batiments
Constructions Et BatimentsConstructions Et Batiments
Constructions Et BatimentsOURAHOU Mohamed
 
Types de plancher en construction
Types de plancher en constructionTypes de plancher en construction
Types de plancher en constructionAbdoulaye SECK
 
Cours sur les ponts en génie civil : télécharger : http://bit.ly/2RkxKJ4
Cours sur les ponts en génie civil : télécharger : http://bit.ly/2RkxKJ4Cours sur les ponts en génie civil : télécharger : http://bit.ly/2RkxKJ4
Cours sur les ponts en génie civil : télécharger : http://bit.ly/2RkxKJ4Hani sami joga
 
Multiple Choice Questions on JAVA (object oriented programming) bank 8 -- int...
Multiple Choice Questions on JAVA (object oriented programming) bank 8 -- int...Multiple Choice Questions on JAVA (object oriented programming) bank 8 -- int...
Multiple Choice Questions on JAVA (object oriented programming) bank 8 -- int...Kuntal Bhowmick
 

What's hot (11)

Chapitre05 : Les tableaux
Chapitre05 : Les tableauxChapitre05 : Les tableaux
Chapitre05 : Les tableaux
 
Chap04 les-algorithme-de-tri-et-de-recherche
Chap04 les-algorithme-de-tri-et-de-rechercheChap04 les-algorithme-de-tri-et-de-recherche
Chap04 les-algorithme-de-tri-et-de-recherche
 
Slide matlab
Slide matlab Slide matlab
Slide matlab
 
Les listes simplement chaînées en langage C
Les listes simplement chaînées en langage CLes listes simplement chaînées en langage C
Les listes simplement chaînées en langage C
 
Sélection de contrôles avec correction
Sélection de contrôles avec correctionSélection de contrôles avec correction
Sélection de contrôles avec correction
 
Chap III : Cours de Modélisation & Simulation des systèmes
Chap III : Cours de Modélisation & Simulation des systèmesChap III : Cours de Modélisation & Simulation des systèmes
Chap III : Cours de Modélisation & Simulation des systèmes
 
Constructions Et Batiments
Constructions Et BatimentsConstructions Et Batiments
Constructions Et Batiments
 
Types de plancher en construction
Types de plancher en constructionTypes de plancher en construction
Types de plancher en construction
 
Cours sur les ponts en génie civil : télécharger : http://bit.ly/2RkxKJ4
Cours sur les ponts en génie civil : télécharger : http://bit.ly/2RkxKJ4Cours sur les ponts en génie civil : télécharger : http://bit.ly/2RkxKJ4
Cours sur les ponts en génie civil : télécharger : http://bit.ly/2RkxKJ4
 
Multiple Choice Questions on JAVA (object oriented programming) bank 8 -- int...
Multiple Choice Questions on JAVA (object oriented programming) bank 8 -- int...Multiple Choice Questions on JAVA (object oriented programming) bank 8 -- int...
Multiple Choice Questions on JAVA (object oriented programming) bank 8 -- int...
 
04 cours matrices_suites
04 cours matrices_suites04 cours matrices_suites
04 cours matrices_suites
 

Viewers also liked

Project#3다항식의연산 Hwp
Project#3다항식의연산 HwpProject#3다항식의연산 Hwp
Project#3다항식의연산 HwpKimjeongmoo
 
나는 어떻게 알고리즘을 공부했을까? + 신기한 방법으로 문제 풀어보기
나는 어떻게 알고리즘을 공부했을까? + 신기한 방법으로 문제 풀어보기나는 어떻게 알고리즘을 공부했을까? + 신기한 방법으로 문제 풀어보기
나는 어떻게 알고리즘을 공부했을까? + 신기한 방법으로 문제 풀어보기Baekjoon Choi
 
Everything You Need to Know About Google +1
Everything You Need to Know About Google +1Everything You Need to Know About Google +1
Everything You Need to Know About Google +1dealerskins
 
25 Ways to improve website ranking
25 Ways to improve website ranking25 Ways to improve website ranking
25 Ways to improve website rankingIvan Correces
 
Jamie Anderson - From ”CRM” to the Customer Managed Relationship
Jamie Anderson - From ”CRM” to theCustomer Managed RelationshipJamie Anderson - From ”CRM” to theCustomer Managed Relationship
Jamie Anderson - From ”CRM” to the Customer Managed RelationshipBert Evens
 
The Ultimate Guide To ACA Compliance
The Ultimate Guide To ACA ComplianceThe Ultimate Guide To ACA Compliance
The Ultimate Guide To ACA ComplianceBambooHR
 
How To Develop Your Blog & Content Plan - Milkit Blogging Webinar by Doyle Bu...
How To Develop Your Blog & Content Plan - Milkit Blogging Webinar by Doyle Bu...How To Develop Your Blog & Content Plan - Milkit Blogging Webinar by Doyle Bu...
How To Develop Your Blog & Content Plan - Milkit Blogging Webinar by Doyle Bu...Doyle Buehler
 
How to deal with a tenant who is(finished)
How to deal with a tenant who is(finished)How to deal with a tenant who is(finished)
How to deal with a tenant who is(finished)RandyBett
 
HAR Engage Digital Pre-Listing Packet
HAR Engage Digital Pre-Listing PacketHAR Engage Digital Pre-Listing Packet
HAR Engage Digital Pre-Listing PacketByron Underwood
 
Impacto de las tic
Impacto de las  tic Impacto de las  tic
Impacto de las tic mnavarro2010
 
User Experience Distilled
User Experience DistilledUser Experience Distilled
User Experience DistilledHindu Dharma
 
Toast tapa of sardines in olive oil and tomatoes
Toast tapa of sardines in olive oil and tomatoesToast tapa of sardines in olive oil and tomatoes
Toast tapa of sardines in olive oil and tomatoesOlmeda Orígenes
 
90 10 principle - اصل 90/10
90 10 principle -  اصل 90/1090 10 principle -  اصل 90/10
90 10 principle - اصل 90/10Jack Jim
 
Grafico diario del dax perfomance index para el 12 06-2012
Grafico diario del dax perfomance index para el 12 06-2012Grafico diario del dax perfomance index para el 12 06-2012
Grafico diario del dax perfomance index para el 12 06-2012Experiencia Trading
 
Savings e Investimenti Pubblicitari: Intro - 4 marzo 2010 - Furlanetto
Savings e Investimenti Pubblicitari: Intro - 4 marzo 2010  - FurlanettoSavings e Investimenti Pubblicitari: Intro - 4 marzo 2010  - Furlanetto
Savings e Investimenti Pubblicitari: Intro - 4 marzo 2010 - FurlanettoPaola Furlanetto
 
Cibeles Madrid Fashion Week: Otoño - Invierno 2009/ 2010
Cibeles Madrid Fashion Week: Otoño - Invierno 2009/ 2010Cibeles Madrid Fashion Week: Otoño - Invierno 2009/ 2010
Cibeles Madrid Fashion Week: Otoño - Invierno 2009/ 2010Compulsiva Accesorios
 
Daily Newsletter: 11th March, 2011
Daily Newsletter: 11th March, 2011Daily Newsletter: 11th March, 2011
Daily Newsletter: 11th March, 2011Fullerton Securities
 

Viewers also liked (20)

Project#3다항식의연산 Hwp
Project#3다항식의연산 HwpProject#3다항식의연산 Hwp
Project#3다항식의연산 Hwp
 
나는 어떻게 알고리즘을 공부했을까? + 신기한 방법으로 문제 풀어보기
나는 어떻게 알고리즘을 공부했을까? + 신기한 방법으로 문제 풀어보기나는 어떻게 알고리즘을 공부했을까? + 신기한 방법으로 문제 풀어보기
나는 어떻게 알고리즘을 공부했을까? + 신기한 방법으로 문제 풀어보기
 
Everything You Need to Know About Google +1
Everything You Need to Know About Google +1Everything You Need to Know About Google +1
Everything You Need to Know About Google +1
 
25 Ways to improve website ranking
25 Ways to improve website ranking25 Ways to improve website ranking
25 Ways to improve website ranking
 
Jamie Anderson - From ”CRM” to the Customer Managed Relationship
Jamie Anderson - From ”CRM” to theCustomer Managed RelationshipJamie Anderson - From ”CRM” to theCustomer Managed Relationship
Jamie Anderson - From ”CRM” to the Customer Managed Relationship
 
The Ultimate Guide To ACA Compliance
The Ultimate Guide To ACA ComplianceThe Ultimate Guide To ACA Compliance
The Ultimate Guide To ACA Compliance
 
How To Develop Your Blog & Content Plan - Milkit Blogging Webinar by Doyle Bu...
How To Develop Your Blog & Content Plan - Milkit Blogging Webinar by Doyle Bu...How To Develop Your Blog & Content Plan - Milkit Blogging Webinar by Doyle Bu...
How To Develop Your Blog & Content Plan - Milkit Blogging Webinar by Doyle Bu...
 
Revista digital
Revista digitalRevista digital
Revista digital
 
Estrategias de lectura
Estrategias de lecturaEstrategias de lectura
Estrategias de lectura
 
How to deal with a tenant who is(finished)
How to deal with a tenant who is(finished)How to deal with a tenant who is(finished)
How to deal with a tenant who is(finished)
 
HAR Engage Digital Pre-Listing Packet
HAR Engage Digital Pre-Listing PacketHAR Engage Digital Pre-Listing Packet
HAR Engage Digital Pre-Listing Packet
 
Impacto de las tic
Impacto de las  tic Impacto de las  tic
Impacto de las tic
 
User Experience Distilled
User Experience DistilledUser Experience Distilled
User Experience Distilled
 
Toast tapa of sardines in olive oil and tomatoes
Toast tapa of sardines in olive oil and tomatoesToast tapa of sardines in olive oil and tomatoes
Toast tapa of sardines in olive oil and tomatoes
 
90 10 principle - اصل 90/10
90 10 principle -  اصل 90/1090 10 principle -  اصل 90/10
90 10 principle - اصل 90/10
 
Grafico diario del dax perfomance index para el 12 06-2012
Grafico diario del dax perfomance index para el 12 06-2012Grafico diario del dax perfomance index para el 12 06-2012
Grafico diario del dax perfomance index para el 12 06-2012
 
Savings e Investimenti Pubblicitari: Intro - 4 marzo 2010 - Furlanetto
Savings e Investimenti Pubblicitari: Intro - 4 marzo 2010  - FurlanettoSavings e Investimenti Pubblicitari: Intro - 4 marzo 2010  - Furlanetto
Savings e Investimenti Pubblicitari: Intro - 4 marzo 2010 - Furlanetto
 
Indonesia Social Media Strategist Club
Indonesia Social Media Strategist ClubIndonesia Social Media Strategist Club
Indonesia Social Media Strategist Club
 
Cibeles Madrid Fashion Week: Otoño - Invierno 2009/ 2010
Cibeles Madrid Fashion Week: Otoño - Invierno 2009/ 2010Cibeles Madrid Fashion Week: Otoño - Invierno 2009/ 2010
Cibeles Madrid Fashion Week: Otoño - Invierno 2009/ 2010
 
Daily Newsletter: 11th March, 2011
Daily Newsletter: 11th March, 2011Daily Newsletter: 11th March, 2011
Daily Newsletter: 11th March, 2011
 

Similar to 자료구조 프로젝트

2012 Ds B1 01
2012 Ds B1 012012 Ds B1 01
2012 Ds B1 01seonhyung
 
2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdfjinwookhong
 
2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdfkd19h
 
2012 Ds D0 01 Pdf
2012 Ds D0 01 Pdf2012 Ds D0 01 Pdf
2012 Ds D0 01 Pdfkd19h
 
2012 Ds D0 01
2012 Ds D0 012012 Ds D0 01
2012 Ds D0 01chl132435
 
자료구조5보고서
자료구조5보고서자료구조5보고서
자료구조5보고서KimChangHoen
 
Project#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 HwpProject#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 HwpKimjeongmoo
 
자료구조 01 최종 보고서
자료구조 01 최종 보고서자료구조 01 최종 보고서
자료구조 01 최종 보고서pkok15
 
Project#1파스칼 삼각형
Project#1파스칼 삼각형Project#1파스칼 삼각형
Project#1파스칼 삼각형Kimjeongmoo
 
1.자료구조와 알고리즘(강의자료)
1.자료구조와 알고리즘(강의자료)1.자료구조와 알고리즘(강의자료)
1.자료구조와 알고리즘(강의자료)fmbvbfhs
 
Computational Complexity
Computational ComplexityComputational Complexity
Computational Complexityskku_npc
 
2012 Ds A1 05
2012 Ds A1 052012 Ds A1 05
2012 Ds A1 05seonhyung
 

Similar to 자료구조 프로젝트 (20)

2012 Ds B1 01
2012 Ds B1 012012 Ds B1 01
2012 Ds B1 01
 
2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf
 
이산치2번
이산치2번이산치2번
이산치2번
 
2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf2012 Dm A0 02 Pdf
2012 Dm A0 02 Pdf
 
2012 Ds D0 01 Pdf
2012 Ds D0 01 Pdf2012 Ds D0 01 Pdf
2012 Ds D0 01 Pdf
 
2012 Ds D0 01
2012 Ds D0 012012 Ds D0 01
2012 Ds D0 01
 
2012 Ds 01
2012 Ds 012012 Ds 01
2012 Ds 01
 
자료구조5보고서
자료구조5보고서자료구조5보고서
자료구조5보고서
 
Project#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 HwpProject#5 최단거리 찾기 D0 Hwp
Project#5 최단거리 찾기 D0 Hwp
 
자료구조01
자료구조01자료구조01
자료구조01
 
자료구조01
자료구조01자료구조01
자료구조01
 
자료구조01
자료구조01자료구조01
자료구조01
 
자료구조 01 최종 보고서
자료구조 01 최종 보고서자료구조 01 최종 보고서
자료구조 01 최종 보고서
 
Project#1파스칼 삼각형
Project#1파스칼 삼각형Project#1파스칼 삼각형
Project#1파스칼 삼각형
 
자료구조02
자료구조02자료구조02
자료구조02
 
1.자료구조와 알고리즘(강의자료)
1.자료구조와 알고리즘(강의자료)1.자료구조와 알고리즘(강의자료)
1.자료구조와 알고리즘(강의자료)
 
2012 Dm 07
2012 Dm 072012 Dm 07
2012 Dm 07
 
Computational Complexity
Computational ComplexityComputational Complexity
Computational Complexity
 
2012 Ds A1 05
2012 Ds A1 052012 Ds A1 05
2012 Ds A1 05
 
자구2번
자구2번자구2번
자구2번
 

자료구조 프로젝트

  • 1. 프로젝트 보고서 프로젝트#1 파스칼의 삼각형 소속 : 컴퓨터 공학과 조 명 : A1 조원 : 김형오, 오승원, 정상혁, 강수현
  • 2. ◎프로젝트 목적 ⇒ 배열의 사용법을 안다. ⇒ 프로그램의 시간, 공간 복잡도 계산 할 수 있다. ◎조원별 업무파악 조장 김형오 : 공간복잡도에 대한 조사 , 출력부분에 대해서 조사 오승원 : 전체적인 코딩, 회의를 통해 의견 수렴 후 소스 수정 정상혁 : 시간복잡도에 대한 조사 , n과 m을 입력 받는 부분에 대해서 조사 강수현 : 보고서 구성 & 작성 , 배열과 파스칼의 삼각형에 대한 내용 조사 ◎반성 무작정 소스를 구현을 한다는 목적만을 가지고 프로젝트를 진행을 하는 것보다는 주어진 문제에 대해서 많 은 정보를 수집을 하고 수집된 자료와 참고 서적을 가지고와서 논의를 하다가 모르는 부분이 있으면 바로바로 확인을 하고 해결을 하여 프로젝트에 대한 회의가 원활히 진행이 될 수 있도록 해야 한다. 회의를 하면서 수 정했던 내용, 어떤 부분에 대해 논의 했는지 모든 내용들을 메모해서 보고서에 포함시켜야 할 것이다. ◎배열 -둘 이상의 변수를 모아놓은 것. 동일한 자료형의 변수를 여러 개 선언하여 사용하는 것. -여러 개의 변수가 모여서 배열을 이루기 때문에 여러 개의 값을 저장할 수 있다. -(예) int array[4]; ⇒ int형 변수 4개로 이뤄진 배열을 선언하되, 그 배열의 이름을 array로 한다!! ⇒ int : 배열을 이루는 요소(변수)의 자료형 ⇒ [4] : 배열의 길이 int int int int ⇒ 배열 array(길이가 4인 int형 1차원 배열) -arr[idx]=20; ⇒ 배열 arr의 idx+1번째 요소에 20을 저장해라!! -(예) arr[0]=10; ⇒ 배열 arr의 첫 번째 요소에 10을 저장해라!! -[ 인덱스 값 ] ⇒배열의 위치 정보를 명시하는 인덱스 값은 1이 아닌 0에서부터 시작.
  • 3. - 배열을 선언과 동시에 초기화하는 방법 ⇒ (예1) int arr1[5]={1, 2, 3, 4, 5} 순차적으로 1,2,3,4,5로 초기화 함. 1 2 3 4 5 ⇒ (예2) int arr2[ ]={1,2,3,4,5,6,7}; 컴파일러에 의해서 자동으로 7이 삽입됨. 초기화리스트가 선언되면 배열의 길이정보를 생략할 수 있다. 컴파일러가 초기 화 리스트의 수를 참조하여 길이정보를 채워주기 때문이다. 1 2 3 4 5 6 7 ⇒(예3) int arr3[5]={1,2}; 3,4,5번째 배열요소는 0으로 채워짐. 1 2 0 0 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)
  • 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 ) = %dn", n, m, arr[n-1][m]); // p(n,m) 값 확인 }
  • 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)
  • 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)=%dn", 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++)
  • 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 ) = %.0fn",n,m,arr[n-1][m-1]);// p(n,m) 의 값을 출력
  • 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)를 찾는 것
  • 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 참고
  • 10. A2조 자료구조 프로젝트 보고서 [Project #2 : 말(馬)의 여행] 조장 : 김형오 조원 : 민영지 박다솔 박우용
  • 11. 과제수행일지 소속 조장 : 김형오 조원 : 민영지 박다솔 박우용 자료조사 : 프로그래밍 : 보고서 작성 : A2 김형오, 박우용 김형오, 박우용 박다솔 민영지, 박다솔 과제수행기간 12일 8시간 I. 계획의 작성 연구제목 말(馬)의 여행 말의 여행을 통해서 스택, 큐, 백트래킹의 원리를 알고 말이 움직인 행적(지나간 자리) 연구배경 을 표시하여 장기판을 다 돌게 하는 프로그램의 알고리즘을 작성, 프로그램 소스 코딩 을 해 보면서 스택, 큐, 백트래킹에 대해 적용을 할 수 있다. 윤성우의 열혈 자료구조(C언어를 이용한 자료구조 학습서) / 윤성우 지음 참고 서적 / 오렌지 미디어 열혈강의 자료구조 / 이상진 지음 / 프리렉 C언어로 쉽게 풀어쓴 자료구조 / 천인국, 공용해 지음 / 생능 참고자료 http://www.winapi.co.kr/ 참고 URL http://lwove.egloos.com/ http://internet512.chonbuk.ac.kr/datastructure/stack/stackq.htm#/ II. 계획의 실행 첫째 날 2012년 3월 27일 화요일 오늘의 작업 조원의 업무 분담과 학습할 내용 및 과제에 대한 이해와 숙지 조장 : 김형오 자료조사 : 민영지, 박다솔 프로그래밍 : 김형오, 박우용 토의 내용 위와 같이 조원의 업무를 분담했다. 프로그래밍과 자료조사를 조원들끼리 나누어서 하 는 게 효율성은 좋지만, 이 프로젝트를 하기 위해서는 스택, 큐, 백트래킹에 대해 개념 을 다 알고 이해해야 했기 때문에 효율성보다는 효과성을 택했다. 그래서 이 프로젝트
  • 12. 에 대한 소스도 각자 생각해오고 하기로 하였다. 새로운 프로젝트가 제시가 되고 새로운 조를 편성을 함에 따라 새로 정해야하는 것들이 과제준비에서 생겨났고 이러한 것들을 빨리 해결을 하는 것과 동시에 프로젝트의 문제를 파악하고 적 느낀 점 절하게 임무를 분담을 하였다. 둘째 날 2012년 3월 31일 토요일 오늘의 작업 각자 조사해온 내용에 대한 토의 말의 여행 프로젝트를 수행하기 위해서는 가장 먼저 이해해야 할 스택과 큐, 백드래킹 을 중심적으로 설명하고, 토의를 하였다. •Stack -정의 ; 여러 개의 데이터 항목들이 일정한 순서로 나열된 자료 구조 -먼저 삽입된 것은 나중에 삭제되고, 나중에 삽입된 것이 먼저 삭제된다. 한쪽 끝에서만 새로운 항목을 삽입하거나 기존의 항목을 삭제할 수 있도록 고안된 것 -실생활의 예 : 동전을 넣고 뺄 수 있도록 되어 있는 동전 케이스 주차장에 주차한 자동차(나보다 나중에 들어온 차들 때문에 나갈 수가 없다, 결국 나중 에 들어온 차들이 모두 나갈 때까지 기다린 후에 차를 뺄 수 있다) *Back traking -검색 공간의 모든 가능한 배치 방법에 대해 어떤 작업을 반복하기 위한 조직적인 방법 토의 내용 -백트래킹은 용도에 맞게 개별적으로 구현해서 써야 하는 범용알고리즘 기법 -함수가 실행되는 것과 비슷한 방식으로 컴퓨터 내부에서 실행이 됨 (함수안의 함수) •Queue -정의 : 리스트의 한쪽 끝에서는 원소들이 삭제되고 반대쪽 끝에서는 원소들이 삽입만 가능하게 만든 순서화된 리스트 -실생활의 예 : 은행에서 순서대로 번호표를 뽑게 하고 일을 처리해주는 예 버스정류장에서 먼저 온 순서대로 탑승하는 예 물건을 구매할 때 줄을 서서 계산대에서 계산을 기다리는 예 서로 각자가 공부를 해오고 모르는 것을 서로에게 질문하였고, 교수님께서 말씀하신 스 택과 큐, 백트래킹이 실생활에 어디에 사용되는지 생각해보라고 하셔서 조원들이 함께 생각해보고, 교수님께 추가적인 설명들을 듣고 하였다. 스택과 큐와 백트래킹에 대해서 찾아보았지만 백트래킹에 대한 내용이 스택과 큐에 비 과제준비에서 해서 많이 적었다. 그래서 도서관에 가서 자료구조에 대한 정리가 되어있는 책들을 찾 느낀 점 아보고 백트래킹에 대한 개념을 찾아내긴 했지만 아직 확실하게는 파악을 못하였고 이 로 인해서 백트래킹에 대해서는 다시 한 번 더 조사를 하기로 하였다.
  • 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
  • 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일 일요일 오늘의 작업 말의 여행 초안 소스에 대한 토의 말이 어떠한 방향으로 이동을 해야할까?에 대해서 많은 고민을 했었습니다. 그러다가 난수를 설정을 하여서 임의로 가도록 해보기도 했지만, 결국은 모든 좌표를 설계 방법 돌아다니지를 못하였습니다. 그래서 다른 방법을 고안을 하여 말이 움직이는 방향을 정 하여서 이곳으로만 이동을 하도록 하는 것보다는 갈수 있는 방향을 제시만을 해주고 범 위에서 벗어나지 않도록만 설정을 하여서 갈수 있는 방향을 찾아가도록 하였다.
  • 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; }
  • 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) {
  • 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);
  • 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]; }
  • 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);//갈수 있는 모든곳을 푸시
  • 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);
  • 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; }
  • 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++) {
  • 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;
  • 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]; } Ⅳ. 반성 과제를 마치면서 각자 조원들이 자료를 조사해오고 같이 토의하면서 모르는 것을 질문하고 가르쳐 줌으 느낀 점 로써 스스로 공부해오고 알아가는 프로젝트 과제의 장점을 느낄 수 있었다. 개개인이 조사해오는 자료마다 조금씩 달라서 조원이 다 같이 이해하고 정보를 습득 하는 데에서 는 시간이 지체되었고, 살짝 어려움이 있었다. 하지만 이 부분도 프로젝트의 단점이라고
  • 25. 생각 할 수 있겠지만 어떻게 보면 장점이라고 생각 할 수도 있었다. 프로젝트를 C언어 로 코딩을 해야 하는 점에서 아직 조원들이 많이 부족하다는 것을 느낄 수 있었고,조금 더 공부하고 더 연습해야겠다는 것을 몸소 느꼈고, 매 수업시간마다 그리고 온라인으로 만나는 시간마다 회의를 할 때 회의록을 작성하여서 보고서의 질을 좀 더 높일 수 있었 을 텐데…라는 아쉬움이 남았다.
  • 26. B0 프로젝트 보고서 #3 조장 09 오승원 팀원 09 김형오 09 장진승 11 성주희 11 정상혁 역할 분담 팀원 09 오승원, 김형오, 장진승 자료조사 및 이해 11 성주희, 정상혁 09 오승원, 김형오 코딩 보고서 09 장진승 * 문제 파악 링크드 리스트를 이용하여 다항식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.htm http://blog.naver.com/pjy9954?Redirect=Log&logNo=70128298541 http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Database/DataStructure/LinkedList
  • 27. 링크드 리스트는 각 데이터를 서로 연결해서 관리하며 , 이때 각각의 데이터를 노드(node)라고 불리우는 Unit에 넣어서 관리한다. 스택이나 큐와 같은 경우 링크드 리스트란? 각 위치에 데이터자체가 저장되는 것과는 약간다르다 . 이처럼 데이터를 노드에 넣어 서 관리하는 이유는 데이터의 리스트를 유지하기 위해서 데이터외에도 다음 데이터의 위치를 나타낼수 있는 어떤 부가적인 정보가 필요하기 때문이다. 1)싱글 링크드리스트(단일 연결리스트 ) 각 노드는 저장하고자할 데이터와 다음 노드를 가리키는 포인터를 포함한다. 싱글링 크드리스트에서 각 노드는 다음노드의 위치를 가리키기 때문에, 우리는 반드시 시작 노드의 위치를 알고 있어야만 할것이다. 또한 이전노드의 위치는 알수없도록 되어 있 다. 2)이중 연결리스트 다음노드를 가리키는 하나의 포인터만 가지고 있는 싱글링크드리스트와는 달리 이전 링크드 리스트의 종류 노드를 가리키는 포인터도 가지고 있다 . 전방향 , 후방향어느 쪽으로든지 순환이 가능 한 링크드리스트이다. 3)환형 연결리스트 환형 연결 리스트에서는 노드의 시작과 끝을 구별하지 않음으로써 마지막 노드와 처 음 노드가 연결되어 있음으로 임의의 노드에서 다른 모든 노드로의 접근이 가능하여 임의 노드의 검색이 가능하게 된다 . 단순 연결 리스트의 경우 정보가 끊어지면 그 다 음은 찾을 수가 없는데 환형 연결 리스트는 그것을 극복할 수 있다. 링크드 리스트의 구조 데이터의 위치를 나타내기 위해서 사용할수 있는것은 pointer가 될것이다 . 즉 노드는 데이터와 함께 다음 데이터의 위치정보를 가지고 있는 "포인터 "를 포함하게 된다. 장점 : 구현이 간단하다 배열을 이용 단점 : 크기에 제한이 있다 , 삽입과 삭제시 오버헤드가 발생한다 리스트의 구현방법 장점 : 크기에 제한이 없다 포인터를 이용 단점 : 구현이 복잡하다 배열의 경우 연속적인 공간에 위치함으로 특정위치에 있는 데이터에 접근하고자 할때 O(1)의 시간이 소모된다 . 링크드리스트의 경우 O(N)의 시간이 소모된다. 처음노드부 터 순환을 해야하기 때문이다. 배열(스택,큐)과 비교되는 배열의 경우 처음과 마지막에 데이터를 삽입하는건 매우 쉽고 효율적이지만 중간에 링크드 리스트의 있는 데이터를 삭제하거나, 삽입하는건 상대적으로 어렵고 비효율적이다 . 링크드 리스 트는 이러한 경우 매우 효율적이다. 특징 배열의 경우 일단 만들어진 사이즈를 조정할 수 없으나 링크드리스트는 자유롭게 사 이즈를 조정할 수 있다. 장점 새로운 노드의 추가, 삽입 ,삭제가 쉽고 빠르다 링크드리스트의 다음 링크를 가리키는 포인터가 4Byte씩 잡아먹는다 단점 첫 노드부터 마지막 노드까지 순서대로 검색을 하기 때문에 , 최악의 경우 배 장단점 열보다 자료를 검색하는데 들어가는 시간이 더 걸릴 수 있다.
  • 28. *일정별 토의 내용 날짜 토의 내용 *이번 프로젝트의 조장을 정함 *이번 프로젝트를 할 때 전체적인 일정을 정함 - 토의 일정을 화,목 9시부터 수업시간 전까지로 정하고 따로 한 번 더 만 날 일이나 토의할 내용이 있으면 네이트온을 통해서 만나기 4/12(목) 로 결정 *다음 모임 전까지 각자 링크드 리스트에 대해 공부를 하고 공부를 하 면서 봤던 자료 중 정리가 잘 돼있다고 생각되는 자료를 공유하기로 결정 *목요일부터 링크드리스트에 대해 각자 조사 했던 것을 공유 *각자 다항식에 대해 구상했었던 알고리즘에 대한 토의 - 변수명을 P(x)와 S(x)는 각각 P,S라 두고 계수와 차수에 대해서는 각각 a1,n1으로 하기로 결정 - 덧셈, 뺄셈, 곱셈은 덧셈으로 모아지는 모양새를 발견함 - 나눗셈에 대한 결론은 내리지 못하였음 4/17(화) - 입력 부분에 대해서는 각자 소스를 짜보면서 각자 생각한대로 해 보기로 결정 *식 전체를 입력 받고 그 식에서 계수와 차수를 추출, 연산에 사용하 는 방식을 사용하기로 결정 *각 파트별로 역할을 결정 - 덧셈 : 11성주희, 뺄셈 : 09김형오, 곱하기 : 09오승원, 나눗셈 : 11정상혁 - 보고서 작성 : 09장진승 *사칙 연산에 대해 각자 파트를 나눠 구상/작성 하기로 하였으나 입력 부분이 해결되지 않아서 인지 어떻게 해결하고 작성해야 하는지에 대 한 구상은 일정부분 고민을 많이 해온 듯 하지만 작성까지 진행 되지 못하였음 *입력 부분에서 생각의 전환이 생김 - 09김형오가 전체를 입력 받고 계수와 차수를 추출하여 이용하는 입 력 부분 코딩 구상 - 09오승원이 계수와 차수만을 입력 받는 부분의 입력 코딩/구상 작 4/19(목) 성 - 교수님의 조언에 따라 다항식 전체를 입력받고 그 입력 받은 부분 에서 필요한 부분을 추출 해내는 방식에서 계수와 차수 이 두 가지 를 받는 쪽으로 변경함(다항식의 변수 x같은 경우는 누구나 다 아는 일반적인 사실이므로 결국 실질적으로 계산되는 계수와 차수만을 입력 받으면 되는 것이고 출력에서는 x까지 나타나는 완벽한 다항 식을 출력하면 되는 것) *입력 부분을 확실히 정하였으므로 남은 기간 입력 부분과 연계하여 각 파트에 대한 코딩을 완성시키기로 결정
  • 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; } }
  • 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)//차수비교 {
  • 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
  • 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++; }
  • 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 %dn",p->a1,p->n1); } }
  • 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);
  • 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("nn빼기n"); sub(&list3,&list4,&list6);// 정렬된 두 식의 뺄샘 print(&list6); printf("nn곱하기n"); mul(&list3,&list4,&list7);// 정렬된 두 식의 곱셈 arra(&list7,&list8); print(&list8); printf("nn나누기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); }
  • 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; } }
  • 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); } // 식을 차수를 통해 내림차순정렬 해주는 함수
  • 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;
  • 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); } }
  • 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
  • 42. B0 활동 보고서 #4 조장 11 정상혁 팀원 09 김형오 09 오승원 09 장진승 11 박다솔 역할 분담 팀원 자료조사 및 이해 09 장진승 11 박다솔 09 오승원, 김형오 코딩 11 박다솔 보고서 09 장진승 11 정상혁 * 문제 파악 트리를 이용하여 상호참조 생성기를 만들고 시간/공간복잡도를 구한다. - 트리의 정의 밑 사용법에 대한 이해 - 만든 프로그램에서의 시간/공간복잡도에 대한 이해 * 일정 일 월 화 수 목 금 토 8일 9일 10일 11일 12일 트리의 정의 및 종류에 구조체 11~13트리 완성하기 대해 조사하기/ 모양 통일 /보고서 구상 트리 소스 찾아보기 13일 14일 15일 17일 18일 정렬,탐색, 보고서 출력 부분 최종발표 완성 완성하기 *참고자료 : C로쓴 자료구조론(교보문고) http://blog.naver.com/hkn10004?Redirect=Log&logNo=20109208779 http://blog.naver.com/rlakk11?Redirect=Log&logNo=60159303809 http://lazypaul.tistory.com/222
  • 43. *트리 비선형, 계층적 자료구조이다 1개 이상의 유한한 개수의 노드의 집합 루트 노드와 0개 이상의 겹치지 않는 하위 나무 구조들의 집합으로 이 루어짐 Node와 Link로 구성 예) 트리란? Node(=vertex 정보를 나타냄 ) Link(=edge) 노드의 연결관계를 나타냄 Root Node 부모가 없는 최상위 노드 Leaf Node 자식이 없는 최하위 노드(단말노드라고도 부름) P-Node 부모 노드(어느 특정 노드의 상위에 있는 노드) C-Node 자식 노드(어느 특정 노드의 하위에 있는 노드) 트리의 용어 Path 링크에 의해 연결된 노드들의 집합 Sub tree 트리의 부분 집합(큰 tree에 속한 작은 tree) root node부터 Leaf node까지의 중첩되지 않은 path의 Level node 개수 Degree 하위 sub tree의 개수 Node의 차 트리에 있는 노드의 최대 차수 수 이원 탐색트리 AVL트리,레드-블랙 트리, 스플레이 트리 트리의 종류 다원 탐색트리 m-원 탐색 트리,B-트리,B⁺트리 이진트리,N-ary트리 이진 트리란? 자식 노드의 수가 최대 2개인 트리 이진 트리의 레벨이 i일 때 최대 노드의 수는 2i-1(i⁺≥1)이다. 성질 깊이가 k일 때 최대 노드 수는 2k(k≥1)이다. 한쪽으로 기울어진 트리[리스트와 비슷하나 메모리를 편향 트리 더 많이 잡아먹는다, 시간복잡도가 O(n)이다] 이진 트리의 완전 이진트 마지막 레벨을 제외한 자식노드가 순차적으로 꽉 차 모양 리 있는 트리 포화 이진트 마지막 레벨까지 완전한 모양을 유지하는 트리 리
  • 44. 왼쪽자식-> 뿌리-> 오른쪽 자식(일반적으로 사용 되는 중위 순회 식과 같은 방법으로 출력된다) ex) A/B*C*D 뿌리->왼쪽 자식->오른쪽 자식 순(전위 표기법으로 출 전위 순회 이진트리의 순회 력이 된다) ex) +**/ABCD 왼쪽자식->오른쪽 자식-> 뿌리(후위 표기법으로 출력이 후위 순회 된다) ex) AB/C*D* 레벨순서순회 노드의 순서대로 방문 ex) **D/CAB AVL트리는 Adelson-Velskii와 Landis에 의해 1962년에 제안된 트 리로서 각 노드에서 왼쪽 서브 트리의 높이와 오른쪽 서브 트리의 높 이 차이가 1이하인 이진 탐색 트리를 말한다. AVL 트리는 트리가 비 AVL 트리 균형 상태로 되면 스스로 노드들을 재배치하여 균형 상태로 만든다. 시간 복잡도가 O(log₂n)이 된다. 균형인수란 (왼쪽서브트리의 높이 - 오른쪽 서브트리의 높이)로 정의 된다. 모든 노드의 균형인수가 ±1 이하이면 AVL 트리이다. 새로 삽입된 노드를 N,가장 가까우면서 균형인수가 ±2가 된 조상 노 드를 A라고 할 때 (1)LL타입 : N이 A의 왼쪽 서브트리의 왼쪽에 삽입되는 경우(A노드 의 왼쪽노드의 왼쪽에 삽입) (2) LR타입 : N이 A의 왼쪽 서브트리의 오른쪽에 삽입되는 경우 (A AVL 트리에서 노드의 왼쪽노드의 오른쪽에 삽입) 회전 방법 (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 불균형을 바로 잡는 변환 모든 노드는 빨간색 아니면 검은색이다. 루트 노드는 검은색이다. 레드-블랙트리 잎 노드는 검은색이다. 의 빨간 노드의 자식들은 모두 검은색이다. 하지만 검은색 노드의 자식이 성질 빨간색일 필요는 없다. 루트 노드와 모든 잎 노드 사이에 있는 검은색 노드의 수는 모두 동 일 모든 리프 노드는 같은 깊이를 갖는다 성질 키가 n개 있으면, 이 노드의 자식은 n+1개이다 기본적으로 이진검색트리에서의 검색과 같다 B-트리 이진검색트리에서는 검색 키가 노드의 키와 일치하는 것이 검색 있는지 확인하는 반면, B-트리에서는 노드의 여러 키 중 검 색 키와 일치하는 것이 있는지 확인한다
  • 45. *일정별 토의 내용 날짜 내용 *이번 프로젝트의 조장을 정함 *이번 프로젝트를 할 때 전체적인 일정을 정함 - 일요일에 한번 만나기로 하고 화요일 날 아침 10시에 만나기로 함 5/8 따로 토의할 내용이 있을 경우에는 네이트온을 통해서 만나기로 결정 *트리의 정의 및 종류, 소스들을 찾아보고 다음 토의 때 각자 찾아온 자료 들을 정리 및 공유하기로 함 *각자 조사한 내용을 바탕으로 알고리즘에 대한 토의를 나눔 - 09김형오가 데이터를 입력 받았을 때 먼저 정렬을 하고 난 후에 트리 속으로 집어넣는 방법을 이야기 함 - 정렬, 트리 생성, 탐색 부분으로 나눠서 역할을 분담하려고 하였으나 트리 생성이 시급한 것으로 판단, 트리 생성을 일요일까지 완료하기로 5/10 결정하였음 *구조체의 형태는 밑의 형태로 정함 LINK DATA(단어) DATA(LINE) LINK *프로젝트를 함에 있어서 역할을 결정 - 소스 : 09김형오,09오승원,11박다솔,11정상혁 - 보고서 : 09장진승 *이진 탐색 트리를 사용하여 상호 참조 생성기를 만드는 것을 구상 5/13 *상호 참조 생성기를 이진 탐색 트리를 사용하여 만들었으나 교수님의 요 구사항인 AVL트리를 사용하지 않고 만든 트리이므로 AVL트리를 사용하 5/15 여서 다시 만들기로 결정함. *프로젝트 마무리를 하기 위해서 마지막으로 만나서 보고서구상 및 트리 5/16 에 대한 내용을 정리하면서 토론을 하였습니다. *소스 *파일 입출력 부분 파일 #include <stdio.h> 입출력 #include <string.h>
  • 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++)
  • 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; }
  • 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 %sn",p->key.word, p->key.count, p->key.L1); display(p->right); } }
  • 49. *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 AVL트리 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);
  • 50. } else *root = n; } void display(TreeNode *p) { if(p != NULL) { display(p->left); printf("%10s %d %sn",p->key.word, 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);
  • 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); }
  • 52. TreeNode* rotate_LR(TreeNode *parent) { TreeNode *child = parent->left; parent->left = rotate_RR(child); return rotate_LL(parent); } 프로그램 실행 시
  • 53.
  • 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으로 표시한다. 플로이드 알고리즘 -최단 거리를 구하는 알고리즘으로서, 모든 정점을 출발해서 출발한 정점을 제외한 모든 정점을 도착점으로 하는 최단거리를 구하는 알고리즘 방식이다.
  • 55. 위의 그래프에서 1번 정점에서 3번 정점으로 이동을 할 때 최단 경로를 찾아낸다고 하면 그 방법에 있어서 1번 정점에서 3번 정점으로 직접 연결하면 최단 거리가 6이 되지만, 1번 정점에서 2번 정점을 거치고 3번 정 점을 연결하면, 최단거리가 5가 되는 것을 알 수 있다. 위와 같은 원리로 각 정점 사이의 최단 거리를 테이블로 표현한 후, 다른 테이블에는 각 정점의 어떠한 경로 로 왔는지에 관한 테이블을 생성합니다. 뒤의 테이블을 이용하여 각 정점의 최단 경로가 어떠한 경로로 형성 이 되었는지에 관하여 추적 할 수 있습니다. 예제 그래프. 정 정 1 2 3 4 5 6 1 2 3 4 5 6 점 점 1 0 9 3 18 20 23 1 0 3 1 3 1 5 2 ∞ 0 ∞ ∞ ∞ 30 2 ∞ 0 ∞ ∞ ∞ 2 3 ∞ 6 0 15 21 24 3 ∞ 3 0 3 4 5 4 ∞ 25 ∞ 0 6 9 4 ∞ 4 ∞ 0 4 5 5 ∞ ∞ ∞ ∞ 0 3 5 ∞ ∞ ∞ ∞ 0 5 6 ∞ ∞ ∞ ∞ ∞ 0 6 ∞ ∞ ∞ ∞ ∞ 0 <각 정점간의 최단 거리 테이블> <경로 테이블> 위의 플로이드 알고리즘을 활용하여 이번 프로그램을 만들게 되었습니다.
  • 56. 일정 5.29(화요일) http://air.changwon.ac.kr/wp-content/uploads/2012/01/2012-DS-p 회의 roject-05.pdf 위의 내용을 통해서 이번 과제의 문제에 대해 회의를 하였으며, 내용. 수업시간의 교수님의 추가적인 내용을 토대로 이번 과제를 해결하기 앞서, 각자 맡을 업무를 분담하였습니다. 이번 회의 결과, 조장은 다음 모임 까지, 개별적으로 이번 회의 프로젝트를 위한 자료를 구하고, 자료 조사팀에서는 그래프에 결과 및 대한 기본 성질에 대해서 자료를 구하고, 프로그램을 맡은 토의 사람은 이번 프로젝트를 인접 행렬과, 인접 리스트 방식 중 인접 행렬로 기본적인 틀을 만들어 오기로 결정하였습니다. 일정 5.31(목요일) 저번 회의 때 각자 맡은 업무를 확인하고, 자료조사팀과 조장이 구한 자료 및 서적의 내용을 통해 그래프에 대해서 서로 토의를 하고, 부족한 부분을 조사팀이 질의응답을 해주는 식으로 토의 하였습니다. 회의 그리고 프로그래밍을 한 조원이 구한 알고리즘을 토대로 이것을 서로 토의 하고 이해하는 식으로 이번 회의를 마쳤습니다. 내용. 회의 이번 회의 결과, 플로이드 알고리즘을 토대로 프로그램을 결과 및 완성 시키는 것으로 결정하였고. 다음 주 월요일까지
  • 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; }
  • 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; }
  • 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;
  • 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("가중치 : %dn",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); } } 위의 프로그래밍한 조원이 완성시키고, 구현을 한 조원의 설명을 통해서, 이번 과제에서의 기본적인 알고리즘에 대해서 배우게 되었습니다.
  • 61.
  • 62. (1) 다익스트라 알고리즘이란? - 그리디 알고리즘은 전후 상황을 파악하지 않고, 현재 시점에서 가장 최적의 상황을 찾아 경로를 파악해 나 가는 것이다. 즉 최적 해를 구하는 데에 사용되는 근사적인 방법으로, 여러 경우 중 하나를 결정해야 할 때마 다 그 순간에 최적이라고 생각되는 것을 선택해 나가는 방식으로 진행하여 최종적인 해답에 도달하게 된다. - 그리디 알고리즘을 기본적 원리로 두어 최단경로를 구해내는 방법이 다익스트라 알고리즘이다. 여기서 다익 스트라는 만든 사람의 이름을 딴 것이다. (2) 다익스트라 알고리즘의 원리 - 다익스트라 알고리즘을 구체적으로 적용하기 전에 해결과정을 정리해 보면 다음과 같다. ① 가중치인접행렬에서는 직접 연결된 것이 없으면 무한대, 연결된 간선은 가중치를 표현한다. ② 두개의 집합 S와 C를 만들어 S에는 출발점을 초기값으로, C는 출발점을 제외한 모든 정점을 초기값으로 한다. ③ S에서 정해진 초기값으로부터 C의 각 정점에 대한 최단 경로 dist[i]를 구한다. ④ dist[i]의 기록 중에서 최단 경로를 택하여 해당 정점 v를 C에서 제거 후 S에 넣는다. ⑤ S의 초기 정점과 C에 직접 이르는 거리와 S안의 모든 정점을 거친 후 C에 이르는 거리중 최단 경로를 dist[w]로 한다. ⑥ ➃-➄의 과정을 C가 공집합이 될 때까지 반복한다.
  • 63.
  • 64. 이번 프로젝트의 목적은 사전에서 단어를 검색하여 틀린 글자가 나올시 표시후, 적절한 단어를 추천하는 프로그램을 제작하여, heap과 deap, hash에 대해 학습하는 것이 이번 과제의 목표입니다. Heap이란? 완전이진 트리의 방식중 하나로서 각각의 노드는 유일한 키 값을 가진다.heap은 여러개의 노드 중 가장 큰 키 값(Max Heap)을 가지는 노드나 가장 작은 키 (Min Heap)값을 가지는 노드를 가장 빠른 시간 내에 찾아내 도록 만들어진 자료 구조 방식이다. 이것 말고도,min-max heap방식이 있는데 이것은 각 층당 1레벨에서는 min 다름 레벨에선 max,min max를 반복하여 생성한 것입니다. <min-heap> <Max-heap> <Min-Max heap> Deap이란? Deap은 Min-Max heap의 변환된 형태로서, 맨처음 루트에는 빈 루트를 만들어주고, 왼편에는 min heap,오른 편에는 max heap방식으로 넣어준다. Hash란? 가지는 테이블 항목을 검색하기 위해 특정한 변환 함수를 이용하여 키 값을 항목의 주소로 직접 바꾸어 검색 하는 방법을 Hash라고 한다. 이때 변환하는 함수를 hash 함수라고 한다. hash를 이용하면 hash함수에서 받은 키 값을 해당 주소로 바로 변환해 주므로 매우 빠른 검색이 가능하다.
  • 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)을 가지는 노드