Sort.. algorithm

Algorithm 2008. 9. 9. 16:12
<5. 정렬 알고리즘(1) >

1) 개요

     * 정렬(sort) : 임의위 순서대로 배열하는 것
     *오름차순(ascending order)
     *내림차순(descending order)

     1] 정렬의 방법론
          * 파일(file) - 정렬대상, 정보의 단위인 레코드의 나열
          * 필드(field) - 각 레코드의 구체적 정보단위
          * 레코드(record)는 C에서 구조체로 표현, 필드는 구조체의 멤버!
          * 키(key) - 필드 중에서 비교의 대상인 것

     2] 정렬 알고리즘의 다양성
          * 간단 : 선택정렬, 삽입정렬, 거품정렬, 셀정렬
          * 복잡 : 퀵정렬, 기수정렬, 힙정렬, 병합정렬

          *내부정렬 (Internal sort) - 속도 빠름, 모든자료를 메인메모리로 옮겨 놓아야 하는 부담
          *외부정렬 (External sort) - 속도 느림, 자료가 메인메모리 차지안하므로 메모리 절약!

          *직접정렬 (Direct sort) - 메모리 절약 but 속도느림
          *간접정렬 (Indirect sort) - 메모리 소요, 실제 레코드 교환안하므로 속도 빠름

          * 삽입(Insertion) : ex) 삽입정렬
          * 교환(Exchange) : ex) 거품정렬, 퀵정렬, 기수교환정렬
          * 병합(Merging) :  ex) 병합정렬
          * 선택(Selection) : ex)선택정렬, 힙정렬
          * 세기(Counting) : ex) 분포수세기, 직접기수정렬

--------------------------------------------------------------------------------

2) 선택정렬 (Selection sort)

          (1) i=0;
          (2) i=n-1면 끝
          (3) i~n-1 중 최소값을 min에 저장
          (4) i항과 min항을 교환
          (5) i하나 증가 -> 2로~

     void select_sort (int a[], int n)
     {
          int min, minindex, i, j;

          for(i=0; i<n-1; i++)
          {
              minindex=i;
              min=a[i];
               for(j=i+1; j<n; j++)
               {
                    if(min>a[j])
                    {
                         min=a[j];
                         minindex=j;
                    }
               }
               a[minindex] = a[i];
               a[i] = min;
          }
     }

     # 배열 앞부분부터 차례로 정렬해 나간다.
     # 아직 정렬하지 않은 부분은 n의 변함이 없다.
     # 비교횟수 N^2/2정도, 교환횟수<=N (최악의 경우-역순일 때, 교환횟수=N)
     # 성능 O(N^2)
     # 안정성이 없다.
     # N<100에서 만족할 만한 속도~

--------------------------------------------------------------------------------

3) 삽입정렬 (Insertion sort)

     (1) i=1;
     (2) j=i;
     (3) a[j-1]>a[i], j>0인 동안
         a[j]=a[j-1]; j--;
     (4) a[j] = a[i];
     (5) i++, 2로~~ ( → i항 이하는 이미 정렬된 상태가 됨!!!)

     void insert_sort(int a[], int n)
     {
          int i, j, t;
          for(i=1; i<n; i++)
          {
               t=a[i];
               j=i;
               while(a[j-1]>t  && j>0)
               {
                    a[j]=a[j-1];
                    j--;
               }
               a[j]=t;
          }
     }

     # 삽입정렬은 입력자료에 민감
     # 이미 정렬된 배열일 경우 매우 빠름
     # 최악의 경우 : 역순!
     # 난수 배열인 경우 - 선택정렬보다 효율이 좋다
     # O(N^2)의 성능

--------------------------------------------------------------------------------

4) 거품정렬 (Bubble Sort)

     (1) i=0;
     (2) i=n-1되면 끝
     (3) j=1;
     (4) j=n-1면 7로
     (5) a[j-1]>a[j] 이면 두 값을 교환
     (6) j하나 증가 -> 4로
     (7) i증가, 2로!

     void bubble_sort(int a[], int n)
     {
          int i, j, t;
          for(i=0; i<n-1; i++)
         {
               for(j=1; j<n-1; j++)
               {
                    if(a[j-1]>a[j])
                    {
                         t=a[j-1];
                         a[j-1]=a[j];
                         a[j]=t;
                    }
               }
          }
     }

     # 최선의 경우 - 이미 정렬된 배열
     # 최악의 경우 - 역순!
    
--------------------------------------------------------------------------------

5) 쉘 정렬 ( Shell sort )
   -  h간격으로 떨어진 레코드를 삽입정렬 함

    (1)  h의 초기값을 구한다.
    (2)  h가 1보다 작으면 끝낸다
    (3) i=0;
    (4) i 가 h보다 크기가 같으면 7로 간다.
    (5) (h 간격+i)요소들에 대해서 삽입 정렬을 한다.
    (6) i를 하나 증가시키고 4로 간다.
    (7) h의 다음값을 구하고 2로 간다!

    void shell_sort (int a[], int n)
    {
        int i, j, k, h, v, j;
        for(h=0; i<h; i++)
        {
            for(j=i+h; j<n; j+=h)
            {
                v=a[j];
                k=j;

               while(k>h-1 && a[k-1]>v)
                {
                   a[k]=a[k-h];
                    k-=h;
                }
            a[k]=v;
        }
        }
    }

    # 안정성이 없다.
    # 입력자료의 형태에 상관없이 속도  good!!!
    # 최선의 경우 - 이미 정렬된것
    # 최악의 경우 - 난수 (하지만 그래도 빠른편!)
    # O(N(log N^2), O(N^1.25) 의 성능

--------------------------------------------------------------------------------

6) 분포수 세기 (Distribution counting)
        - 같은 키가 많이 있는 배열에 한해 적용할 수 있다.
        - 특정 키 값이 출현 하는 빈도를 저장하여 누적분포를 이용하여 간단하게 정렬

     (1) count[]배열을 O으로 초기화
     (2) a[] 배열의 키의 빈도를 계산하여 그 빈도를 count[]에 저장
     (3) count[]배열을 누적 분포로 변환
     (4) a[]배열을 뒤에서부터 읽어서 b[--count[a[i]]]에 저장

    coid dist_count (int a[], int n, int m)
    {
        int i; int *b, *count;
   
        b=(int*)malloc(sizeof(int)*n);
        count=(int*)malloc(sizeof(int)*(m+1));

        for(i=0; i<=m; i++) count[i]=0;
        for(i=0; i<n; i++) count[a[i]]++;
        for(i=2; i<=m; i++) count[i] = count[i-1] + count[i];
        for(i=n-1; i>=0; i--) b[--count[a[i]]] = a[i];
        for(i=0; i<n; i++) a[i]=b[i];
        free(b);
        free(count);
    }

--------------------------------------------------------------------------------


  


'Algorithm' 카테고리의 다른 글

CORBA, EJB, COM/DCOM  (0) 2008.12.05
ACID  (0) 2008.09.16
HDLC 프로토콜  (0) 2008.08.26
셀정렬  (1) 2008.08.23
삽입정렬  (0) 2008.08.23
Posted by 으랏차
,