본문 바로가기
공부기록/알고리즘

Chapter 06-4. 정렬 알고리즘_단순 삽입 정렬

by 루팽 2024. 8. 16.

단순 삽입 정렬(straight insertion sort)

선택한 요소를 그보다 더 앞쪽의 알맞은 위치에 삽입하는 작업을 반복하는 정렬 알고리즘

  • 아직 정렬되지 않은 부분의 첫 번째 요소를 정렬한 부분의 알맞은 위치에 삽입
for (int i = 1; i < n; i++) {
	// tmp <- a[i]
	// a[0], ..., a[i-1]의 알맞은 곳에 tmp 삽입

	int j = i;
	int tmp = a[i];
	// 정렬된 열의 왼쪽 끝에 도달하거나, tmp보다 작거나 같은 key를 갖는 항목 a[j-1]을 발견할때까지 반복
	while(j > 0 && a[j-1] > tmp) {
		a[j] = a[j-1];
		j--;
	}
	a[j] = tmp;
}

 

단순 삽입 정렬

package ch06_4;

import java.util.Scanner;

// 단순 삽입 정렬
public class Ex01_insertionSort {
    // 단순 삽입 정렬
    static void insertionSort(int[] a, int n) {
        for (int i = 1; i < n; i++) {
            int j;
            int temp = a[i];

            for (j = i; j > 0 && a[j - 1] > temp; j--) {
                a[j] = a[j - 1];
            }
            a[j] = temp;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("단순 삽입 정렬");
        System.out.print("요솟수: ");
        int nx = scanner.nextInt();
        int[] x = new int[nx];

        for (int i = 0; i < nx; i++) {
            System.out.print("x[" + i + "]: ");
            x[i] = scanner.nextInt();
        }

        insertionSort(x, nx); // 배열 x를 단순 삽입 정렬

        System.out.println("오름차순으로 정렬했습니다.");
        for (int i = 0; i < nx; i++) {
            System.out.println("x[" + i + "] = " + x[i]);
        }
    }
}

 

단순 정렬의 시간 복잡도

세 가지 단순 정렬(버블, 선택, 삽입)의 시간 복잡도는 모두 O(n^2)으로 효율이 좋지 않음

 

단순 선택 정렬(교환 과정을 자세히 출력)

package ch06_4;

import java.util.Scanner;

// 단순 선택 정렬(교환 과정을 자세히 출력)
public class Ex02_selectionSortEx {
    // a[idx1]과 a[idx2]의 값을 교환
    static void swap(int[] a, int idx1, int idx2) {
        int t = a[idx1];
        a[idx1] = a[idx2];
        a[idx2] = t;
    }

    // 단순 선택 정렬
    static void selectionSort(int[] a, int n) {
        for (int i = 0; i < n - 1; i++) {
            int min = i; // 아직 정렬되지 않은 부분에서 가장 작은 요소의 인덱스를 저장
            for (int j = i + 1; j < n; j++) {
                if (a[j] < a[min]) {
                    min = j;
                }
            }
            for (int j = 0; j < n; j++) {
                // 바꿀 요소는 +, 위치는 *
                System.out.print((j == i) ? "  * " : (j == min) ? "  + " : "    ");
            }
            System.out.println();
            for (int j = 0; j < n; j++) {
                System.out.printf("%3d ", a[j]);
            }
            System.out.println("\\n");
            swap(a, i, min); // 아직 정렬되지 않은 부분의 첫 요소와 가장 작은 요소를 교환
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("단순 선택 정렬");
        System.out.print("요솟수: ");
        int nx = scanner.nextInt();
        int[] x = new int[nx];

        for (int i = 0; i < nx; i++) {
            System.out.print("x[" + i + "]: ");
            x[i] = scanner.nextInt();
        }

        selectionSort(x, nx); // 배열 x를 단순 선택 정렬

        System.out.println("오름차 순으로 정렬했습니다.");
        for (int i = 0; i < nx; i++) {
            System.out.println("x[" + i + "] = " + x[i]);
        }
    }
}
/*
단순 선택 정렬
요솟수: 4
x[0]: 2
x[1]: 9
x[2]: 6
x[3]: 1
  *           + 
  2   9   6   1 

      *       + 
  1   9   6   2 

          *     
  1   2   6   9 

오름차 순으로 정렬했습니다.
x[0] = 1
x[1] = 2
x[2] = 6
x[3] = 9
 */

 

단순 삽입 정렬(삽입 과정을 자세히 출력)

package ch06_4;

import java.util.Scanner;

// 단순 삽입 정렬(삽입 과정을 자세히 출력)
public class Ex03_insertionSortEx {
    // 단순 삽입 정렬
    static void insertionSort(int[] a, int n) {
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < n; j++) {
                System.out.printf("%3d ", a[j]);
            }
            System.out.println();

            int j;
            int temp = a[i];
            for (j = i; j > 0 && a[j - 1] > temp; j--) {
                a[j] = a[j - 1];
            }
            a[j] = temp;

            System.out.print(" ".repeat(4 * j));
            System.out.print(i != j ? "^-" : "  ");
            System.out.print("-".repeat(4 * (i - j)));
            System.out.println("+");
            System.out.printf("a[%d]의 %d을/를 a[%d]의 위치에 삽입하였습니다.\\n\\n", i, temp, j);
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("단순 삽입 정렬");
        System.out.print("요솟수: ");
        int nx = scanner.nextInt();
        int[] x = new int[nx];

        for (int i = 0; i < nx; i++) {
            System.out.print("x[" + i + "]: ");
            x[i] = scanner.nextInt();
        }

        insertionSort(x, nx); // 배열 x를 단순 삽입 정렬

        System.out.println("오름차순으로 정렬했습니다.");
        for (int i = 0; i < nx; i++) {
            System.out.println("x[" + i + "] = " + x[i]);
        }
    }
}
/*
단순 삽입 정렬
요솟수: 4
x[0]: 6
x[1]: 4
x[2]: 8
x[3]: 2
  6   4   8   2 
^-----+
a[1]의 4을/를 a[0]의 위치에 삽입하였습니다.

  4   6   8   2 
          +
a[2]의 8을/를 a[2]의 위치에 삽입하였습니다.

  4   6   8   2 
^-------------+
a[3]의 2을/를 a[0]의 위치에 삽입하였습니다.

오름차순으로 정렬했습니다.
x[0] = 2
x[1] = 4
x[2] = 6
x[3] = 8
 */

 

단순 삽입 정렬(보초법: 배열의 맨 앞 요소는 비어있음)

package ch06_4;

import java.util.Scanner;

// 단순 삽입 정렬(보초법: 배열의 맨 앞 요소는 비어있음)
public class Ex04_insertionSortCen {
    // 단순 삽입 정렬
    static void insertionSort(int[] a, int n) {
        for (int i = 2; i < n; i++) {
            int temp = a[0] = a[i];
            int j = i;
            for (; a[j - 1] > temp; j--) {
                a[j] = a[j - 1];
            }
            if (j > 0) {
                a[j] = temp;
            }
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("단순 삽입 정렬");
        System.out.print("요솟수: ");
        int nx = scanner.nextInt();
        int[] x = new int[nx + 1]; // 여분으로 1개 더 생성

        for (int i = 1; i <= nx; i++) { // x[1] ~ x[nx]에 입력받음
            System.out.print("x[" + i + "]: ");
            x[i] = scanner.nextInt();
        }

        insertionSort(x, nx + 1); // 배열 x를 단순 삽입 정렬

        System.out.println("오름차순으로 정렬하였습니다.");
        for (int i = 1; i <= nx; i++) {
            System.out.println("x[" + i + "] = " + x[i]);
        }
    }
}

 

이진 삽입 정렬

package ch06_4;

import java.util.Scanner;

// 이진 삽입 정렬
public class Ex05_binInsertionSort {
    // 이진 삽입 정렬
    static void binInsertionSort(int[] a, int n) {
        for (int i = 1; i < n; i++) {
            int key = a[i];
            int first = 0; // 검색범위 맨 앞의 인덱스
            int last = i - 1; // 검색번위 맨 끝의 인덱스
            int center; // 검색범위 중앙의 인덱스
            int insertion; // 삽입하는 위치의 인덱스

            do {
                center = (first + last) / 2;
                // 검색 성공
                if (a[center] == key) {
                    break;
                } else if (a[center] < key) {
                    first = center + 1;
                } else {
                    last = center - 1;
                }
            } while (first <= last);

            insertion = (first <= last) ? center + 1 : last + 1;

            for (int j = i; j > insertion; j--) {
                a[j] = a[j - 1];
            }
            a[insertion] = key;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("이진 삽입 정렬");
        System.out.print("요솟수: ");
        int nx = scanner.nextInt();
        int[] x = new int[nx];

        for (int i = 0; i < nx; i++) {
            System.out.print("x[" + i + "]: ");
            x[i] = scanner.nextInt();
        }

        binInsertionSort(x, nx);			// 배열 x를 이진삽입정렬

        System.out.println("오름차순으로 정렬하였습니다.");
        for (int i = 0; i < nx; i++)
            System.out.println("x[" + i + "] = " + x[i]);
    }
}

댓글