
선택 정렬은 목록의 정렬되지 않은 부분에서 가장 작은(또는 가장 큰) 요소를 반복적으로 선택하고 목록의 정렬된 부분으로 이동하여 작동하는 간단하고 효율적인 정렬 알고리즘이다.
목록의 정렬되지 않은 부분에서 가장 작은(또는 가장 큰) 요소를 반복적으로 선택하고 정렬되지 않은 부분의 첫 번째 요소와 스왑한다. 이 과정은 전체 목록이 정렬될 때까지 정렬되지 않은 나머지 부분에 대해 반복한다.





package selectionsort;
import arrayprinter.ArrayPrinter;
public class SelectionSort {
public static void sort(int array[]) {
int n = array.length;
for (int i = 0; i < n - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (array[minIndex] > array[j]) {
minIndex = j;
}
}
int tmp = array[minIndex];
array[minIndex] = array[i];
array[i] = tmp;
}
}
public static void main(String[] args) {
int[] arr = {5, 7, 4, 10, 2, 3, 9, 8, 6, 1};
sort(arr);
ArrayPrinter.print(arr);
}
}
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
삽입 정렬은 정렬되지 않은 목록의 각 요소를 목록의 정렬된 부분에 있는 올바른 위치에 반복적으로 삽입하여 작동하는 간단한 정렬 알고리즘이다.
손에 있는 카드패를 정리하는 것처럼 정렬되어 있지 않은 부분의 요소를 정렬되어 있는 목록의 올바른 위치에 삽입하여 정렬한다.

package insertionsort;
import arrayprinter.ArrayPrinter;
public class InsertionSort {
public static void sort(int[] array) {
int n = array.length;
for (int i = 1; i < n; i++) {
int target = array[i];
int j = i - 1;
while(j >= 0 && array[j] > target) {
array[j + 1] = array[j];
j--;
}
array[j + 1] = target;
}
}
public static void main(String args[]) {
int[] arr = {5, 7, 4, 10, 2, 3, 9, 8, 6, 1};
sort(arr);
ArrayPrinter.print(arr);
}
}
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
버블 정렬은 인접한 원소들이 순서가 틀릴 경우 반복적으로 스왑하는 방식으로 작동하는 가장 간단한 정렬 알고리즘이다.



package bubblesort;
import arrayprinter.ArrayPrinter;
public class BubbleSort {
public static void sort(int[] array) {
int n = array.length;
int tmp;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (array[j] > array[j + 1]) {
tmp = array[j];
array[j] = array[j + 1];
array[j + 1] = tmp;
}
}
}
}
public static void main(String[] args) {
int[] arr = {5, 7, 4, 10, 2, 3, 9, 8, 6, 1};
sort(arr);
ArrayPrinter.print(arr);
}
}
package bubblesort;
import arrayprinter.ArrayPrinter;
public class BubbleSort {
public static void sort(int[] array) {
int n = array.length;
int tmp;
boolean swapped;
for (int i = 0; i < n - 1; i++) {
swapped = false;
for (int j = 0; j < n - i - 1; j++) {
if (array[j] > array[j + 1]) {
tmp = array[j];
array[j] = array[j + 1];
array[j + 1] = tmp;
swapped = true;
}
}
if (!swapped) {
break;
}
}
}
public static void main(String[] args) {
int[] arr = {5, 7, 4, 10, 2, 3, 9, 8, 6, 1};
sort(arr);
ArrayPrinter.print(arr);
}
}
병합 정렬은 분할정복 접근법을 따르는 정렬 알고리즘이다. 입력 배열을 재귀적으로 더 작은 하위 배열로 나누고 그 하위 배열을 정렬한 다음 다시 병합하여 정렬된 배열을 얻는 방식으로 작동한다.
1. Divide
2. Conquer
3. Merge

package mergesort;
import arrayprinter.ArrayPrinter;
public class MergeSort {
public static void sort(int array[], int left, int right) {
if (left == right) {
return;
}
int mid = (left + right) / 2;
sort(array, left, mid);
sort(array, mid + 1, right);
merge(array, left, mid, right);
}
public static void merge(int array[], int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
int[] leftArray = new int[n1];
int[] rightArray = new int[n2];
for (int i = 0; i < n1; i++) {
leftArray[i] = array[left + i];
}
for (int i = 0; i < n2; i++) {
rightArray[i] = array[mid + 1 + i];
}
int leftIndex = 0;
int rightIndex = 0;
int targetIndex = left;
while (leftIndex < n1 && rightIndex < n2) {
if (leftArray[leftIndex] <= rightArray[rightIndex]) {
array[targetIndex] = leftArray[leftIndex];
leftIndex++;
} else {
array[targetIndex] = rightArray[rightIndex];
rightIndex++;
}
targetIndex++;
}
while (leftIndex < n1) {
array[targetIndex] = leftArray[leftIndex];
leftIndex++;
targetIndex++;
}
while (rightIndex < n2) {
array[targetIndex] = rightArray[rightIndex];
rightIndex++;
targetIndex++;
}
}
public static void main(String[] args) {
int[] arr = {5, 7, 4, 10, 2, 3, 9, 8, 6, 1};
sort(arr, 0, arr.length - 1);
ArrayPrinter.print(arr);
}
}
하나의 리스트를 피벗을 기준으로 두 개의 비균등한 크기로 분할하고 분할된 부분 리스트를 정렬한 다음, 두 개의 정렬된 부분 리스트를 합하여 전체가 정렬된 리스트가 되게 하는 방법이다.
1. Divide: 입력 배열을 피벗을 기준으로 비균등하게 2개의 부분 배열(피벗을 중심으로 왼쪽 = 피벗보다 작은 요소들, 오른쪽 = 피벗보다 큰 요소들)로 분할한다.
2. Conquer: 부분 배열을 정렬한다. 부분 배열의 크기가 충분히 작지 않으면 순환 호출을 이용하여 다시 분할 정복 방법을 적용한다.
3. Combine: 정렬된 부분 배열들을 하나의 배열에 합병한다.
package quicksort;
import arrayprinter.ArrayPrinter;
public class QuickSort {
public static void sort(int[] array) {
sort(array, 0, array.length - 1);
}
private static void sort(int[] array, int start, int end) {
if (start >= end) {
return;
}
int pivot = start;
int low = start + 1;
int high = end;
while (low <= high) {
while (low <= end && array[low] < array[pivot]) {
low++;
}
while (high > start && array[high] > array[pivot]) {
high--;
}
if (low < high) {
swap(array, low, high);
} else {
swap(array, high, pivot);
}
}
sort(array, start, high - 1);
sort(array, high + 1, end);
}
private static void swap(int[] array, int x, int y) {
int tmp = array[x];
array[x] = array[y];
array[y] = tmp;
}
public static void main(String args[]) {
int[] arr = {5, 7, 4, 10, 2, 3, 9, 8, 6, 1};
sort(arr);
ArrayPrinter.print(arr);
}
}
힙 정렬은 이진 힙 데이터 구조를 기반으로 한 비교 기반 정렬 방법이다.
주어진 입력 배열로 힙을 만든다.
힙에 요소가 하나만 포함될 때까지 다음 단계를 반복한다:
힙의 루트 요소(가장 큰 요소)를 힙의 마지막 요소와 스왑한다.
힙의 마지막 요소를 제거한다(지금 올바른 위치에 있음. last index 의 크기를 1 줄인다).
힙의 나머지 요소를 힙화한다.
Max Heap 을 구성하는 경우 오름차순으로 정렬.
Min Heap 을 구성하는 경우 내림차순으로 정렬.
package heapsort;
import arrayprinter.ArrayPrinter;
public class HeapSort {
public static void sort(int[] array) {
int size = array.length;
for (int i = size / 2 - 1; i >= 0; i--) {
heapify(array, size, i);
}
for (int i = size - 1; i > 0; i--) {
swap(array, 0, i);
heapify(array, i, 0);
}
}
private static void heapify(int[] array, int size, int i) {
int largest = i;
int left = i * 2 + 1;
int right = i * 2 + 2;
if (left < size && array[left] > array[largest]) {
largest = left;
}
if (right < size && array[right] > array[largest]) {
largest = right;
}
if (largest != i) {
swap(array, largest, i);
heapify(array, size, largest);
}
}
private static void swap(int[] array, int x, int y) {
int tmp = array[x];
array[x] = array[y];
array[y] = tmp;
}
public static void main(String args[]) {
int[] arr = {5, 7, 4, 10, 2, 3, 9, 8, 6, 1};
sort(arr);
ArrayPrinter.print(arr);
}
}
‘Donald L. Shell’이라는 사람이 제안한 방법으로, 삽입정렬을 보완한 알고리즘이다.
삽입 정렬이 어느 정도 정렬된 배열에 대해서는 대단히 빠른 것에 착안
정렬해야 할 리스트의 각 k번째 요소를 추출해서 부분 리스트를 만든다. 이때, k를 ‘간격(gap)’ 이라고 한다.
보통 간격을 n/2 로 줄이는데 n/3+1로 줄이는 것이 더 빠르다고 알려져있다.
package shellsort;
import arrayprinter.ArrayPrinter;
public class ShellSort {
public static void sort(int[] array) {
int size = array.length;
for (int gap = size / 2; gap > 0; gap = gap / 2) {
for (int i = gap; i < size; i++) {
int tmp = array[i];
int j;
for (j = i; j >= gap && array[j - gap] > tmp; j = j - gap) {
array[j] = array[j - gap];
}
array[j] = tmp;
}
}
}
public static void main(String[] args) {
int[] arr = {5, 7, 4, 10, 2, 3, 9, 8, 6, 1};
sort(arr);
ArrayPrinter.print(arr);
}
}