3 분 소요

개요

  • 데이터들이 주어졌을 때 이를 정해진 순서대로 나열


버블 정렬

  • n-1번째와 n번째를 정렬한 뒤 다시 처음부터 n-2번째와 n-1번째까지 정렬
  • O(n^2)
  • C++ code
    void bubbleSort(vector<int> &numbers) {
    	for(int i = 1 ; i < (int)numbers.size() ; i++) {
    		for(int j = 0 ; j < (int)numbers.size() - i ; j++) {
    			if(numbers.at(j) > numbers.at(j + 1)) {
    				swap(numbers.at(j), numbers.at(j + 1));
    			}
    		}
    	}
    }
    


칵테일/셰이커 정렬

  • 홀수 번째 돌 때는 앞부터, 짝수 번째는 뒤부터 훑는 정렬
  • O(n^2)
  • C++ code
    void cocktailSort(vector<int> &numbers) {
    	for(int i = 1 ; i < (int)numbers.size() ; i++) {
    		if(i % 2 == 1) {
    			for(int j = 0 ; j < (int)numbers.size() - i ; j++) {
    				if(numbers.at(j) > numbers.at(j + 1)) {
    					swap(numbers.at(j), numbers.at(j + 1));
    				}
    			}
    		} else {
    			for(int j = numbers.size() - i ; j > 0 ; j--) {
    				if(numbers.at(j - 1) > numbers.at(j)) {
    					swap(numbers.at(j), numbers.at(j - 1));
    				}
    			}
    		}
    	}			
    }
    


선택 정렬

  • 1번째부터 끝까지 훑어서 가장 작은 게 1번째, 2번째부터 끝까지 훑어서 가장 작은 게 2번째를 반복하는 정렬
  • O(n^2)
  • C++ code
    void selectionSort(vector<int> &numbers) {
    	for(int i = 0 ; i < (int)numbers.size() - 1; i++) {
    		int min = i;
    		for(int j = i + 1 ; j < (int)numbers.size() ; j++) {
    			if(numbers.at(i) > numbers.at(j)) {
    				min = j;
    			}
    		}
       
    		if(i != min) {
    			swap(numbers.at(i), numbers.at(min));
    		}
    	}
    }
    


이중 선택 정렬

  • 끝까지 훑어서 최솟값과 최댓값을 동시에 찾아낸 뒤 값을 바꾼 다음 훑는 범위를 양쪽으로 한 칸씩 줄여서 반복하는 정렬
  • O(n^2)
  • C++ code
    void doubleSelectionSort(vector<int> &numbers) {
    	for(int i = 0 ; i < (int)numbers.size() - i; i++) {
    		int start = i;
    		int end = (int)numbers.size() - i - 1;
       
    		int min = start;
    		int max = end;
    		for(int j = start ; j <= end ; j++) {
    			if(numbers.at(j) < numbers.at(min)) {
    				min = j;
    			} else if(numbers.at(j) > numbers.at(max)) {
    				max = j;
    			}
    		}
       
    		if(start != min) {
    			swap(numbers.at(start), numbers.at(min));
       
    			if(start == max) {
    				max = min;
    			}
    		}
       
    		if(end != max) {
    			swap(numbers.at(end), numbers.at(max));
    			break;
    		}
    	}
    }
    


삽입 정렬

  • k번째 원소를 1부터 k-1까지와 비교해 적절한 위치에 끼워넣고 그 뒤의 자료를 한 칸씩 뒤로 밀어내는 정렬
  • O(n^2)
  • C++ code
    void insertionSort(vector<int> &numbers) {
    	for(int i = 0 ; i < (int)numbers.size() - 1 ; i++) {
    		for(int j = i + 1 ; j >= 0 && numbers[j - 1] > numbers[j] ; j--) {
    			swap(numbers.at(j - 1), numbers.at(j));
    		}
    	}
    }
    


병합/합병 정렬

  • 원소 개수가 1 또는 0이 될 때까지 두 부분으로 쪼개고 쪼개서 자른 순서의 역순으로 크기를 비교해 병합해가는 정렬
  • 안전한 정렬
  • O(n log n)
  • C++ code
    void mergeSort(vector<int> &numbers, const int &start, const int &end) {
    	if(start >= end) {
    		return;
    	}
       
    	int middle = (start + end) / 2;
       
    	mergeSort(numbers, start, middle);
    	mergeSort(numbers, middle + 1, end);
       
    	vector<int> temp;
    	temp.clear();
    	int i = start, j = middle + 1;
    	while(i <= middle && j <= end) {
    		if(numbers.at(i) < numbers.at(j)) {
    			temp.push_back(numbers.at(i++));
    		} else {
    			temp.push_back(numbers.at(j++));
    		}
    	}
       
    	while(i <= middle) {
    		temp.push_back(numbers.at(i++));
    	}
       
    	while(j <= end) {
    		temp.push_back(numbers.at(j++));
    	}
       
    	for(int i = start ; i <= end ; i++) {
    		swap(numbers.at(i), temp.at(i - start));
    	}
    }
    


힙 정렬

  • 힙을 이용하여 정렬
  • O(n log n)


퀵 정렬

  • 원소 하나를 피봇으로 잡고 피봇을 기준으로 피봇보다 큰 값, 작은 값으로 나눈뒤 각각에 대해 다시 피봇을 잡아 나누어가는 정렬
  • O(n log n)
  • C++ code
    void quickSort(vector<int> &numbers, const int &left, const int &right) {
    	if(left >= right) {
    		return;
    	}
       
    	int pivot = (left + right) / 2;
       
    	int leftArrow = left;
    	int rightArrow = right;
    	bool leftDirection = true;
       
    	while(leftArrow <= rightArrow) {
    		if(leftDirection) {
    			if(numbers.at(leftArrow) >= numbers.at(pivot)) {
    				swap(numbers.at(leftArrow), numbers.at(pivot));
    				pivot = leftArrow;
    			}
    			++leftArrow;
    			leftDirection = false;
    		} else {
    			if(numbers.at(rightArrow) <= numbers.at(pivot)) {
    				swap(numbers.at(rightArrow), numbers.at(pivot));
    				pivot = rightArrow;
    			}
    			--rightArrow;
    			leftDirection = true;
    		}
    	}
       
    	quickSort(numbers, left, pivot - 1);
    	quickSort(numbers, pivot + 1, right);
    }
    


트리 정렬

  • 이진 탐색 트리를 만들어 정렬하는 방식
  • O(n log n)


카운팅 정렬

  • 각 항목의 개수를 이용하여 정렬하는 방식
  • 배열을 이용하므로 정수인 자료만 가능
  • 데이터의 최대값이 작다면 매우 효율적인 알고리즘
  • O(n + k)
    • k는 데이터의 최대값
  • C++ code
    void countingSort(vector<int> &numbers, const int maxSize) {
    	vector<int> counting(maxSize + 1);
       
    	for(auto &iter : numbers) {
    		counting[iter]++;
    	}
       
    	numbers.clear();
    	for(int i = 0 ; i < (int)counting.size() ; i++) {
    		if(counting.at(i) == 0) {
    			continue;
    		}
       
    		for(int j = 0 ; j < counting.at(i) ; j++) {
    			numbers.push_back(i);
    		}
    	}
    }