티스토리 뷰
안녕하세요!
오늘은 정렬 알고리즘에 대해 공부하려고 해요.
정렬 알고리즘은 공부를 안하면 늘 까먹는 것 같아요..
퀵정렬이 어떻게 이뤄지는지....선택정렬이 뭐였는지..
또 시간복잡도는 뭔지!!!
공부를 해도 항상 몇달 뒤면 까먹게 되네요 :(
저도 공부를 할 겸 정리하는 시간을 가져볼려고 합니다.
1. 선택정렬(selection sort) - O(n2)
먼저 선택정렬의 정의 부터 볼까요?
"선택 정렬(selection sort)은 정렬되지 않은 데이터들에 대해
가장 작은 데이터를 찾아 가장 앞의 데이터와
교환해나가는 방식이다."
라고 하네요 :)
선택정렬에서는 세가지 과정만 기억하시면 됩니다.
1. 앞에서 부터 데이터 하나를 선택한다.
2. 내가 선택한 데이터 이후에 있는 원소들 중 가장 작은 값을 찾는다.
3. 내가 선택한 값과 바꾼다.
말로하니 잘 모르시겠나요?
위키백과에 있는 예제를 통해 알아볼게요 :)
[9,1,6,8,4,3,2,0]
1. 앞에서 부터 데이터 하나를 선택한다. --> 9
[9,1,6,8,4,3,2,0]
2. 내가 선택한 데이터 이후에 있는 원소들 중 가장 작은 값을 찾아 --> 0
[9,1,6,8,4,3,2,0]
3. 내가 선택한 값과 바꾼다. 0 <----> 9
[0,1,6,8,4,3,2,9]
1. 앞에서 부터 데이터 하나를 선택한다. --> 1
[0,1,6,8,4,3,2,9]
2. 내가 선택한 데이터 이후에 있는 원소들 중 가장 작은 값을 찾아 --> 1
[0,1,6,8,4,3,2,9]
3. 내가 선택한 값과 바꾼다. 1 <----> 1
[0,1,6,8,4,3,2,9]
1. 앞에서 부터 데이터 하나를 선택한다. --> 6
[0,1,6,8,4,3,2,9]
2. 내가 선택한 데이터 이후에 있는 원소들 중 가장 작은 값을 찾아 --> 2
[0,1,6,8,4,3,2,9]
3. 내가 선택한 값과 바꾼다. 6 <----> 2
[0,1,2,8,4,3,6,9]
"삽입정렬은 자료 배열의 모든 요소를 앞에서부터 차례대로
이미 정렬된 배열 부분과 비교하여,
자신의 위치를 찾아 삽입함으로써
정렬을 완성하는 알고리즘입니다."
출처 - 위키백과
위 자료들을 보시면 어느정도 이해가 가실 것 같아요 :)
제가 쉽게 설명드릴려고 생각해봤는데,
딱 제가 선택한 원소를 인형뽑기 집게로 딱!! 뽑았다고 생각하세요.
그리고 뒤는 보지말고 앞의 원소들만 보며 비교하면서,
제가 집은 그 원소를 적절한 자리에 삽입시켜준다고 생각해보세요 :)
삽입정렬에 대한 설명과 자료들은 엄청나게 많으니
이해가 안되신다면 더 찾아보시는 것을 추천드립니다 ㅠㅠ
삽입정렬의 장단점이 있는데요,
장점 : 구현이 간단하다.
단점 : 배열이 길어질수록 효율이 떨어진다.
마지막으로 삽입정렬에 대한 시간복잡도를 생각해 볼까요?
최악의 경우 (역으로 정렬되어 있을 경우) 선택정렬과 마찬가지로,
(n-1) + (n-2) + .... + 2 + 1 => n(n-1)/2
삽입 정렬 내부 반복문은 생각보다 빠르기 때문에
데이터의 수가 8~20 개 근처일 때
가장 빠른 정렬 알고리즘이 될 수도 있다고 하네요 :)
그래서 시간복잡도가 뭐냐구요?
하지만 저희가 시간복잡도를 나타내는 빅오 표기법
(Big-O notation)은 최악을 기준으로 하기 때문에
삽입정렬의 시간복잡도는 O(n2) 이라고
알고계시면 될 것 같아요ㅎㅎ
3. 버블 정렬 (Bubble Sort)- O(n2)
버블정렬은 두 인접한 원소를 검사하여 정렬하는 방법이에요.
버블정렬은 시간복잡도가 O(n2) 으로 상당히 느린편에 속하지만,
코드가 단순해서 자주 사용된다고 합니다 :)
예제를 통해 한번 볼까요? 버블정렬은 정말 쉬우니
한번에 이해가 가실거에요.
과정을 먼저 살펴볼까요?
1. 앞에서부터 다음 인덱스와 비교한다.(인접한 인덱스끼리 비교)
2. 큰 것은 뒤로 보낸다.
3. 배열의 끝까지 1~2과정을 반복하며, 한 회전이 끝나면
다시 앞으로 돌아와 1~2의 과정을 반복한다.
[6,5,9,3,1]
1. 앞에서부터 다음 인덱스와 비교한다.
[6,5,9,3,1]
2. 큰 것은 뒤로 보낸다.
[5,6,9,3,1]
첫번째 인덱스에 관해 정렬이 끝났으니
이제 두번째 인덱스에서 시작해
인접한 인덱스, 즉 다음 인덱스와 비교해야겠죠?
1. 앞에서부터 다음 인덱스와 비교한다.
[5,6,9,3,1]
2. 큰 것은 뒤로 보낸다.
[5,6,9,3,1]
1. 앞에서부터 다음 인덱스와 비교한다.
[5,6,9,3,1]
2. 큰 것은 뒤로 보낸다.
[5,6,3,9,1]
1. 앞에서부터 다음 인덱스와 비교한다.
[5,6,3,9,1]
2. 큰 것은 뒤로 보낸다.
[5,6,3,1,9]
자, 이렇게 한 회전이 끝났습니다.
이제 처음으로 ( 첫번째 인덱스로 ) 돌아가 위 과정을 반복해주면
최종적으로 오름차순으로 정렬이 되게 된답니다 :)
버블정렬의 시간복잡도를 생각해볼까요?
시간복잡도는
(n-1) + (n-2) + .... + 2 + 1 => n(n-1)/2
즉 O(n2)라고 할 수 있겠네요.
선택정렬과 마찬가지로 배열이 어떻게 되어있든
비교를 진행하니 O(n2)이 맞겠죠?
버블 정렬은 한번의 순회를 마칠 때 마다 비교 대상이 하나씩 줄어들기 때문에,
-> why? 한 회전이 끝나면 배열안에서 가장 큰 값이 맨 뒤로 가기 때문.
전체 원소의 개수가 n개 라고 할 때, 총 n-1 번 순회하면 정렬이 끝납니다.
위의 예제에서는 총 원소 개수가 5개 이므로,
4 + 3 + 2 + 1 = 10번 비교하게 됩니다.
자, 오늘은 O(n2) 정렬 알고리즘들을 살펴봤는데요,
원래 모든 정렬 알고리즘을 하나의 글에 정리하려다 너무 길어질 것 같아서
시간복잡도로 나눠서 정리하려고 합니다 XD
O(n2)정렬 알고리즘엔
선택정렬, 삽입정렬, 버블정렬이 있다는것.
잊지마세요!!
그리고 사실 이 글에는 쓰지않았지만,
퀵소트도 빅오표기법으로 시간복잡도를 O(n2)을 가지는 정렬 알고리즘입니다.
위에서 말씀드렸듯이, 빅오표기법(Big-O notation)은
최악의 수행시간으로 말해야 합니다 :)
궁금증이 드실 수 도 있겠네요.
"퀵소트 O(nlogn)아니야?"
이 말은 사실 정확히 맞는말은 아닙니다.
왜 정확히 맞는 말이 아닌지 생각하기전에,
"시간복잡도"
혹시 "시간복잡도"의 정의를 아시나요?
시간복잡도는
간단히 말해서
"어떤 알고리즘이 얼마나 걸리느냐"
라고 할 수 있습니다.
이 시간복잡도를 구하는 방법은
시간 복잡도 = 알고리즘을 구성한 명령어가 실행된 횟수
(frequency of calling command)
라고 정의할 수 있습니다.
frequency of calling command는
frequency count라고도 한답니다.
원래 시간복잡도는
시간복잡도 =
알고리즘을 구성한 명령어가 실행된 횟수(frequency count)
+
명령어 실행시간(execution time)
입니다.
하지만 이 명령어 실행시간(execution time)은
특정 하드웨어 또는 사용 언어에 따라서 값이 달라질 수 있기때문에
일반적인 시간복잡도는 명령어 실행시간을 제외한
명령어가 실행된 횟수(frequency count)만을 고려하게 됩니다.
또한 시간복잡도에도 종류가 있다는 것. 아시죠?
시간복잡도는 나타내는 방법으로는 세가지가 있습니다.
Θ() - 세타 -> 평균시간
입니다.
설명을 붙이자면,
O(). 빅오표기법(Big-O notation)은
가장 일반적으로 많이 쓰이는 시간복잡도 표기법입니다.
즉, 알고리즘 실행시간의 상한을 나타내는 표기법이죠.
Ω(). 오메가표기법은 알고리즘 실행시간의 하한을 나타내는 표기법입니다.
시간복잡도에 대한 설명이 길어졌네요 ㅎㅎ..
본론으로 돌아와서!!
왜 퀵소트의 시간복잡도 O(nlogn)이 틀린말일까요?
위에 퀵소트에 대한 설명이 없어서 아직 퀵소트가 무엇인지 잘 모르시겠지만,
이것 하나만 알아두세요.
퀵소트에 대한 시간복잡도는
평균복잡도는 nlogn이지만 최악의 경우엔 n2이므로,
빅오표기법으로 표현한다면 시간복잡도는 O(n2)입니다.
왜 최악인지는 다음 글에서 설명할게요.
그럼 퀵소트를 nlogn의 시간복잡도로 표현하고 싶다면,
평균복잡도가 nlogn이니
Θ(nlogn)이 되겠네요.
뭔가 위에서 시간복잡도 다 말해놓고
밑에서시간복잡도의 정의를 설명하는게 좀 웃길 수도 있는데,
퀵소트를 말하다보니 이렇게 됐네요..ㅎㅎ
퀵소트의 시간복잡도에는 함정이 있으니 조심하세요!!
ps. 퀵소트를 이 글에 추가해야할지, 아니면 다음 글에 추가해야 할지 고민하다가 (왠지 여기에 추가하는 게 맞는 것 같지만)여기에 설명하게 되었네요
ㅎㅎ..
'공부' 카테고리의 다른 글
왕 초보를 위한 CocoaPods(코코아팟) 사용법 (Xcode와 연동) (16) | 2017.02.13 |
---|---|
소프트웨어 개발 방법론 (애자일 / 스크럼 ) (10) | 2017.02.13 |
사파리에서 403 Forbidden에러 해결법(애플 개발자 사이트 오류) (3) | 2017.01.22 |
MAC xcode 신뢰 할 수 없는 개발자 설정 방법 (1) | 2017.01.13 |
MAC 에서의 포인트(pt)와 픽셀(px)의 관계! (13) | 2017.01.11 |
- IOS
- UIBezierPath
- Combine
- swift 공부
- fastlane
- actor
- FLUTTER
- 피아노
- iOS delegate
- Xcode
- Accessibility
- WidgetKit
- WWDC
- swift tutorial
- 스위프트 문법
- ios 13
- swift delegate
- SwiftUI
- 제이슨 파싱
- 스위프트
- swift array
- np-complete
- 회고
- Swift
- np-hard
- swift3
- Git
- WKWebView
- github
- swift sort
- Total
- Today
- Yesterday