public void selectionSort(int arr[], int size) {
for (int i = 0 ; i < size -1 ; i++) {
int minIndex = i;
for (int j = i + 1 ; j < size ; i++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
swap(arr[i], arr[minIndex]); // 가장 작은 값과 위치를 바꾼다.
}
}
public void insertionSort(int arr[], int size) {
for(int i = 1 ; i < size ; i++) {
int target = arr[i];
int j = i - 1;
// 더 작지 않다면 비교할 필요가 없다.
while (j >= 0 && target < arr[j]) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = target; // 가장 마지막에 비교한 위치에 위치시킨다.
}
}
public void bubbleSort(int arr[], int size) {
for (int i = 0 ; i < size - 1; i++) {
for (int j = 0; j < size - 1 - i ; j++) {
// 인접한 두 값을 비교해서 자리를 바꾼다.
if (arr[j] > arr[j + 1]) {
swap(arr[j], arr[j+1]);
}
}
}
}
// 임시로 저장할 메모리가 필요하다.
int[] temp = new int[arr.length];
public void mergeSort(int[] arr, int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
// 중간 값을 기준으로 나눠 재귀적으로 수행한다.
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
// 나눠진 부분 집합을 합친다.
merge(arr, left, mid, right);
}
}
private void merge(int[] arr, int left, int mid, int right) {
int i = left; // 첫 번째 배열의 인덱스
int j = mid + 1; // 두 번재 배열의 인덱스
int k = left; // 임시 배열의 인덱스
// 임시 배열에 두 배열을 비교해서 더 작은 값을 저장한다.
while (i <= mid && j <= right) {
if (arr[i] <= arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
// 남아있는 값들을 임시 배열에 넣어준다.
while (i <= mid) {
temp[k++] = arr[i++];
}
while (j <= right) {
temp[k++] = arr[j++];
}
// 마지막으로 임시 배열을 원래 배열에 복사해준다.
for (int index = left; index < k; index++) {
arr[index] = temp[index];
}
}
public void heapSort(int[] arr) {
int n = arr.length;
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// 힙에서 요소 하나씩 꺼내어 배열의 뒤쪽부터 저장
for (int i = n - 1; i >= 0; i--) {
swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
private void heapify(int[] arr, int n, int i) {
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest]) {
largest = left;
}
if (right < n && arr[right] > arr[largest]) {
largest = right;
}
if (largest != i) {
swap(arr[i], arr[largest];
heapify(arr, n, largest);
}
}
public void quickSort(int[] arr, int left, int right) {
if (left < right) {
// 기준점(pivot)을 기준으로 배열을 나눈다.
int pivotIndex = partition(arr, left, right);
// 재귀적으로 정렬한다.
quickSort(arr, left, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, right);
}
}
private int partition(int[] arr, int left, int right) {
// 일반적으로 기준값(pivot)은 처음 혹은 마지막 값으로 정한다.
int pivot = arr[left];
int i = left + 1;
int j = right;
// 기준값보다 큰 값과 작은 값을 좌우로 나누는 과정
while (i <= j) {
while (i <= j && arr[i] <= pivot) {
i++;
}
while (i <= j && arr[j] > pivot) {
j--;
}
if (i < j) {
swap(arr[i], arr[j]);
}
}
// 기준값을 교차지점에 둔다.
swap(arr[left], arr[j]);
return j;
}
public void radixSort(int[] arr) {
int max = getMax(arr);
for (int exp = 1; max / exp > 0; exp *= 10) {
countSort(arr, exp);
}
}
private int getMax(int[] arr) {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
private void countSort(int[] arr, int exp) {
int n = arr.length;
int[] output = new int[n];
int[] count = new int[10];
for (int i = 0; i < n; i++) {
int digit = (arr[i] / exp) % 10;
count[digit]++;
}
for (int i = 1; i < 10; i++) {
count[i] += count[i - 1];
}
for (int i = n - 1; i >= 0; i--) {
int digit = (arr[i] / exp) % 10;
output[count[digit] - 1] = arr[i];
count[digit]--;
}
for (int i = 0; i < n; i++) {
arr[i] = output[i];
}
}

듀얼 피벗 퀵정렬은 기준값(pivot)이 두 개, 분할되는 영역이 3개인 퀵정렬 알고리즘이다.
시간복잡도는 좀더 개선된 O(nlog3n)이다.



팀 피터스가 만든 정렬 알고리즘이다. 파이썬의 표준 정렬 알고리즘이기도 하다.
삽입 정렬과 합병 정렬을 결합한 알고리즘이고, 시간복잡도는 O(nlogn)이다.
public int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}