λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

μ•Œκ³ λ¦¬μ¦˜

μ•Œκ³ λ¦¬μ¦˜ [Algorithm] - 병합 μ •λ ¬ Merge Sort(5) (C,Python)

병합정렬

  μ΄λ²ˆμ—λŠ” 병합 정렬에 λŒ€ν•΄ μ•Œμ•„λ³΄μž. 병합정렬도 퀡정렬과 λ§ˆμ°¬κ°€μ§€λ‘œ λŒ€ν‘œμ μΈ '뢄할정볡' 방법을 μ±„νƒν•œ μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€. λ”°λΌμ„œ 결과적으둜 퀡 μ •λ ¬κ³Ό λ™μΌν•˜κ²Œ O(N * logN)의 μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€.

 

  λ‹€λ§Œ 퀡 정렬은 μ΅œμ•…μ˜ 경우 O(N^2)의 μ‹œκ°„λ³΅μž‘λ„λ₯Ό κ°€μ§€μ§€λ§Œ, 병합정렬은 μ •ν™•νžˆ λ°˜μ ˆμ”© λ‚˜λˆˆλ‹€λŠ” μ μ—μ„œ μ΅œμ•…μ˜ κ²½μš°μ—λ„ O(N*logN)을 보μž₯ν•œλ‹€. 

 


λ‹€μŒμ˜ μˆ«μžλ“€μ„ μ˜€λ¦„μ°¨μˆœμœΌλ‘œ μ •λ ¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ„Έμš”.

7 6 5 8 3 5 9 1


병합정렬은 ν•˜λ‚˜μ˜ 큰 문제λ₯Ό λ‘κ°œμ˜ μž‘μ€ 문제둜 λΆ„ν• ν•œ 뒀에 각자 κ³„μ‚°ν•˜κ³  λ‚˜μ€‘μ— ν•©μΉ˜λŠ” 방법을 μ±„νƒν•œλ‹€. μ¦‰ κΈ°λ³Έ μ•„μ΄λ””μ–΄λŠ” 일단 μ •ν™•νžˆ 반으둜 λ‚˜λˆ„κ³  λ‚˜μ€‘μ— μ •λ ¬ν•˜λŠ” 것이닀. 

  퀡 μ •λ ¬κ³Ό λ‹€λ₯΄κ²Œ ν”Όλ²— 값이 μ—†κ³  항상 반으둜 λ‚˜λˆˆλ‹€λŠ” νŠΉμ§•μ΄ 있고, λ•Œλ¬Έμ— λ‹¨κ³„μ˜ 크기가 log N이 λ˜λ„λ‘ λ§Œλ“€μ–΄μ€€λ‹€.

 

7   6   5   8   3   5   9   1

67   58   35   19

5678   1359

13556789

 

  문제의 7 6 5 8 3 5 9 1은 λͺ¨λ‘ 크기가 κ°œλ³„μΈ λ°°μ—΄λ‘œ, 즉 크기가 1인 λ°°μ—΄ μƒνƒœλ‘œ μ‹œμž‘ν•œλ‹€. 첫번째 λ‹¨κ³„μ—μ„œλŠ” λ°°μ—΄μ˜ 크기가 2κ°œμ΄λ‹€. μ΄λ•Œ κ°œλ³„μ˜ μ›μ†Œλ“€μ΄ λ‘κ°œλ‘œ ν•©μ³μ§€λŠ” μˆœκ°„ 정렬이 λœλ‹€. λ”°λΌμ„œ 7 / 6 은 67둜, 5 / 8 은 58둜... λ‹€μŒ λ‹¨κ³„μ—μ„œλ„ 2개의 μ›μ†Œλ‘œ 이루어진 배열듀이 μ •λ ¬λ˜λ©΄μ„œ 합쳐진닀. 67 / 58 이 5678둜, 35 / 19κ°€ 1359둜...

 

  ν•©μΉ˜λŠ” κ°―μˆ˜κ°€ 2λ°°μ”© μ¦κ°€ν•œλ‹€λŠ” μ μ—μ„œ λ‹¨κ³„μ˜ ν¬κΈ°λŠ” λ°μ΄ν„°μ˜ κ°―μˆ˜κ°€ N개 μΌλ•Œ log N을 μœ μ§€ν•˜κ²Œ λœλ‹€. 

λ”°λΌμ„œ λ³‘ν•©μ •λ ¬μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(N * log N)이 λœλ‹€.

 

#include <stdio.h>
int number = 8;

int size;
int sorted[8]; // μ •λ ¬ 배열은 λ°˜λ“œμ‹œ μ „μ—­λ³€μˆ˜λ‘œ μ„ μ–Έ
int count = 0;

void merge(int a[],int m, int middle, int n)){
	int i = m;
    int j = middle +1;
    int k = m;
    // μž‘μ€ μˆœμ„œλŒ€λ‘œ 배열에 μ‚½μž…
    while(i<=middle &&j<=n){
    	if(a[i] <= a[j]) {
        	sorted[k] = a[i];
            i++;
        }
        else{
        	sorted[k] = a[j];
            j++;
        }
        k++;
    }
    //남은 데이터도 μ‚½μž…
    if(i>middle){
    	for(int t = j; t<=n; t++){
        	sorted[k] = a[t];
            k++;
            }
    }
    else{
    	for(int t=i;t<=middle;t++){
        	sosrted[k] = a[t];
            k++;
        }
    }
    
    //μ •λ ¬λœ 배열을 μ‚½μž…
    for(int t=m; t<=n; t++){
    	a[t] = sorted[t];
    }
}

void mergeSort(int a[], int m, int n){
	//μ΄μ™Έμ˜ κ²½μš°λŠ” 크기가 1개인 경우
    if(m<n){
    	int middle = (m+n)/2;
        mergeSort(a,m,middle);
        mergeSort(a,midddle+1,n);
        merge(a,m,middle,n);
    }
}


int main(void){
	int array[number] = {7, 6, 5, 8, 3, 5, 9, 1};
    mergeSort(array,0,number-1);
    for(int i=0; i< number;i++){
    	printf("%d ", array[i]);
    }
}

병합 정렬을 κ΅¬ν˜„ν•  λ•Œ 정렬에 μ‚¬μš©λ˜λŠ” 배열은 λ°˜λ“œμ‹œ 'μ „μ—­λ³€μˆ˜'둜 μ„ μ–Έν•΄μ•Ό ν•œλ‹€. λ§Œμ•½ ν•¨μˆ˜ μ•ˆμ—μ„œ 배열을 μ„ μ–Έν•˜κ²Œ λœλ‹€λ©΄ 맀번 배열을 μ„ μ–Έν•΄μ•Ό ν•˜λ―€λ‘œ λ©”λͺ¨λ¦¬ λ‚­λΉ„κ°€ 맀우 컀질 수 있기 λ•Œλ¬Έμ΄λ‹€. λ”°λΌμ„œ 기본적으둜 병합정렬은 '기쑴의 데이터λ₯Ό 담을 좔가적인 배열곡간이 ν•„μš”ν•˜λ‹€'λŠ” μ μ—μ„œ λ©”λͺ¨λ¦¬ ν™œμš©μ΄ λΉ„νš¨μœ¨μ μ΄λΌλŠ” λ¬Έμ œκ°€ μžˆλ‹€. ν•˜μ§€λ§Œ μ–΄λ–€ μƒν™©μ—μ„œλ„ λ³‘ν•©μ •λ ¬μ˜ μ‹œκ°„ λ³΅μž‘λ„λŠ” O(N * log N)을 보μž₯ν•˜λŠ” μ μ—μ„œ 효율적인 μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.

 

 

Python

sublist = [7,4,6,5,3,2,1,9,8,10]

def merge(list1,left,right,end):
  merged = []
  l,r = left,right
  while l< right and r<=end:
    if list1[l] <=list1[r]:
      merged.append(list1[l])
      l+=1
    else:
      merged.append(list1[r])
      r+=1
  while l<right:
    merged.append(list1[l])
    l+=1
  while r<=end:
    merged.append(list1[r])
    r+=1

  l = left
  for n in merged:
    list1[l] = n
    l+=1

def mergeSort(list1,p,q):
  if p>=q:
    return
  mid = (p+q)//2
  mergeSort(list1,p,mid)
  mergeSort(list1,mid+1,q)
  merge(list1,p,mid+1,q)


print(sublist)
sorted = mergeSort(sublist,0,len(sublist)-1)
print(sublist)

이 글은 λ‚˜λ™λΉˆλ‹˜μ˜ μ‹€μ „ μ•Œκ³ λ¦¬μ¦˜ κ°•μ’Œ (Algorithm Programming Tutorial)λ₯Ό μ°Έκ³ ν•΄ μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

https://www.youtube.com/watch?v=qQ5iLNjpxSk&list=PLRx0vPvlEmdDHxCvAQS1_6XV4deOwfVrz 

 

 

728x90