Sort 정리
Bubble Sort
stable sort
매번 연속된 두개의 인덱스를 비교하여 정한 기준의 값을 뒤로 넘겨 정렬하는 방법. 오름차순일 경우 비교시 큰값이 뒤로 이동.
시간복잡도 O(n^2)
void bubbleSort(vector<int> v){ for(int i=0; i<v.size()-1;i++){ if(v[j-1]>v[j]) swap(v[j-1],v[j]); } }
Selection Sort
시간복잡도 O(n^2)
unstable sort
void selectionSort(vector<int> v){
for(int i=0; i<v.size();i++){
int tmp = i;
for(int j=i+1;j<v.size();j++){
if(v[tmp]>=v[j]) tmp = j;
}
swap(v[i],v[tmp]);
}
}
Insertion Sort
stable sort
기본 아이디어 : 현재 위치에서, 그 이하의 배열드을 비교하여 자신이 들어갈 위치를찾아, 그 위치에 삽입하는 배열 알고리즘 이다.
시간복잡도 : O(n^2)
void insertionSort(vector<int>v){ for(int i=1; i<v.size();i++){//1씩 증가하며 비교할 숫자 int key = v[i], j= i-1; //i번째 숫자가 key 그 바로아래부터 비교시작 while(j>=0 && key < v[j]){ //비교숫자가 key보다 크거나 같거나 0보다 작을때 까지 비교 swap(v[j], v[j+1]);//key가 비교숫자보다 작거나 인덱스가 0보다 크거나같을때 j--;//감소 } v[j+1] = key; } }
Heap Sort
unstable sort
min heap, max heap을 구성해 정렬하는 방법. 내림차순 정렬을 위해서는 max heap을 이용하고 오름차순 정렬을 위해서는 min heap을 이용하면 된다.
Merge Sort
stable sort
#include<iostream> using namespace std; int N,arr[1000001]; int *arr2; void merge(int left, int right) { int mid = (left + right) / 2; int i = left; int j = mid + 1; int k = left; while (i <= mid && j <= right) { if (arr[i] <= arr[j]) arr2[k++] = arr[i++]; else arr2[k++] = arr[j++]; } int tmp = i>mid ? j : i; while(k<=right) arr2[k++] = arr[tmp++]; for (int i=left;i<=right;i++) arr[i] = arr2[i]; } void partition(int left,int right) { int mid; if (left < right) { mid = (left + right) / 2; partition(left, mid); partition(mid + 1, right); merge(left, right); } } int main() { scanf("%d",&N); arr2 = new int[N]; for (int i=0;i<N;i++) scanf("%d",&arr[i]); partition(0, N - 1); for (int i=0;i<N;i++) printf("%d\n",arr[i]) ; }
Quick Sort
unstable sort
quick sort는 다음의 단계들로 이루어진다.
분할(Divide) : 입력 배열을 피벗을 기준으로 비균등하게 2개의 부분 배열(피벗을 중심으로 왼쪽: 피벗보다 작은 요소들, 오른쪽 : 피벗보다 큰 요소들)로 분할한다.
정복(Conquer) 부분 배열을 정렬한다. 부분 배열의 크기가 충분히 작지 않으면 순환 호출을 이용하여 다시 분할 정복 방법을 적용한다.
결합(Combine) : 정렬된 부분 배열들을 하나의 배열에 합병한다.
순환 호출이 한번 진행될 때 마다 최소한 하나의 원소(피벗)는 최종적으로 위치가 정해지므로 이 알고리즘은 반드시 끝난다는 것을 보장할 수 있다.
특징
장점
속도가 빠르다
시간복잡도 O(nlogn)
추가 메모리 공간을 필요로 하지 않는다.
퀵 소트는 O(logn)만큼의 메모리를 필요로 한다.
단점
정렬된 리스트에 대해서는 퀵 정렬의 불균형 분할에 의해 오히려 수행시간이 더 많이 걸린다.
해결법 : 퀵정렬의 불균형 분할을 방지하기 위해 피벗을 선택할 대 더욱 리스트를 균등하게 분할할 수 있는 데이터를 선택한다.
#include <stdio.h> #include <stdlib.h> #include <iostream> #include <time.h> using namespace std; void swap(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; } int partition(int a[], int left, int right) { srand(time(NULL)); // left ~ right 사이의 값을 랜덤으로 생성 int pivot_index = rand() % (right + 1 - left) + left; int pivot_value = a[pivot_index]; swap(&a[pivot_index], &a[right]); // store_index를 기준으로 // 왼쪽에 pivot_value보다 작은 값들 위치시킴 int store_index = left; for (int i = left; i < right; i++) { if (a[i] < pivot_value) { swap(&a[i], &a[store_index]); store_index += 1; } } swap(&a[store_index], &a[right]); return store_index; } void quick_sort(int a[], int left, int right) { if (left < right) { int p = partition(a, left, right); quick_sort(a, left, p - 1); quick_sort(a, p + 1, right); } } int main() { int a[5]; int len = sizeof(a) / sizeof(int); // 배열길이 // 랜덤함수를 위한 srand와 seed srand(time(NULL)); // 배열 초기화 for (int i = 0; i < len; i++) { // 1 ~ 50까지의 난수 생성 a[i] = rand() % 50 + 1; } // 정렬 전 출력 for (int i = 0; i < len; i++) { cout << a[i] << ' '; } cout << '\n'; // 퀵정렬 quick_sort(a, 0, len - 1); // 정렬 후 출력 for (int i = 0; i < len; i++) { cout << a[i] << ' '; } cout << '\n'; return 0; }
Last updated
Was this helpful?