Computer science/Algorithm

병합 정렬

잔망루피 2021. 1. 29. 19:56

 

병합 정렬

여러 개의 정렬된 자료의 집합을 병합하여 한 개의 정렬되 집합으로 만드는 방식

자료를 최소 단위의 문제까지 나눈 후에 차례대로 정렬하여 최종 결과를 얻음.

Top-Down 방식

O(n log n)

 

 

def merge(left, right):
  result=[]   # 두 개의 분할된 리스트를 병합하여 result 만듦

  while len(left) > 0 and len(right) > 0 :  # 양쪽 리스트에 원소가 남아있는 경우
    # 두 서브 리스트의 첫 원소들을 비교하여 작은 것부터 result에 추가
    if left[0] <= right[0] :
      result.append(left.pop(0))
    else :
      result.append(right.pop(0))

  if len(left) > 0 :  # 왼쪽 리스트에 원소가 남아있는 경우
    result.extend(left)
  if len(right) > 0 : # 오른쪽 리스트에 원소가 남아있는 경우
    result.extend(right)
  return result

def merge_sort(m):
  if len(m) <= 1 :    # 사이즈가 0이거나 1인 경우, 바로 리턴
    return m

  # 1. divide 부분
  mid=len(m)//2
  left=m[:mid]
  right=m[mid:]

  # 리스트의 크기가 1이 될 때까지 merge_sort 재귀 호출
  left=merge_sort(left)
  right=merge_sort(right)

  # 2. conquer 부분 : 분할된 리스트들 병합
  return merge(left, right)
  

 

merge함수에서는 left와 right 원소들을 비교해서 병합한다.

비교가 끝나고도 남은 원소는 result 리스트 뒤에 추가한다.

merge_sort함수는 병합 정렬할 m의 길이가 1과 같거나 작을 때까지 분할한다. 재귀호출을 사용한다.

가운데 mid를 기준으로 left와 right로 분할한다.

 

 

🍿 나의 풀이

 

# 병합(오름차순 정렬)
data1=list(map(int, input().split()))
data2=list(map(int, input().split()))
merge=list()

while data1 != [] and data2 != [] :
  if data1[0] > data2[0] : 
    merge.append(data2.pop(0))
  elif data1[0] < data2[0] :
    merge.append(data1.pop(0))
  else:     # 두 값이 같을 때
    merge.append(data1.pop(0))
    data2.pop(0)

# 남은 값 merge에 추가
if data1 :
  merge+=data1
else :
  merge+=data2

print(merge)

 

병합 기능만 구현해 봄.

data1과 data2가 각각 오름차순 정렬된 리스트라는 가정.

 

 

🍳 다른 사람 풀이

 

# 출처 : https://www.daleseo.com/sort-merge/

def merge_sort(arr):
    def sort(low, high) :       # 분할
        if high - low < 2 :
            return
        mid=(low+high)//2
        sort(low, mid)
        sort(mid, high)
        merge(low, mid, high)

    def merge(low, mid, high) :			# 병합
        temp=[]
        l, h=low, mid
		# 비교. 더 작은 원소를 temp에 삽입
        while l < mid and h < high :
            if arr[l] < arr[h] :
                temp.append(arr[l])
                l+=1
            else :
                temp.append(arr[h])
                h+=1
        # 남은 원소가 있다면 추가        
        while l < mid :
            temp.append(arr[l])
            l+=1
        while h < high :
            temp.append(arr[h])
            h+=1

        for i in range(low, high) :
        	# 원래 리스트 arr을 정렬. i-low를 해야 범위를 벗어나지 않음
            arr[i]=temp[i-low]	

    return sort(0, len(arr))

merge_sort([69, 10, 30, 2, 16, 8, 31, 22])			# 함수 호출

 

merge_sort함수를 호출하면 처음에 sort가 호출됨.

함수 sort에서 비교할 인덱스 범위를 정한다. 길이가 1이 될 때 까지 분할 후 merge함수 호출

merge함수에서 병합한다. temp에 담은 원소를 arr에 담는다(정렬)

다소 복잡한 풀이다.

 

 

 

 

참고. SW expert academy

반응형

'Computer science > Algorithm' 카테고리의 다른 글

이진 트리  (0) 2021.02.03
Tree  (0) 2021.02.03
삽입 정렬  (0) 2021.01.29
Linked List  (0) 2021.01.29
BFS(너비 우선 탐색)  (0) 2021.01.25