CS/알고리즘
[알고리즘] 정렬 알고리즘
삶_
2022. 6. 30. 10:31
선택 정렬
- 데이터를 특정한 기준에 따라 순서대로 나열하는 것
- 아이디어가 매우 간단함
- 선택 정렬 방법
- 처음에 가장 작은 수를 선택하고 맨 앞과 위치를 바꿈
- 그 다음 작은수를 맨앞의 두번째와 자리를 바꿈
- 이 과정을 반복
#순서가없는 0~9의 수
array = [7,5,9,0,3,1,6,2,4,8]
for i in range(len[array]): #인덱스 첫~끝 차례대로 대입
min_index = i #가장 작은 원소가 들어있는 인덱스 찾기(1번으로 기준)
# 인덱스 두번째부터~
# 맨앞의 인덱스 > 두번째,세번째... 비교했는데
# 비교한 값이 더 작으면 그 인덱스를 min으로 바꿈
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] #스와프함
#풀이방법
메인) 리스트의 첫번째에 작은수 / 그다음 작은수가 오게함
비교값이 될 첫번째 인덱스를 정의함
(작은값으로 교체해야되기 때문에 반복되는 수로 대입 > for문사용)
두번째인덱스부터... 차례대로 비교하는데 더 작은수가 포함된 인덱스가 나오면
그 인덱스랑 본인인덱스랑 교체.
계획대로 식이 만들어짐
삽입정렬
- 처리되지 않은 데이터를 하나씩 골라 적절한 위치에 삽입
- 데이터가 정렬되어 있을때 가장 빠름
- 선택정렬에 비해 구현 난이도가 높음
- 삽입정렬 방법
- 첫번째 위치는 첫번째에 있게 고정함 (정렬되어있다 생각하고)
- 두번째는 첫번째와 비교해서 작으면 앞으로, 안작으면 뒤에 있기(그냥 가만히 있으면됨)
- 위과정을 계속 반복하는데,
- 자기보다 작은 걸 만나면 그 위치에서 반복을 멈춘다
- 현재 리스트의 데이터가 거의 정렬되어있다면 매우 빠르게 동작함.
- (앞뒤 빨리 판단되서 연산이 금방 끝나니까)
#순서가없는 0~9의 수
array = [7,5,9,0,3,1,6,2,4,8]
#range(a,b,c) : a가 b가 될때까지 c는 어떤 공식을 넣어 인덱스를 변하게 할건지
for i in range(1, len(array)):
for j in range(i, 0, -1): #인덱스가 0이 되기전까지 -1한다
if array[j] < array[j-1]: #앞의 값보다 작으면 서로를 교체함
array[j], array[j-1] = array[j-1], array[j]
else: #자기보다 작은데이터를 만나면 그 위치에서 멈춤
break
print(array)
퀵 정렬
- 기준 데이터를 설정.
- 대부분의 경우에 가장 적합한 정렬, 충분히 빠르다
- 기준보다 큰 데이터와 작은 데이터의 위치를 바꾸는 방법
- 가장 기본적인 퀵 정렬 방법
- 첫번째 데이터를 기준데이터로 설정
- 가장 왼쪽 -> 오른쪽 가면서 기준데이터보다 큰값을 고르기
- 가장 오른쪽 -> 왼쪽 기준데이터보다 작은값 고르기
- 그리고 뽑힌 두개의 인덱스 위치를 바꿔줌
- 자연스레 작은것이 왼쪽에 분포하고,
큰것이 오른쪽에 분포하게 됨 - 위과정을 계속 반복
- 위치가 엇갈리는 경우 : 왼쪽->오른쪽 가던 작은 값을 기준데이터와 바꿔줌
- 왼쪽들은 기준데이터보다 더 작고, 오른쪽들은 기준데이터보다 더 크다
- 그리고 그 왼쪽과 오른쪽 내에서 각각 또 위과정을 반복
array=[5,7,9,0,3,1,6,2,4,8]
def quick_sort(array, start, end):
# start=0 / end = array길이-1
if start >= end:
return
# 피벗에 첫번째 인덱스를 대입한다
pivot = start
# 왼쪽은 피벗보다 인덱스가 +1 추가됨
left = start + 1
# 오른쪽은 인덱스 끝에서 시작해야 하니 array길이-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)
계수 정렬
- 각각의 데이터가 몇번 등장했는지 알아보기 위한 것
- 특정한 조건이 부합할때만 사용가능. 매우 빠르게 동작하는 정렬 알고리즘
- 데이터의 크기가 한정되어 있는 경우에만 사용이 가능. 조건만 맞다면 매우 빠름.
- 데이터의 크기 범위가 제한되어 정수형태로 표현할 수 있을때 사용 가능
- 가장 작은 데이터부터 가장 큰 데이터까지의 범위가 모두 담길수있도록 리스트 생성
- 데이터를 하나씩 확인. 데이터의 값과 동일한 인덱스의 데이터를 1증가시킴
array=[7,5,9,0,3,1,6,2,9,1,4,8,0,5,2]
#0원소를 array에 담겨있는 수 중 최댓값 만큼 담음 0~최댓값+1 (0이 추가로 들어가니까)
count=[0]*(max(array)+1)
#0~최댓값까지 하나하나씩 위치와 값을 일치시켜서 몇개가 있는지 세준다
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=' ')
sort()로 풀기
- 두개의 배열 A와 B
n개의 원소로 구성됨
최대 K번의 바꿔치기 수행가능. A와 B의 원소하나를 골라 바꿔치기하는것임
배열A의 모든원소의 합이 최대가 되는게 목표
import sys
n, k = map(int, sys.stdin.readline().split())
a = list(map(int, sys.stdin.readline().split()))
b = list(map(int, sys.stdin.readline().split()))
a.sort()
b.sort(reverse=True)
for i in range(k):
if a[i] < b[i]:
a[i] = b[i]
else:
break
print(sum(a))