ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 정렬 - 삽입, 선택, 버블, 쉘, 합병
    컴퓨터 공부/자료구조 2020. 3. 25. 11:21

    오른차순 / 내리차순

     

    정렬 알고리즘 평가 

    --> 비교 횟수

    --> 이동 횟수

     

    단순 & easy, but 비효율적 : 삽입 정렬, 버블 정렬, 선택 정렬

    복잡 & difficult, but 효율적 : 퀵 정렬, 힙 정렬, 합병 정렬


    삽입 정렬

     

    정렬된 부분에 새로운 데이터 삽입

    정렬 안된 부분에서 작은 수 가져오기

     

    삽입 정렬

    // 삽입정렬
    void insertion_sort(int list[], int n)       	
    {   
       int i, j, key;
       for(i=1; i<n; i++){
       	key = list[i];//비교 대상 (current)
    	for(j=i-1; j>=0 && list[j]>key; j--) //key 값이 previous(j)보다 작으면
    		list[j+1] = list[j]; 		// 레코드의 오른쪽 이동
        	list[j+1] = key;
       }
    }
    

     

    복잡도 : O(n^2)

     

    최선의 경우 O(n) : 이미 정렬되어 있는 경우

    비교 : n-1

    이동 : 없음

     

    최악의 경우 O(n^2) : 역순으로 정렬되어 있는 경우

    모든 단계에서 앞에 놓인 자료 전부를 이동

    비교)

    이동)

    단점

    많은 이동이 필요하므로 레코드가 클 경우 불리


    선택 정렬

     

    정렬 안 된 부분(오른쪽)에서 최솟값 --> 정렬된 부분(왼쪽)으로 (자리 교체) --> 오른쪽 부분 데이터 없을 때까지 반복

     

     

    선택 정렬

    #define SWAP(x, y, t) ( (t)=(x), (x)=(y), (y)=(t) ) //자리 교체 
    void selection_sort(int list[], int n)
    {
       int i, j, least, temp;
    
       for(i=0; i<n-1; i++) {
       
          least = i; //최솟값 (처음은 맨 앞)
          for(j=i+1; j<n; j++) 		// 최솟값 탐색(정렬 부분 그 뒤 레코드부터~n)
             if(list[j]<list[least]) least = j; //최솟값 갱신
    
          SWAP(list[i], list[least], temp); // 가장 작은 수를 왼쪽에 넣기
       }
    }
    

     

    복잡도 : O(n^2)

     

    비교 횟수

    (n - 1) + (n - 2) + … + 1 = ∑_(i=1)^(n-1)▒i=  (n(n-1))/2=O(n^2)

     

    이동 횟수

    3(n - 1)

     

    특징

    입력에 민감하지 않다.

    효율성이 떨어진다.


    버블 정렬

    인접한 2개 비교 -> 작은 수를 앞으로 (1cycle-> 가장 큰 수가 뒤로 -> 반복)

    버블 정렬

    #define SWAP(x, y, t) ( (t)=(x), (x)=(y), (y)=(t) ) //자리 교체 메크로
    
    void bubble_sort(int list[], int n)
    {
       int i, j, temp;
    
       for(i=n-1; i>0; i--){      // 데이터가 n개일 때 n-1 회 반복
    		for(j=0; j<i; j++) 	// 앞뒤의 레코드를 비교한 후 교체
    	      if(list[j]>list[j+1])   //앞 레코드가 더 크면
         		    SWAP(list[j], list[j+1], temp); //자리 교체
       }
    }
    

     

    복잡도 :  O(n^2)

     

    비교 횟수(최상, 평균, 최악의 경우 모두 일정)

    O(n^2)

     

    이동 횟수

    이동 횟수 = 3 * 비교 횟수

    이미 정렬된 경우(최선의 경우) :  이동 횟수 = 0

     

    단점

    데이터의 이동이 많다.

    컴퓨터에게 이동은 비교보다 많은 시간이 소요된다.


    쉘 정렬

    삽입 정렬이 어느 정도 정렬된 리스트에서 대단히 빠른 것에 착안

     

    절차

     

     전체 리스트를 일정 간격(gap)의 부분 리스트로 나눈다. --> 각각의 부분 리스트를 삽입 정렬

     간격을 줄임

     부분 리스트의 수는 작아지고 각 부분 리스트의 크기는 더 커진다

     간격이 1 될 때까지 반복

     

    쉘 정렬

    // gap 만큼 떨어진 요소들을 삽입 정렬
    // 정렬의 범위는 first에서 last
    
    inc_insertion_sort(int list[], int first, int last, int gap) //각 부분 리스트 삽입 정렬
    {
    	int i, j, key;
    	for(i=first+gap; i<=last; i=i+gap){
    		key = list[i];
    		for(j=i-gap; j>=first && key<list[j];j=j-gap)
    			list[j+gap]=list[j];
    		list[j+gap]=key;
    	}
    }
    void shell_sort( int list[], int n )
    {
    	int i, gap;
    	for( gap=n/2; gap>0; gap = gap/2 ) { //간격: 5->3->1
    		if( (gap%2) == 0 ) gap++;
    		for(i=0;i<gap;i++)		// 부분 리스트의 개수는 gap (i=0~5/0~3/0~1)
    			inc_insertion_sort(list, i, n-1, gap); //0,9,5
    	}
    }
    

     

    복잡도 : O(n^1.5) , 최악은 O(n^2)


    합병 정렬

     

    리스트 -> 2개로 균등 분할 & 정렬하면서 합병

    분할 정복 (divide and conquer)방법

     

     

    합병 정렬

    merge_sort(list, left, right){
       if (left < right)
          mid = (left+right)/2; //반으로 나누고
          merge_sort(list, left, mid); //앞 부분 또 나누기 (재귀)
          merge_sort(list, mid+1, right); //뒷 부분 나누기
          merge(list, left, mid, right); //합병
       }
    
    merge(list, left, mid, right){
       i←left; j←mid+1; k←left;
       while i≤left and j≤right do
          if(list[i]<list[j]) 
             sorted[k]←list[i];
             k++; i++;
          else
             sorted[k]←list[j];
             k++; j++;
       요소가 남아있는 부분배열을 sorted로 복사;
       sorted를 list로 복사;
       }
    

     

    복잡도 : O(n log n⁡)

     

    비교) log n 으로 분할 (높이) & n번 비교

     

    이동) 각 패스 2n번 이동 --> 전체 2n * logn


     

    '컴퓨터 공부 > 자료구조' 카테고리의 다른 글

    연결리스트  (0) 2020.03.28
    정렬 - 퀵, 힙, 기수  (0) 2020.03.25
      (0) 2020.03.25
    스택 응용  (0) 2020.03.24
    스택  (0) 2020.03.24
Designed by Tistory.