# ํž™ ์ •๋ ฌ (Heap Sort)

written by sohyeon, hyemin ๐Ÿ’ก


# 1. ํž™(Heap)์ด๋ž€?

ํž™(Heap)์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’๋“ค ์ค‘์—์„œ ์ตœ๋Œ“๊ฐ’์ด๋‚˜ ์ตœ์†Ÿ๊ฐ’์„ ๋น ๋ฅด๊ฒŒ ์ฐพ์•„๋‚ด๋„๋ก ๋งŒ๋“ค์–ด์ง„ ์ž๋ฃŒ ๊ตฌ์กฐ์ด๋‹ค.

์ฆ‰. ํž™(Heap)์€ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ํ‚ค ๊ฐ’์ด ์ž์‹ ๋…ธ๋“œ์˜ ํ‚ค ๊ฐ’๋ณด๋‹ค ํ•ญ์ƒ ํฐ(์ž‘์€) ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ๋ฅผ ๋งํ•œ๋‹ค.

# ์ตœ๋Œ€ ํž™(Max Heap)

๋ถ€๋ชจ ๋…ธ๋“œ์˜ ํ‚ค ๊ฐ’์ด ์ž์‹ ๋…ธ๋“œ์˜ ํ‚ค ๊ฐ’๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์€ ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ๋ฅผ ๋งํ•œ๋‹ค.

# ์ตœ์†Œ ํž™(Min Heap)

๋ถ€๋ชจ ๋…ธ๋“œ์˜ ํ‚ค ๊ฐ’์ด ์ž์‹ ๋…ธ๋“œ์˜ ํ‚ค ๊ฐ’๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€ ์™„์ „ ์ด์ง„ ํŠธ๋ฆฌ๋ฅผ ๋งํ•œ๋‹ค.

# ํž™์˜ ์š”์†Œ๋ฅผ ๋ฐฐ์—ด์— ์ €์žฅํ•˜๋Š” ๊ณผ์ •

9 => 7 => 6 => 5 => 4 => 3 => 2 => 2 => 1=> 3 ์™€ ๊ฐ™์ด ์ธ๋ฑ์Šค์˜ ๊ฐ’์„ 1์”ฉ ๋Š˜๋ฆฌ๋ฉด์„œ ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ์— ํž™์˜ ์š”์†Œ๋ฅผ ๋Œ€์ž…ํ•œ๋‹ค.

# ๋ถ€๋ชจ์™€ ์ž์‹์˜ ์ธ๋ฑ์Šค ๊ด€๊ณ„

1. ๋ถ€๋ชจ๋Š” a[(i-1)/2]
2. ์™ผ์ชฝ ์ž์‹์€ a[i*2+1]
3. ์˜ค๋ฅธ์ชฝ ์ž์‹์€ a[i*2+2]

# 2. ํž™ ์ •๋ ฌ์ด๋ž€?

ํž™ ์ •๋ ฌ(Heap Sort)์€ ๊ฐ€์žฅ ํฐ(์ž‘์€) ๊ฐ’์ด ๋ฃจํŠธ์— ์œ„์น˜ํ•˜๋Š” ํŠน์ง•์„ ์ด์šฉํ•˜๋Š” ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.

ํž™ ์ •๋ ฌ์€ ์„ ํƒ ์ •๋ ฌ์„ ์‘์šฉํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ฉฐ ํž™์—์„œ ๊ฐ€์žฅ ํฐ(์ž‘์€) ๊ฐ’์ธ ๋ฃจํŠธ๋ฅผ ๊บผ๋‚ด๊ณ  ๋‚จ์€ ์š”์†Œ์—์„œ ๋‹ค์‹œ ๊ฐ€์žฅ ํฐ(์ž‘์€) ๊ฐ’์„ ๊ตฌํ•ด์•ผ ํ•œ๋‹ค.
๋”ฐ๋ผ์„œ ๋ฃจํŠธ๋ฅผ ๊บผ๋‚ด๊ณ  ๋‚จ์€ ์š”์†Œ๋กœ ๋งŒ๋“  ํŠธ๋ฆฌ๋„ ํž™์˜ ํ˜•ํƒœ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ์žฌ๊ตฌ์„ฑํ•ด์•ผ ํ•œ๋‹ค.


# 3. ๋™์ž‘ ๋ฐฉ์‹

# ๋ฃจํŠธ๋ฅผ ์—†์• ๊ณ  ํž™ ์ƒํƒœ ์œ ์ง€ํ•˜๊ธฐ

1. ๋ฃจํŠธ๋ฅผ ๊บผ๋‚ธ๋‹ค.
2. ๋งˆ์ง€๋ง‰ ์š”์†Œ๋ฅผ ๋ฃจํŠธ๋กœ ์ด๋™ํ•œ๋‹ค.
3. ์ž๊ธฐ๋ณด๋‹ค ํฐ ๊ฐ’์„ ๊ฐ€์ง€๋Š” ์ž์‹ ์š”์†Œ์™€ ์ž๋ฆฌ๋ฅผ ๋ฐ”๊พธ๋ฉฐ ์•„๋ž˜์ชฝ์œผ๋กœ ๋‚ด๋ ค๊ฐ€๋Š” ์ž‘์—…์„ ๋ฐ˜๋ณตํ•œ๋‹ค. ์ด๋•Œ ์ž์‹์˜ ๊ฐ’์ด ์ž‘๊ฑฐ๋‚˜ ์žŽ์— ๋‹ค๋‹ค๋ฅด๋ฉด ์ž‘์—…์ด ์ข…๋ฃŒ๋œ๋‹ค.

# ํž™ ์ •๋ ฌ์˜ ๊ณผ์ •

1. ํž™์˜ ๋ฃจํŠธ(a[0])์— ์žˆ๋Š” ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ๊บผ๋‚ด ๋ฐฐ์—ด ๋งˆ์ง€๋ง‰ ์š”์†Œ(a[9])์™€ ๋ฐ”๊พผ๋‹ค. 
2. ๊ฐ€์žฅ ํฐ ๊ฐ’์„ a[9]๋กœ ์˜ฎ๊ธฐ๋ฉด a[9]๋Š” ์ •๋ ฌ์„ ๋งˆ์น˜๊ฒŒ ๋œ๋‹ค. ์•ž์—์„œ ์‚ดํŽด๋ณธ ์ˆœ์„œ๋Œ€๋กœ a[0]~a[8]์˜ ์š”์†Œ๋ฅผ ํž™์œผ๋กœ ๋งŒ๋“ ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ ๋‘ ๋ฒˆ์งธ๋กœ ํฐ ์š”์†Œ์ธ 9๊ฐ€ ๋ฃจํŠธ์— ์œ„์น˜ํ•˜๊ฒŒ ๋œ๋‹ค. ํž™์˜ ๋ฃจํŠธ a[0]์— ์žˆ๋Š” ๊ฐ€์žฅ ํฐ ๊ฐ’์ธ 9๋ฅผ ๊บผ๋‚ด ์•„์ง ์ •๋ ฌํ•˜์ง€ ์•Š์€ ๋ถ€๋ถ„์˜ ๋งˆ์ง€๋ง‰ ์š”์†Œ์ธ a[8]๊ณผ ๋ฐ”๊พผ๋‹ค.
3. ๋‘ ๋ฒˆ์งธ๋กœ ํฐ ๊ฐ’์„ a[8]๋กœ ์˜ฎ๊ธฐ๋ฉด a[8]~a[9]๋Š” ์ •๋ ฌ์„ ๋งˆ์น˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ a[0]~a[7]์˜ ์š”์†Œ๋ฅผ ํž™์œผ๋กœ ๋งŒ๋“ ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ ์„ธ ๋ฒˆ์งธ๋กœ ํฐ ์š”์†Œ์ธ 8์ด ๋ฃจํŠธ์— ์œ„์น˜ํ•˜๊ฒŒ ๋œ๋‹ค. ํž™์˜ ๋ฃจํŠธ a[0]์— ์žˆ๋Š” ๊ฐ€์žฅ ํฐ ๊ฐ’์ธ 8์„ ๊บผ๋‚ด ์•„์ง ์ •๋ ฌํ•˜์ง€ ์•Š์€ ๋ถ€๋ถ„์˜ ๋งˆ์ง€๋ง‰ ์š”์†Œ์ธ a[7]๊ณผ ๋ฐ”๊พผ๋‹ค.
  • ์ด ๊ณผ์ •์„ ์ ์šฉํ•˜๊ธฐ ์ „์— ๋ฐฐ์—ด์„ ํž™ ์ƒํƒœ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. ๋˜ํ•œ, ์ •๋ ฌ์„ ๋งˆ์น˜๊ฒŒ ๋œ๋‹ค๋ฉด, ์ •๋ ฌํ•˜์ง€ ์•Š์€ ๋ถ€๋ถ„์˜ ์š”์†Œ๋ฅผ ํž™์œผ๋กœ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค.

# 4. ํŠน์ง•

# 1) ์žฅ์ 

  • ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ์ข‹์€ ํŽธ์ด๋‹ค.
  • ํž™ ์ •๋ ฌ์ด ์œ ์šฉํ•  ๋•Œ๋Š” ์ „์ฒด ์ž๋ฃŒ๋ฅผ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๊ฐ€์žฅ ํฐ(์ž‘์€) ๊ฐ’ ์ผ๋ถ€๋งŒ ํ•„์š”ํ•  ๋•Œ์ด๋‹ค.

# 5. ์‹œ๊ฐ„๋ณต์žก๋„

  • ํž™ ํŠธ๋ฆฌ์˜ ์ „์ฒด ๋†’์ด๊ฐ€ ๊ฑฐ์˜ log2(n)(์™„์ „์ด์ง„ํŠธ๋ฆฌ)์ด๋ฏ€๋กœ ํ•˜๋‚˜์˜ ์š”์†Œ๋ฅผ ํž™์— ์‚ฝ์ž…ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ๋•Œ ํž™์„ ์žฌ์ •๋น„ํ•˜๋Š” ์‹œ๊ฐ„ log2(n)๋งŒํผ ์†Œ์š”๋œ๋‹ค.
  • ์š”์†Œ์˜ ๊ฐœ์ˆ˜๊ฐ€ n๊ฐœ์ด๋ฏ€๋กœ ์ „์ฒด์ ์œผ๋กœ O(nlog2(n))์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค.
T(n) = O(nlog2(n))

# 6. ํž™ ์ •๋ ฌ Java ์ฝ”๋“œ

# ex) ํž™ ์ •๋ ฌ ์˜ˆ์ œ

import java.util.Scanner;

// ํž™ ์ •๋ ฌ
class HeapSort {
    // ๋ฐฐ์—ด ์š”์†Œ a[id1]๊ณผ a[id2]์˜ ๊ฐ’์„ ๋ฐ”๊พผ๋‹ค.
    static void swap(int[] a, int id1, int id2) {
        int t = a[id1];
        a[id1] = a[id2];
        a[id2] = t;
}

    // a[left] ~ a[right]๋ฅผ ํž™์œผ๋กœ ๋งŒ๋“ ๋‹ค.
    static void downHeap(int[] a, int left, int right) {
        int temp = a[left];  // ๋ฃจํŠธ
        int child;           // ํฐ ๊ฐ’์„ ๊ฐ€์ง„ ๋…ธ๋“œ
        int parent;          // ๋…ธ๋“œ

        for(parent = left; parent < (right+1)/2; parent = child) {
            int cl = parent * 2 + 1;  // ์™ผ์ชฝ ์ž์‹
            int cr = cl + 1;          // ์˜ค๋ฅธ์ชฝ ์ž์‹
            child = (cr <= right && a[cr] > a[cl]) ? cr : cl; // ํฐ ๊ฐ’์„ ๊ฐ€์ง„ ๋…ธ๋“œ๋ฅผ ์ž์‹์— ๋Œ€์ž…
            if(temp >= a[child])
                break;
            a[parent] = a[child];
        }
        a[parent] = temp;
    }

    // ํž™ ์ •๋ ฌ
    static void heapSort(int[] a, int n) {
        for(int i = (n-1)/2; i>=0; i--)   // a[i]~a[n-1]๋ฅผ ํž™์œผ๋กœ ๋งŒ๋“ค๊ธฐ
            downHeap(a, i, n-1);

        for(int i = n-1; i>0; i--) {
            swap(a,0,i);   // ๊ฐ€์žฅ ํฐ ์š”์†Œ์™€ ์•„์ง ์ •๋ ฌ๋˜์ง€ ์•Š์€ ๋ถ€๋ถ„์˜ ๋งˆ์ง€๋ง‰ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
            downHeap(a, 0, i-1);   // a[0]~a[i-1]์„ ํž™์œผ๋กœ ๋งŒ๋“ ๋‹ค.
        }
    }

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

        System.out.println("ํž™ ์ •๋ ฌ");
        System.out.println("์š”์†Ÿ์ˆ˜ : ");
        int n = scan.nextInt();
        int[] x = new int[n];

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

        heapSort(x, n); // ๋ฐฐ์—ด x๋ฅผ ํž™ ์ •๋ ฌํ•œ๋‹ค. 

        System.out.println("์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ–ˆ์Šต๋‹ˆ๋‹ค.");
        for(int i = 0; i<n; i++)
            System.out.println("x["+i+"] = "+x[i]);
    }
}

# downHeap ๋ฉ”์„œ๋“œ

๋ฐฐ์—ด a ๊ฐ€์šด๋ฐ a[left]~a[right]์˜ ์š”์†Œ๋ฅผ ํž™์œผ๋กœ ๋งŒ๋“œ๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. a[left] ์ด์™ธ์—๋Š” ๋ชจ๋‘ ํž™ ์ƒํƒœ๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  a[left]๋ฅผ ์•„๋žซ๋ถ€๋ถ„์˜ ์•Œ๋งž์€ ์œ„์น˜๋กœ ์˜ฎ๊ฒจ ํž™ ์ƒํƒœ๋ฅผ ๋งŒ๋“ ๋‹ค.

# heapSort ๋ฉ”์„œ๋“œ

์š”์†Œ์˜ ๊ฐœ์ˆ˜๊ฐ€ n๊ฐœ์ธ ๋ฐฐ์—ด a๋ฅผ ํž™ ์ •๋ ฌํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.

1. downHeap ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฐ์—ด a๋ฅผ ํž™์œผ๋กœ ๋งŒ๋“ ๋‹ค.
2. ๋ฃจํŠธ์— ์žˆ๋Š” ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ๋นผ๋‚ด์–ด ๋ฐฐ์—ด ๋งˆ์ง€๋ง‰ ์š”์†Œ์™€ ๋ฐ”๊พธ๊ณ  ๋ฐฐ์—ด์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ ๋‹ค์‹œ ํž™์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•˜์—ฌ ์ •๋ ฌ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. 

# Reference & Additional Resources

Last Updated: 12/5/2020, 11:36:44 AM