πŸ€ Knowledge/μ•Œκ³ λ¦¬μ¦˜

[μ•Œκ³ λ¦¬μ¦˜] μž‘μ—… μŠ€μΌ€μ€„λ§ μ•Œκ³ λ¦¬μ¦˜(JobScheduling) & ν—ˆν”„λ§Œ μ••μΆ•(Huffman)

TIlearn 2023. 12. 3. 14:45

* 곡뢀λ₯Ό ν•˜λ©° μ •λ¦¬ν•œ κΈ€μž…λ‹ˆλ‹€. μˆ˜μ •ν•  점이 μžˆλ‹€λ©΄ λŒ“κΈ€ λ‚¨κ²¨μ£Όμ„Έμš”.

 

 

 

 

μž‘μ—… μŠ€μΌ€μ€„λ§μ΄λž€?

 

 

μ•Œκ³ λ¦¬μ¦˜ 문제λ₯Ό 풀닀보면 μ‹œμž‘ μ‹œκ°„κ³Ό μ’…λ£Œ μ‹œκ°„μ΄ μ§€μ •λœ μ–΄λ– ν•œ μž‘μ—…λ“€μ„ μˆ˜ν–‰ν•˜λŠ” λ¬Έμ œμ— 마주칠 λ•Œκ°€ μžˆλ‹€. μ΄λ•Œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œ μ •λ ¬μ΄λ‚˜ λ§΅ 같은 자료ꡬ쑰λ₯Ό μ“°λ©΄ 될 것 같은데.. 막상 κ΅¬ν˜„ν•΄λ³΄λ©΄ 쉽지 μ•Šμ„ 것이닀.

 

 

 

 

λ”°λΌμ„œ μ΄λŸ¬ν•œ 문제 μœ ν˜•μ— λŒ€ν•΄μ„œλŠ” μ–΄λŠμ •λ„ 틀을 κ°€μ§€κ³  ν‘ΈλŠ” 것이 μ’‹λ‹€. μ§€κΈˆκΉŒμ§€ λ‚΄κ°€ λ³Έ λ°”λ‘œλŠ” κ²°κ΅­ κ·Έ ν‹€ λ‚΄μ—μ„œ 크게 λ²—μ–΄λ‚˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.

 

 

 

 

κ·Έλž˜μ„œ μž‘μ—… μŠ€μΌ€μ€„λ§μ΄ 무엇인가 ν•˜λ©΄, λͺ¨λ“  μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” λ¬Έμ œμ΄λ‹€. λ¬Όλ‘  κ·Έλƒ₯ μˆ˜ν–‰ν•˜λŠ” 것이 μ•„λ‹ˆλΌ ν•΄λ‹Ή μž‘μ—…λ“€μ˜ μˆ˜ν–‰ μ‹œκ°„μ΄ λ’€μ£½λ°•μ£½ μ„žμ΄μ§€ μ•Šκ³  μ΅œμ†Œν•œμœΌλ‘œ 기계λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€. 기계가 μ•„λ‹ˆμ–΄λ„ κ°•μ˜μ‹€ 배치, 컴퓨터 λ“± μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆλŠ” μˆ˜ν–‰ 주체면 λͺ¨λ‘ κ°€λŠ₯ν•˜λ‹€.

 

 

 

 

λ‹€μ‹œλ§ν•΄, μž‘μ—… μŠ€μΌ€μ€„λ§μ€ 각 μž‘μ—…μ— μ‹œμž‘μ‹œκ°„, μ’…λ£Œ μ‹œκ°„μ΄ μ‘΄μž¬ν• λ•Œ μ΅œμ†Œν•œμ˜ 기계(κ°•μ˜μ‹€, 컴퓨터...)λ₯Ό μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” 것이닀.

 

 

 

자 이제, μž‘μ—… μŠ€μΌ€μ€„λ§μ΄ 무슨 μ•Œκ³ λ¦¬μ¦˜μΈμ§€λŠ” λŒ€μΆ© μ•Œκ² κ³ , μ–΄λ–»κ²Œ ν•΄μ•Ό 졜적의 ν•΄λ₯Ό 보μž₯ν•  수 μžˆμ„ μ§€ 생각해야 ν•œλ‹€. μ—¬κΈ°μ„œ λ§ν•˜λŠ” 졜적의 ν•΄λž€, μ΅œμ†Œν•œμ˜ κΈ°κ³„λ‘œ λͺ¨λ“  μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŒμ„ λ§ν•œλ‹€.

 

 

 

κ·ΈλŸ¬ν•œ λ°©λ²•μœΌλ‘œλŠ” 크게 λ„€ κ°€μ§€ 정도가 μžˆλ‹€.

 

1️⃣ λΉ λ₯Έ μ‹œμž‘μ‹œκ°„ μž‘μ—… μš°μ„ (Earliest start time first) λ°°μ •

 

2️⃣ λΉ λ₯Έ μ’…λ£Œμ‹œκ°„ μž‘μ—… μš°μ„ (Earliest finish time first) λ°°μ •

 

3️⃣ 짧은 μž‘μ—… μš°μ„ (Shortest job first) λ°°μ •

 

4️⃣ κΈ΄ μž‘μ—… μš°μ„ (Longest job first) λ°°μ •

 

 

이 μ€‘μ—μ„œ κ°€μž₯ 많이 μ‚¬μš©ν•˜λŠ” 것은 1번의 κ²½μš°μ΄λ‹€. μ΅œμ ν•΄λ₯Ό μ™„μ „ν•˜κ²Œ 보μž₯ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ΄ 1λ²ˆλ°–μ— μ—†κΈ° λ•Œλ¬Έμ΄λ‹€. λ¬Όλ‘  상황에 λ”°λΌμ„œ μ΅œμ ν•΄λ₯Ό 보μž₯ν•˜μ§€ μ•Šλ”λΌλ„ μ‚¬μš©ν•΄μ•Όλ§Œ ν•˜λŠ” λ•Œλ„ 있긴 ν•  κ²ƒμ΄μ§€λ§Œ 자주 μ‚¬μš©ν•˜μ§€λŠ” μ•ŠλŠ”λ‹€.

 

 

 

 

 

 

 

 

 

 

 

 

μž‘μ—… μŠ€μΌ€μ€„λ§μ˜ μˆ˜λ„ μ½”λ“œ(Pseudo Code)

 

 

 

 

λ‹€μŒμœΌλ‘œ μ‚΄νŽ΄λ³Ό 것은 μ˜μ‚¬ μ½”λ“œμ΄λ‹€. κ·Έ 둜직만 μΆ©λΆ„νžˆ νŒŒμ•…ν•˜κ³  μžˆλ‹€λ©΄ μ–΄λ– ν•œ 언어라도 μ‰½κ²Œ μ μš©ν•  수 μžˆμ„ 것이닀.

 

μž…λ ₯ : n 개의 μž‘μ—…(t1 ~ tn)
좜λ ₯ : 각 기계에 λ°°μ •λœ μž‘μ—… μˆœμ„œ

μ‹œμž‘ μ‹œκ°„μœΌλ‘œ μ •λ ¬ν•œ μž‘μ—… 리슀트: L(μ˜€λ¦„ 차순 μ •λ ¬)
whlie L이 λΉ„μ–΄μžˆμ§€ μ•Šλ‹€λ©΄
    Lμ—μ„œ κ°€μž₯ 이λ₯Έ μ‹œμž‘ μ‹œκ°„ μž‘μ—… tiλ₯Ό κ°€μ Έμ˜¨λ‹€.
    if tiλ₯Ό μˆ˜ν–‰ν•  수 μžˆλŠ” 기계가 μžˆλ‹€λ©΄
        tiλ₯Ό μˆ˜ν–‰ν•  수 μžˆλŠ” 기계에 λ°°μ •ν•œλ‹€.
    else
        μƒˆ 기계에 tiλ₯Ό λ°°μ •ν•œλ‹€.
    tiλ₯Ό Lμ—μ„œ μ œκ±°ν•œλ‹€.
return 각 기계에 λ°°μ •λœ μž‘μ—… μˆœμ„œ

 

 

 

 

μž‘μ—…λ“€μ„ μ •λ ¬ν•˜κ³ , 각 μž‘μ—… μ‹œκ°„λŒ€λ₯Ό μ²˜λ¦¬ν•  수 μžˆλŠ” μ΅œμ†Œν•œμ˜ 기계λ₯Ό μ°Ύμ•„ λ°°μ •ν•˜λŠ” 것. 그것이 전뢀이긴 ν•˜λ‹€. 이 λ•Œλ¬Έμ— μ‹œκ°„ λ³΅μž‘λ„λ„ μ •λ ¬ μ‹œκ°„ O(nlogn)에 기계λ₯Ό μ°Ύκ³  while문으둜 μž‘μ—…μ„ λ°°μ •ν•˜λŠ” 과정인 O(mn)을 λ”ν•œ 값이닀.(O(nlogn) + O(mn)

 

 

μ•„λž˜λŠ” μž‘μ—… μŠ€μΌ€μ€„λ§μ˜ μˆ˜λ„ μ½”λ“œλ₯Ό Java둜 κ΅¬ν˜„ν•œ μ˜ˆμ‹œμ΄λ‹€. μˆ˜λ„ μ½”λ“œλ₯Ό μ‹€μ œ μ½”λ“œλ₯Ό κ΅¬ν˜„ν•˜λŠ” 과정도 봐둬야 λ‚˜μ€‘μ— 덜 νž˜λ“€ 수 μžˆλ‹€. ν•œ λ²ˆμ”© μ‚΄νŽ΄λ³΄μž.

 

더보기

πŸ“ μž‘μ—… μŠ€μΌ€μ€„λ§ μ½”λ“œ μ˜ˆμ‹œ(Java)

 

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Job {
    int id;
    int startTime;
    int endTime;

    public Job(int id, int startTime, int endTime) {
        this.id = id;
        this.startTime = startTime;
        this.endTime = endTime;
    }
}

public class JobScheduling {

    public static List<List<Job>> scheduleJobs(List<Job> jobs) {
        Collections.sort(jobs, Comparator.comparingInt(job -> job.startTime));

        int numMachines = 1;
        List<List<Job>> machineSchedule = new ArrayList<>();
        machineSchedule.add(new ArrayList<>(Arrays.asList(jobs.get(0))));

        for (int i = 1; i < jobs.size(); i++) {
            Job currentJob = jobs.get(i);
            boolean assigned = false;

            for (int j = 0; j < numMachines; j++) {
                List<Job> machine = machineSchedule.get(j);
                Job lastJob = machine.get(machine.size() - 1);

                if (currentJob.startTime >= lastJob.endTime) {
                    machine.add(currentJob);
                    assigned = true;
                    break;
                }
            }

            if (!assigned) {
                List<Job> newMachine = new ArrayList<>(Arrays.asList(currentJob));
                machineSchedule.add(newMachine);
                numMachines++;
            }
        }

        return machineSchedule;
    }

    public static void main(String[] args) {
        List<Job> jobs = new ArrayList<>();
        jobs.add(new Job(1, 7, 8));
        jobs.add(new Job(2, 3, 7));
        jobs.add(new Job(3, 1, 5));
        jobs.add(new Job(4, 5, 9));
        jobs.add(new Job(5, 0, 2));
        jobs.add(new Job(6, 6, 8));
        jobs.add(new Job(7, 1, 6));

        List<List<Job>> machineSchedule = scheduleJobs(jobs);

        for (int i = 0; i < machineSchedule.size(); i++) {
            System.out.println("Machine " + (i + 1));
            for (Job job : machineSchedule.get(i)) {
                System.out.println("Job " + job.id + " ("+job.startTime + "," + job.endTime + ")");
            }
        }
    }
}

 

 

πŸ”² class Job은 μ‹œμž‘ μ‹œκ°„, μ’…λ£Œ μ‹œκ°„, id 값을 κ°€μ§„λ‹€.

 

 

πŸ”² Comparatorλ₯Ό ν†΅ν•΄μ„œ μ‹œμž‘ μ‹œκ°„μ„ κΈ°μ€€μœΌλ‘œ μ˜€λ¦„μ°¨μˆœ μ •λ ¬ν•œλ‹€.

 

 

πŸ”² ν˜„μž¬ Job(currentJob)이 기쑴에 κ°€μ§€κ³  μžˆλŠ” machineλ“€λ‘œ μ²˜λ¦¬κ°€ κ°€λŠ₯ν•œ μ§€ μ•Œμ•„λ³Έλ‹€. 이 λ•Œ μ‹œκ°„λŒ€κ°€ κ²ΉμΉ˜λŠ” μ§€μ˜ 여뢀에 따라 κ°€λŠ₯ν•œμ§€ μ•„λ‹Œμ§€ 확인할 수 μžˆλ‹€. κ²°κ΅­μ—λŠ” 쀑볡이 μ—†μ–΄μ•Ό ν•œλ‹€λŠ” 것이 이 μž‘μ—… μŠ€μΌ€μ€„λ§μ˜ λͺ©μ μ΄κΈ° λ•Œλ¬Έμ΄λ‹€.

 

 

πŸ”² λ§Œμ•½ ν˜„μž¬ κ°€μ§€κ³  μžˆλŠ” machineλ“€λ‘œ μ²˜λ¦¬κ°€ λΆˆκ°€λŠ₯ν•˜λ‹€λ©΄, μƒˆλ‘œμš΄ newMachine을 λ§Œλ“€μ–΄μ„œ μ²˜λ¦¬ν•΄μ•Ό ν•œλ‹€.

 

 

 

 

 

 

 

 

 

 

 

 

 

ν—ˆν”„λ§Œ μ½”λ”©(HuffmanCoding)

 

 

μš°λ¦¬λŠ” 항상 λΉ λ₯Έ μ‹œκ°„, 그리고 쒋은 νš¨μœ¨μ„ μΆ”κ΅¬ν•œλ‹€. μ΄λŠ” μ„€λ Ή νŒŒμΌμ„ λˆ„κ΅°κ°€μ—κ²Œ μ „μ†‘ν•œλ‹€κ³  ν•  λ•Œλ„ λ§ˆμ°¬κ°€μ§€λ‘œ μ μš©λœλ‹€. λ§Œμ•½ μ „μ†‘ν•˜κ³ μž ν•˜λŠ” 파일의 크기λ₯Ό 쀄일 수 μžˆλ‹€λ©΄ λ©”λͺ¨λ¦¬ 곡간을 효율적으둜 μ‚¬μš©ν•  수 있으며, 파일 전솑 μ‹œκ°„λ„ ꡉμž₯히 μ§§μ•„μ§ˆ 것이닀.

 

 

 

이λ₯Ό μœ„ν•œ "파일 μ••μΆ•"의 기법에 μžˆμ–΄μ„œλŠ” λ‹€μ–‘ν•œ 방법듀이 μžˆμ§€λ§Œ, μš°λ¦¬λŠ” μ•Œκ³ λ¦¬μ¦˜μ μœΌλ‘œ μ ‘κ·Όν•˜κΈ° μ‰¬μš΄ "ν—ˆν”„λ§Œ μ••μΆ•"에 λŒ€ν•˜μ—¬ μ•Œμ•„λ³΄μž.

 

 

 

"ν—ˆν”„λ§Œ μ••μΆ•"의 큰 νŠΉμ§• 쀑 ν•˜λ‚˜λŠ” 접두뢀 νŠΉμ„±μ΄λΌλŠ” 것이닀. ν—ˆν”„λ§Œ μ••μΆ• 기법이 μ•„λ‹Œ λ‹€λ₯Έ μ••μΆ• 기법은 μ½”λ“œμ™€ μ½”λ“œ 사이λ₯Ό ꡬ뢄 μ§“κΈ° μœ„ν•΄ νŠΉλ³„ν•œ 문자λ₯Ό μ‚¬μš©ν•œλ‹€. 예λ₯Ό λ“€μ–΄ 101#10#1#111 λ“± #을 μ‚¬μš©ν•˜μ—¬ 각 μ½”λ“œλ₯Ό ꡬ뢄 μ§€μ—ˆλ‹€. 이와 달리 ν—ˆν”„λ§Œ μ½”λ“œλŠ” 각 λ¬Έμžμ— ν• λ‹Ήλœ 이진 μ½”λ“œκ°€ λ‹€λ₯Έ 문자의 ν• λ‹Ήλœ 이진 μ½”λ“œμ˜ 접두뢀가 λ˜μ§€ μ•ŠλŠ”λ‹€.

 

 

 

 

즉, ν—ˆν”„λ§Œ 압좕에 μžˆμ–΄μ„œλŠ” #κ³Ό 같이 ꡬ뢄을 μœ„ν•œ 문자의 ν•„μš”κ°€ μ—†λ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— 파일의 μ••μΆ•κ³Ό ν•΄μ œμ— μžˆμ–΄μ„œλ„ 별닀λ₯Έ μ½”λ“œκ°€ ν•„μš”ν•˜μ§€ μ•Šλ‹€.

 

 

 

 

κ·Έλ ‡λ‹€λ©΄ ν—ˆν”„λ§Œ 압좕은 μ–΄λ– ν•œ λ°©μ‹μœΌλ‘œ 압좕을 ν•˜λŠ” κ²ƒμΌκΉŒ? 여기에 μžˆμ–΄μ„œλŠ” 각 문자의 λΉˆλ„ μˆ˜μ— κΈ°λ°˜μ„ λ‘” 이진 트리λ₯Ό λ§Œλ“€μ–΄ 각 λ¬Έμžμ— 이진 μ½”λ“œλ₯Ό ν• λ‹Ήν•˜λŠ” 방법을 μ‚¬μš©ν•œλ‹€. μ΄λ ‡κ²Œ λ§Œλ“€μ–΄μ§„ 이진 μ½”λ“œλ₯Ό ν—ˆν”„λ§Œ μ½”λ“œλΌκ³  ν•œλ‹€.

 

 

 

 

 

 

 

 

 

 

 

ν—ˆν”„λ§Œ μ½”λ”©(HuffmanCoding)의 μˆ˜λ„ μ½”λ“œ(Pseudo code)

 

 

μž…λ ₯ : μž…λ ₯ 파일 n개의 λ¬Έμžμ— λŒ€ν•œ 각각의 λΉˆλ„ 수
좜λ ₯ : ν—ˆν”„λ§Œ 트리


각 문자 λ‹Ή λ…Έλ“œλ₯Ό λ§Œλ“€κ³ , κ·Έ 문자의 λΉˆλ„ 수λ₯Ό λ…Έλ“œμ— μ €μž₯ν•œλ‹€.
n λ…Έλ“œμ˜ λΉˆλ„ μˆ˜μ— λŒ€ν•΄ μš°μ„  μˆœμœ„ 큐λ₯Ό λ§Œλ“ λ‹€.

while Q에 μžˆλŠ” λ…Έλ“œ 수 >= 2
    λΉˆλ„ μˆ˜κ°€ κ°€μž₯ 적은 2개의 λ…Έλ“œ(A와 B)λ₯Ό Qμ—μ„œ μ œκ±°ν•œλ‹€.
    μƒˆ λ…Έλ“œ N을 λ§Œλ“€κ³ , A와 Bλ₯Ό N의 μžμ‹λ…Έλ“œλ‘œ λ§Œλ“ λ‹€.
    N의 λΉˆλ„ 수 = A의 λΉˆλ„ 수  + B의 λΉˆλ„ 수
    λ…Έλ“œ N을 Q에 μ‚½μž…ν•œλ‹€.

return Q

 

 

 

πŸ”² μš°μ„  μˆœμœ„ 큐λ₯Ό μ™œ λ§Œλ“œλŠ” κ°€?

 

λΉˆλ„ μˆ˜μ— λŒ€ν•œ 정렬을 ν•˜μ—¬μ•Ό 효율적인 ν—ˆν”„λ§Œ μ½”λ“œλ₯Ό λ§Œλ“€ 수 μžˆλ‹€. 예λ₯Ό λ“€μ–΄ AλΌλŠ” λ¬Έμžκ°€ BλΌλŠ” λ¬Έμžλ³΄λ‹€ λΉˆλ„ μˆ˜κ°€ λ§Žλ‹€κ³  ν•  λ•Œ, 이에 λŒ€ν•œ ν—ˆν”„λ§Œ μ½”λ“œλ₯Ό "1010"으둜 μ €μž₯ν•˜λŠ” 것보단 "10"으둜 μ €μž₯ν•˜λŠ” 것이 훨씬 μ’‹λ‹€.

 

즉, 정렬은 효율적인 ν—ˆν”„λ§Œ μ½”λ“œλ₯Ό λ§Œλ“œλŠ”λ° μžˆμ–΄ ν•„μˆ˜μ μΈ μš”μ†Œμ΄λ―€λ‘œ μš°μ„ μˆœμœ„ 큐λ₯Ό μ‚¬μš©ν•œλ‹€.

 

 

 

 

μ•„λž˜λŠ” ν—ˆν”„λ§Œ 코딩을 Java둜 κ΅¬ν˜„ν•œ μ˜ˆμ‹œμ΄λ‹€. μœ„μ˜ 둜직이 μ–΄λŠ λΆ€λΆ„μ—μ„œ μ‚¬μš©λ˜λŠ” μ§€ μ‚΄νŽ΄λ³΄μž.

 

 

더보기

πŸ“ ν—ˆν”„λ§Œ μ½”λ“œ μ˜ˆμ‹œ(Java)

 

import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Arrays;

class Entry {
    private int frequency;  // λΉˆλ„
    private String word;    // 문자 λ˜λŠ” 단어
    private Entry left;     // μ™Όμͺ½ μžμ‹ λ…Έλ“œ
    private Entry right;    // 였λ₯Έμͺ½ μžμ‹ λ…Έλ“œ
    private String code;    // Huffman μ½”λ“œ

    public Entry(int newFreq, String newValue, Entry l, Entry r, String s) {
        frequency = newFreq;
        word = newValue;
        left = l;
        right = r;
        code = s;
    }

    public int getKey() {
        return frequency;
    }

    public String getValue() {
        return word;
    }

    public String getCode() {
        return code;
    }

    public Entry getLeft() {
        return left;
    }

    public Entry getRight() {
        return right;
    }

    public void setCode(String newCode) {
        code = newCode;
    }
}


public class Huffman {
    private static Entry[] minHeap;
    private static int size;

    public Huffman(Entry[] entries, int n) {
        minHeap = new Entry[n + 1];
        size = 0;

        for (int i = 1; i <= n; i++) {
            minHeap[++size] = entries[i];
        }

    }

    public void createHeap() {
        // μ΅œμ†Œ νž™μœΌλ‘œ λ³€ν™˜
        for (int i = size / 2; i >= 1; i--) {
            minHeapify(i);
        }


    }

    public Entry createTree() {
        while (size >= 2) {
            Entry a = extractMin();
            Entry b = extractMin();

            Entry n = new Entry(a.getKey() + b.getKey(), "", a, b, "");

            insert(n);
        }

        return minHeap[1];
    }

    private void minHeapify(int i) {
        int left = 2 * i;
        int right = 2 * i + 1;
        int smallest = i;

        if (left <= size && minHeap[left].getKey() < minHeap[i].getKey()) {
            smallest = left;
        }

        if (right <= size && minHeap[right].getKey() < minHeap[smallest].getKey()) {
            smallest = right;
        }

        if (smallest != i) {
            swap(i, smallest);
            minHeapify(smallest);
        }
    }

    private Entry extractMin() {
        if (size < 1) {
            return null;
        }
        Entry min = minHeap[1];
        minHeap[1] = minHeap[size--];
        minHeapify(1);
        return min;
    }

    private void insert(Entry entry) {
        if (size >= minHeap.length - 1) {
            minHeap = Arrays.copyOf(minHeap, minHeap.length * 2);
        }
        minHeap[++size] = entry;

        int i = size;
        while (i > 1 && minHeap[i].getKey() < minHeap[i / 2].getKey()) {
            swap(i, i / 2);
            i = i / 2;
        }
    }

    private void swap(int i, int j) {
        Entry temp = minHeap[i];
        minHeap[i] = minHeap[j];
        minHeap[j] = temp;
    }

    public void preorder(Entry root) {
        if (root != null) {
            if (!root.getValue().isEmpty()) {
                System.out.print(root.getValue() + ": " + root.getCode() + " ");
            }
            preorder(root.getLeft());
            preorder(root.getRight());
        }
    }

    public static void print() {
        for (int i = 1; i <= size; i++) {
            System.out.print("[" + minHeap[i].getKey() + " " + minHeap[i].getValue() + "] ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Entry[] a = new Entry[7];
        a[1] = new Entry(60, "a", null, null, null);
        a[2] = new Entry(20, "b", null, null, null);
        a[3] = new Entry(30, "c", null, null, null);
        a[4] = new Entry(35, "d", null, null, null);
        a[5] = new Entry(40, "e", null, null, null);
        a[6] = new Entry(90, "f", null, null, null);

        Huffman h = new Huffman(a, 6);
        System.out.println("μ΅œμ†Œ νž™ λ§Œλ“€κΈ° μ „");
        print();

        h.createHeap();
        System.out.println("μ΅œμ†Œ νž™:");
        print();

        System.out.println("ν—ˆν”„λ§Œ μ½”λ“œ:");

        Entry root = h.createTree();
        h.generateHuffmanCodes(root, "");
        h.preorder(root);
        System.out.println();
    }

    public void generateHuffmanCodes(Entry root, String code) {
        if (root != null) {
            root.setCode(code);

            generateHuffmanCodes(root.getLeft(), code + "0");
            generateHuffmanCodes(root.getRight(), code + "1");
        }
    }
}

 

 

πŸ”² Entry ν΄λž˜μŠ€λŠ” Huffman Tree의 λ…Έλ“œλ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

 

πŸ”² EntryλŠ” 단어, λ‹¨μ–΄μ˜ λΉˆλ„μˆ˜, μ™Όμͺ½ μžμ‹, 였λ₯Έμͺ½ μžμ‹μ— λŒ€ν•œ 정보λ₯Ό κ°€μ§„λ‹€.

 

πŸ”² μ•žμ„  μ„€λͺ…μ—μ„œλŠ” μš°μ„  μˆœμœ„ 큐λ₯Ό ν†΅ν•΄μ„œ μ΅œμ†Œ 값을 μ°ΎλŠ”λ‹€κ³  ν•˜μ˜€μ§€λ§Œ, ν•΄λ‹Ή μ˜ˆμ œμ—μ„œλŠ” μ΅œμ†Œ νž™μ„ μ‚¬μš©ν•˜μ˜€λ‹€.

 

πŸ”² minHeapfy λ©”μ„œλ“œλ₯Ό ν†΅ν•΄μ„œ 자기 μžμ‹  λ…Έλ“œμ™€ μ™Όμͺ½, 였λ₯Έμͺ½ μžμ‹μ— λŒ€ν•΄ μ΅œμ†Œ 값을 μ°Ύμ•„ μƒμœ„ λ…Έλ“œλ‘œ μ§€μ •ν•œλ‹€.

 

πŸ”² extractMin λ©”μ„œλ“œλŠ” μ΅œμ†Œ 값을 λ½‘λŠ” ν•¨μˆ˜μ΄λ‹€. 

 

πŸ”² createTree λ©”μ„œλ“œμ—μ„œ λ‘κ°œμ˜ μ΅œμ†Œ κ°’ λ…Έλ“œλ₯Ό μ œκ±°ν•˜κ³ , μƒˆ λ…Έλ“œλ₯Ό λ§Œλ“€μ–΄ μ‚½μž…ν•œλ‹€.

 

 

 

 

 

 

πŸ”²  generateHuffmancodesλ₯Ό ν†΅ν•΄μ„œ ν—ˆν”„λ§Œ μ½”λ“œλ₯Ό 얻을 수 μžˆλ‹€. 루트 λ…Έλ“œλ‘œ λΆ€ν„° μž¬κ·€μ μœΌλ‘œ 탐색해 λ‚˜κ°€λ©°, μ½”λ“œλ₯Ό 뢙일 수 있으며 λ§ˆμ§€λ§‰ λ‹¨λ§λ…Έλ“œμ—μ„œ νšλ“ν•˜λŠ” μ½”λ“œκ°€ 각 문자의 ν—ˆν”„λ§Œ μ½”λ“œμž„μ„ μ•Œ 수 μžˆλ‹€.