udada
Daisy on April
udada
전체 방문자
오늘
어제
  • 분류 전체보기 (51)
    • Computer Science (19)
      • 웹(Web) (0)
      • SQL (0)
      • 개발자 공부(Developer) (13)
      • 코딩테스트 (5)
    • 소프트웨어 전공 (12)
      • 알고리즘 개론 (0)
      • 컴퓨터 구조 개론 (3)
      • 프로그래밍 언어 (0)
      • 시스템 프로그램 (6)
      • 시스템 프로그래밍 실습 (3)
      • 자바 프로그래밍 실습 (0)
      • 웹 프로그래밍 실습 (0)
    • 스파르타코딩클럽 (0)
      • 웹개발 (0)
    • 프로젝트 (0)
      • URP 프로젝트 (0)
      • ICT 한이음 프로젝트 (0)
      • [CloneCoding] Twitter (0)
    • 경력 (0)
      • IBK 기업은행 (0)
    • News (4)
      • Tech News (3)
      • 경제 신문 스크랩 (0)
    • 독서 (1)
    • 기타 (0)
    • English Expression (9)
    • Motion Graphic (1)
    • Metaverse (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • DigitalWallet
  • 메타버스
  • 쿼리
  • RDBMS
  • sql #rdbms
  • web-dev
  • metaverse
  • 아이폰과갤럭시
  • HTML
  • SQL
  • 관계형데이터베이스
  • 영어표현
  • 웹개발
  • ComputerScience
  • 자물쇠효과
  • javascripts
  • CSS
  • front-end
  • query
  • 프론트엔드

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
udada

Daisy on April

Computer Science/코딩테스트

[Python] 정렬

2022. 9. 16. 16:23

정렬(Sorting)

: 데이터를 특정한 기준에 따라서 순서대로 나열하는 것

→ 정렬 알고리즘으로 데이터를 정렬하면 이진 탐색(binary Search)가 가능

 

선택 정렬(Selection Sort)

: 가장 원시적인 방법으로 가장 작은 것을 선택; 오름차순 기준으로 가장 작은 데이터를 앞으로 보내는 과정을 N-1번 반복

→ 데이터가 무작위로 여러 개 있을 때, 이 중에서 가장 작은 데이터를 선택해 맨 앞에 있는 데이터와 바꾸고, 그 다음 데이터를 선택하여 앞에서 두 번째 데이터와 바꾸는 과정을 반복

array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]

for i in range(len(array)):
	min_index = i
    for j in range(i+1, len(array)):
    	if array[min_index] > array[j]:
        	min_index = j
    array[i], array[min_index] = array[min_index], array[i]
 
print(array)

시간 복잡도: O(N^2)

 

삽입 정렬(Insertion Sort)

: 특정한 데이터를 적절한 위치에 삽입

→ 필요할 때만 위치를 바꾸므로 '데이터가 거의 정렬되어 있을 때' 훨씬 효율적

 

삽입정렬은 두 번째 데이터부터 시작한다. 왜냐하면 첫 번째 데이터는 그 자체로 정렬되어 있다고 판단하기 때문

array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]

for i in range(1, len(array)): #두번째 원소부터 시작
	for j in range(i, 0, -1): #인덱스 i부터 1까지 감소하며 반복하는 문법
    	if array[j] < array[j-1]:
        	array[j], array[j-1] = array[j-1], array[j]
        else:
        	break
print(array)

시간 복잡도: O(N^2)

 

퀵 정렬(Quick Sort)

: 기준(피벗; pivot)을 설정한 다음 큰 수와 작은 수를 교환한 후 리스트를 반으로 나누는 방식으로 동작

퀵 정렬에서는 특정한 리스트에서 피벗을 설정하여 정렬을 수행한 이후에, 피벗을 기준으로 왼쪽 리스트와 오른쪽 리스트에서 각각 다시 정렬을 수행 → 재귀함수와 동작원리가 동일

 

보편적인 퀵 정렬

array = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8]

def quick_sort(array, start, end):
	if start >= end: #원소가 1개인 경우 종료
    	return
    pivot = start
    left = start + 1
    right = end
    while left <= right:
    	#피벗보다 큰 데이터를 찾을 때까지 반복
        while left <= end and array[left] <= array[pivot]:
        	left += 1
        #피벗보다 작은 데이터를 찾을 때까지 반복
        while right > start and array[right] >= array[pivot]:
        	right -= 1
        if left > right: #엇갈렸다면 작은 데이터와 피벗을 교체
        	array[right], array[pivot] = array[pivot], array[right]
        else:
        	array[left], array[right] = array[right], array[left]
        #분할 이후 왼쪽 부분과 오른쪽 부분에서 각각 정렬 수행
        quick_sort(array, start, right -1)
        quick_sort(array, right + 1, end)

quick_sort(array, 0, len(array)-1)
print(array)

파이썬의 장점을 살린 퀵 정렬

array = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8]

def quick_sort(array):
	#리스트가 하나 이하의 원소만을 담고 있다면 종료
    if len(array) <= 1:
    	return array
    pivot = array[0]
    tail = array[1:]
    
    left_side = [x for x in tail if x <= pivot] #분할된 왼쪽 부분
    right_side = [x for x in tail if x > pivot] #분할된 오른쪽 부분
    
    #분할 이후 왼쪽 부분과 오른쪽 부분에서 각각 정렬을 수행하고, 전체 리스트를 반환
    return quick_sort(left_side) + [pivot] + quick_sort(right_side)
print(quick_sort(array))

시간 복잡도: 평균적인 시간복잡도 - O(Nlog(N)) 최악의 시간복잡도 - O(N^2)

 

데이터가 무작위로 입력되는 경우는 퀵 정렬이 빠르게 동작하지만, 이미 데이터가 정렬되어 있는 경우에는 느리게 동작

 

계수 정렬

: 특정한 조건에 부합할 따만 사용할 수 있지만 매우 빠른 정렬 알고리즘

→ 데이터 크기 범위가 제한되어 정수 형태로 표현할 수 있을 때만 사용 가능

일반적으로 가장 큰 데이터와 가장 작은 데이터의 차이가 1,000,000을 넘지 않을 때 효과적으로 사용 가능

Why? 계수 정렬을 사용할 때는 모든 범위를 담을 수 있는 크기의 리스트(배열)을 선언해야 하기 때문

#모든 원소의 값이 0보다 크거나 같다고 가정
array = [7, 5, 9, 0, 3, 1, 6, 2, 9, 1, 4, 8, 0, 5, 2]
#모든 범위를 포함하는 리스트 선언(모든 값은 0으로 초기화)
count = [0] * (max(array) + 1)

for i in range(len(array)):
	count[array[i]] += 1 #각 데이터에 해당하는 인덱스의 값 증가
for i in range(len(count)): #리스트에 기록된 정렬 정보 확인
	for j in range(count[i]):
    	print(i, end='') #띄어쓰기를 구분으로 등장한 횟수만큼 인덱스 출력

시간 복잡도: O(N + K) (N:데이터 개수, K: 데이터 중 최대값의 크기) → 가장 빠르다.

공간 복잡도: O(N + K) (N:데이터 개수, K: 데이터 중 최대값의 크기)

 

계수정렬은 데이터의 크기가 한정되어 있고, 데이터의 크기가 많이 중복되어 있을수록 유리하다.

하지만 공간의 비효율성이 발생할 수 있기 때문에 데이터의 특성을 파악하기 어렵다면 퀵 정렬을 쓰는 것이 유리하다.

 

파이썬의 정렬 라이브러리

기본 정렬 라이브러리인 sorted() 함수를 제공; 퀵 정렬과 동작방식이 유사한 병합 정렬을 기반으로 제작

최악의 경우에도 시간복잡도 O(Nlog(N))

array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]

result = sorted(array)
print(result) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
array = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]

array.sort()
print(array) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
array = [('바나나', 2), ('사과', 5), ('당근', 3)]

def setting(data):
	return data[1]
    
#키 값으로는 하나의 함수가 들어가야 한다.
result = sorted(array, key=setting)
print(result) #[('바나나', 2), ('당근', 3), ('사과', 5)]

문제에서 별도의 요구가 없다면 

단순히 정렬해야 하는 상황: 기본 정렬 라이브러리 사용

데이터의 범위가 한정되어 있으며 빠르게 동작해야 하는 상황: 계수 정렬 사용

 

'Computer Science > 코딩테스트' 카테고리의 다른 글

[Python] 최단 경로 알고리즘  (0) 2022.10.02
[Python] 이진탐색  (0) 2022.09.20
[Python] DFS(깊이우선탐색)/BFS(너비우선탐색)  (0) 2022.08.25
[Python] 그리디  (0) 2022.08.23
    'Computer Science/코딩테스트' 카테고리의 다른 글
    • [Python] 최단 경로 알고리즘
    • [Python] 이진탐색
    • [Python] DFS(깊이우선탐색)/BFS(너비우선탐색)
    • [Python] 그리디
    udada
    udada

    티스토리툴바