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))