버블 정렬
- 이웃한 두 요소의 대소 관계를 비교하고 필요에 따라 교환을 반복하는 알고리즘
장점
- 구현이 간단하다
단점
- 비교 작업이 많아 연산 시간이 오래 걸림
package bublleSort;
public class bubleSort {
static int cnt=0;
static int[] a=new int[] {1,3,9,4,7,8,6};
public static void main(String[] args) {
bubbleSort();
for(int i=0;i<a.length;i++) {
System.out.print(a[i]);
}
System.out.println();
System.out.println(cnt);
}
static public void swap(int[] a,int i,int j){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
static public void bubbleSort() {
for(int i=0;i<a.length;i++) {
for(int j=i+1;j<a.length;j++) {
cnt++;
if(a[i]>a[j]) {
swap(a,i,j);
}
}
}
}
}
위처럼 하면 정렬이 완료되어있어도 정렬이 중간에 중단하지 못하고 끝까지 작업을 계속 진행하기 때문에 비교 작업을 계속하게 됩니다.
그래서 최적화하려면 조건을 걸어 break를 시키는 것도 방법 중 하나입니다.
static public void bubbleSort() {
for(int i=0;i<a.length-1;i++) {
int flag=0;
for(int j=a.length-1;j>i;j--) {
cnt++;
if(a[j-1]>a[j]) {
swap(a,j-1,j);
flag++;//값이 변경되면 flag++
}
}
if(flag ==0) {//교환이 없었다는 뜻 = 정렬이 완료 되었다라는 뜻
break;
}
}
}
위 정렬로 하게 되면 비교 연산이 21이었던 게 비교 연산 횟수가 20번으로 줄어듭니다.
하지만 이것마저도 최선의 방법은 아닙니다. 최선의 방법은 마지막 교환한 요소의 인덱스 값을 기억하고 있는 것입니다.
static public void bubbleSort() {
for(int i=0;i<a.length-1;) {
int lastIndex=a.length-1;//마지막으로 요소를 교환한 위치
for(int j=a.length-1;j>i;j--) {
cnt++;
if(a[j-1]>a[j]) {
swap(a,j-1,j);
lastIndex=j;//교환한 마지막인덱스 값저장
}
}
i=lastIndex;//수행할 패스의 범위 제한
}
}
이 최적화 방법을 사용하게 되면 비교 연산이 12회밖에 진행되지 않는다. 버블 정렬을 사용하려면 위 방법처럼 최적화시켜서 사용하는 게 제일 좋다.
선택 정렬
선택 정렬은 가장 작은 요소를 맨 앞으로 이동하고, 두 번째 작은 요소를 맨 앞에서 두 번째로 이동하는 등의 작업을 반복하는 알고리즘
static void select() {
for(int i=0;i<a.length-1;i++) {
int min=i; //정렬되지않는 부분에서 제일작은 인덱스값 저장
for(int j=i+1;j<a.length;j++) {
if(a[min]>a[j]) {
min=j;// 제일 요소가 작은값이 min값
}
}
swap(a,i,min);//정렬 되지 않은 부분의 첫요소와 가장작은 요소를 교환
}
}

삽입 정렬
삽입 정렬은 선택한 요소를 그보다 더 앞쪽의 알맞은 위치에 삽입하는 작업을 반복하여 정렬하는 알고리즘입니다.
static void insertion() {
for(int i=1;i<a.length;i++) {
int temp=a[i];
int j;
for(j=i;j>0&&a[j-1]>temp;j--) {
a[j]=a[j-1];
}
a[j]=temp;
}
}
삽입 정렬 예시 영상
https://www.youtube.com/watch?v=EdIKIf9mHk0
위 3가지 단순 정렬의 시간 복잡도는 모두 O(n^2)
셸 정렬
shell sort은 삽입 정렬의 장점을 살리고 단점을 보완하여 좀 더 빠르게 정렬하는 알고리즘이다.
아래는 shell 정렬의 예시이다.
https://www.youtube.com/watch?v=CmPA7zE8mx0
아래는 코드로 구현한 것이다.
static void shellSort() {
int halfSize=a.length/2; //일정한 간격으로 두요소로 묶기 위해
for(;halfSize>0;halfSize/=2) {//간격을 좁혀 그룹의 수를 줄이면서 정렬 반복
for(int i=halfSize;i<a.length;i++) {
int temp=a[i];
int j;
for(j=i-halfSize;j>=0;j=j-halfSize) {// 그룹끼리 비교하기 위해
if(a[j]>temp) {
a[j+halfSize]=a[j];
}else {
break;
}
}
a[j+halfSize]=temp;
}
}
//printSort();
}
아래 사진은 내가 이해하려고 손 코딩으로 풀이한 것


혼자서 알고리즘을 생각하여 정렬을 만드는 게 너무 머리가 아프고 힘든 것 같다. 이 정렬에 익숙해져서 알고리즘을 외우고 이해하는 것이 필요할 것 같다. 손으로 일일이 풀이하면서 이해하도록 해야겠다
'자료구조and알고리즘' 카테고리의 다른 글
| [알고리즘] DFS 깊이우선탐색 미로찾기 (Queue로구현) (0) | 2022.07.15 |
|---|---|
| [알고리즘] BFS 너비우선탐색 (Stack으로 구현)미로 찾기 (0) | 2022.07.15 |
| [알고리즘] BFS 너비우선탐색 (Queue사용) 미로찾기 (0) | 2022.07.15 |
| [알고리즘] DFS 깊이 우선 탐색 (Stack 사용)미로 (0) | 2022.07.15 |
| [알고리즘] Stack 이해하기 직접만들기+ Stack<E>사용하기 (0) | 2022.07.14 |
댓글