728x90
반응형
1) 버블 정렬
시작 | 5 | 3 | 2 | 1 | 4 |
1회차 | 3 | 2 | 1 | 4 | 5 |
2회차 | 2 | 1 | 3 | 4 | 5 |
3회차 | 1 | 2 | 3 | 4 | 5 |
4회차 | 1 | 2 | 3 | 4 | 5 |
- 가장 기본적인 정렬 중 하나이다. 인접한 i번째 키와 i+1번째 키를 비교하여 교환한다.
- 즉 1, 2번째 키를 비교하고, 2,3번째 키를 비교하여 정렬한다.
- 이러한 방식은 자연스럽게 가장 큰 값을 가장 뒤로 정렬하게 된다.
- 시간복잡도는 평균과 최악 모두 n^2 으로 같으며, 사용 메모리는 n이다.
public class HelloWorld{
public static void main(String []args){
int[] nums = {2, 3, 6, 1, 4, 9, 10};
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
bubbleSort(nums);
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
}
public static void bubbleSort(int[] nums) {
for(int i=0; i<nums.length; i++) {
for(int j=0; j<nums.length - i - 1; j++) {
//0~7, 0~6, 0~5 ... 0~1
if(nums[j] > nums[j+1]) {
int tmp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = tmp;
}
}
}
}
}
2) 선택정렬
시작 | 5 | 3 | 2 | 1 | 4 |
1회차 | 1 | 3 | 2 | 5 | 4 |
2회차 | 1 | 2 | 3 | 5 | 4 |
3회차 | 1 | 2 | 3 | 5 | 4 |
4회차 | 1 | 2 | 3 | 4 | 5 |
- 순차적으로 가장 작은 원소를 찾아 앞에서부터 채워넣는다.
- 즉, 한 번 실행될 때마다 앞에서부터 한 레코드씩 정렬된다.
- 버블 정렬이 가장 큰 값을 차례대로 뒤로 보냈다면, 선택정렬은 가장 작은 값을 차례대로 앞으로 보낸다.
- 시간복잡도는 평균과 최악 모두 n^2 으로 같으며, 사용 메모리는 n이다.
public class HelloWorld{
public static void main(String []args){
int[] nums = {2, 3, 6, 1, 4, 9, 10};
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
selectiveSort(nums);
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
}
public static void selectiveSort(int[] nums) {
for(int i=0; i<nums.length - 1; i++) {
int min = Integer.MAX_VALUE;
int minLoc = 0;
for(int j=i; j<nums.length; j++) {
if(min > nums[j]) {
min = nums[j];
minLoc = j;
}
}
nums[minLoc] = nums[i];
nums[i] = min;
}
}
}
3) 삽입정렬
시작 | 5 | 3 | 2 | 1 | 4 |
1회차 | 3 | 5 | 2 | 1 | 4 |
2회차 | 2 | 3 | 5 | 1 | 4 |
3회차 | 1 | 2 | 3 | 5 | 4 |
4회차 | 1 | 2 | 3 | 4 | 5 |
- 하나의 배열을 i번째 까지의 배열과, i+1 이후의 배열로 나눈다.
- i번째까지의 배열은 반드시 정렬되어 있어야 하며, i+1번째 이후의 배열의 첫 원소를 앞의 배열에 편입시키며 i번째 배열을 정렬해나간다.
- 즉, 0과 1을 비교하여 0~1로 이루어진 배열을 만들고, 0~1과 2를 비교하여 0~2까지의 배열을 만드는 식으로 정렬한다
- 시간복잡도는 평균과 최악 모두 n^2 으로 같으며, 사용 메모리는 n이다.
public class HelloWorld{
public static void main(String []args){
int[] nums = {2, 3, 6, 1, 4, 9, 10};
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
insertionSort(nums);
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
}
public static void insertionSort(int[] nums) {
for(int i=1; i<nums.length; i++) {
int tmp = nums[i];
for(int j=0; j<i; j++) {
if(tmp < nums[j]) {
nums[i] = nums[j];
nums[j] = tmp;
tmp = nums[i];
}
}
}
}
}
4) 셸정렬
- 삽입정렬의 보완버전으로, 삽입정렬은 하나의 레코드의 위치가 수정될 때마다 뒤의 모든 레코드들이 한 칸씩 뒤로 밀려야 했다.
- 이를 보완하여 한 번에 여러 칸 이동을 시도하는 것이 셸 정렬이다.
- 간격(step, hop)을 정하고 행렬을 여러 개의 부파일로 나눠 삽입 정렬을 진행한다.
- 실행 시간은 O(n(log2n)^2), O(n^2)
5) 퀵정렬
- 분할정복 정렬 방법의 하나이다.
- 평균 수행시간이 비교에 의한 정렬 방법 중 가장 짧다.
- 배열의 한 원소를 피봇으로 선정하고, 이를 기준으로 두 개의 배열로 분리한다.
- 그리고 왼쪽 배열은 피봇보다 작은 값들로 구성하고, 오른쪽 배열은 큰 값들로 구성한다.
- 이러한 분할로 인한 변동이 없어질 때까지 계속한다.
- 평균 수행 시간은 O(n log2 n)이나, 정렬이 된 배열에 대해서는 O(n^2)의 복잡도를 보인다.
- 공간 복잡도는 O(log2 n)
- 피벗을 결정하는 방법은 랜덤으로 선정하거나 중위법 (왼쪽 끝, 중앙, 혹은 우측 끝을 선정)이 있다.
- 아래의 경우는 중위법 중 중앙의 것을 피벗으로 선정
public class HelloWorld{
public static void main(String []args){
int[] nums = {2, 3, 6, 1, 4, 9, 10};
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
quickSort(nums, 0, nums.length-1);
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
}
public static void quickSort(int[] nums, int start, int end) {
int left = start;
int right = end;
int pivot = nums[(start+end)/2];
while(left <= right) {
while(nums[left] < pivot) left++;
while(nums[right] > pivot) right--;
if(left <= right) {
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
left++;
right--;
}
}
//left를 start로 하여 다음 로테이션 실행
if(start < left-1) quickSort(nums, start, left-1);
if(left < end) quickSort(nums, left, end);
}
}
6) 힙정렬
- 완전 이진트리를 이용한 정렬 방법.
- 최대힙이란 상위 레벨 노드가 반드시 하위 레벨 노드보다 큰 숫자인 트리를 의미한다.
- 힙정렬은 힙을 만든 후 이를 통해 정렬하는 방법이다.
- 평균 수행 시간과 최악의 수행시간 모두 O(n log2 n)이다.
- PriorityQueue를 사용하면 쉽게 구현할 수 있다.
import java.util.PriorityQueue;
public class HelloWorld{
public static void main(String []args){
int[] nums = {2, 3, 6, 1, 4, 9, 10};
PriorityQueue<Integer> hp = new PriorityQueue<Integer>();
for(int i=0; i<nums.length; i++) {
System.out.print(nums[i] + " ");
hp.add(nums[i]);
}
System.out.println();
while(hp.size() != 0) System.out.print(hp.poll() + " ");
System.out.println();
}
}
- PriorityQueue를 사용하지 않은 경우의 코드는 다음과 같다.
public class HelloWorld{
public static void main(String []args){
int[] nums = {2, 3, 6, 1, 4, 9, 10};
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
heapSort(nums);
for(int i=0; i<nums.length; i++) System.out.print(nums[i] + " ");
System.out.println();
}
public static void heapSort(int[] nums) {
for (int i = nums.length / 2 - 1; i >= 0; i--) {
heapify(nums, nums.length, i);
}
for (int i = nums.length - 1; i > 0; i--) {
int tmp = nums[0];
nums[0] = nums[i];
nums[i] = tmp;
heapify(nums, i, 0);
}
}
public static void heapify(int[] nums, int n, int i) {
int parent = i; //부모노드
int left = i*2 + 1; //왼쪽자식
int right = i*2 + 2; //오른쪽 자식
if (left < n && nums[parent] < nums[left]) {
parent = left;
}
if (right < n && nums[parent] < nums[right]) {
parent = right;
}
if (i != parent) {
int tmp = nums[parent];
nums[parent] = nums[i];
nums[i] = tmp;
heapify(nums, n, parent);
}
}
}
728x90
반응형
'IT 지식 > 알고리즘' 카테고리의 다른 글
이진트리 (JAVA 코드 포함) (2) | 2024.02.26 |
---|---|
[알고리즘] DP (0) | 2021.10.26 |
[알고리즘] BFS와 DFS (0) | 2021.10.26 |