[자료구조] 우선순위 큐 Priority Queue

2022. 6. 8. 14:02·CS/자료구조

08 우선순위 큐 Priority Queue

출처

  • C언어로 쉽게 풀어쓴 자료구조(천인국, 공용해, 하상호 저)

 


목차

  1. 우선순위 큐의 개념

      1-1. 우선순위 큐란

      1-2. 우선순위 큐의 기능

      1-2. 우선순위 큐의 표현방법

 

  1. 히프

      2-1. 히프란?

      2-2. 배열을 이용한 구현

      2-3. 히프를 통한 구현

 

  1. 우선순위 큐 응용

      3-1. 히프 정렬

      3-2. 머신 스케줄링

      3-3. 허프만 코드




1. 우선순위 큐의 개념

 


1-1. 우선순위 큐란?

 

우선순위 큐(Priority Queue)는 우선순위를 가진 항목들을 저장하는 큐로 FIFO(First In First Out) 순서가 이닌 순위가 높은 데이터가 먼저나가는 자료구조를 말한다.

 

  • 스택 큐, 우선순위 큐 비교
자료구조 우선 삭제되는 요소
스택 가장 최근에 들어온 데이터
큐 가장 먼저 들어온 데이터
우선순위 큐 가장 우선순위가 높은 데이터

 

우선순위 큐는 시뮬레이션 시스템, 네트워크의 트래픽 제어, 운영체제 작업스케줄링 등에 사용된다.

 


1-2. 우선순위 큐의 기능

 

우선 순위 큐의 추상 자료형(ADT)를 살펴보자.

·객체: n개의 element형의 우선 순위를 가진 요소들의 모임

·연산: 
▪ create() ::= 우선순위큐를 생성한다.
▪ init(q) ::= 우선순위큐 q를 초기화한다.
▪ is_empty(q) ::= 우선순위큐 q가 비어있는지를 검사한다. 
▪ is_full(q) ::= 우선순위큐 q가 가득 찼는가를 검사한다.
▪ insert(q, x) ::= 우선순위큐 q에 요소 x를 추가한다.
▪ delete(q) ::= 우선순위큐로부터 가장 우선순위가 높은 요소를 삭제하고 이 요소를 반환한다.
▪ find(q) ::= 우선순위가 가장 높은 요소를 반환한다.

 

위 기능 중에서 가장 중요한 연산은 insert(삽입) 연산과 delete(삭제) 연산이다. 삽입, 삭제의 우선순위를 어떻게 정하느냐에 따라 최소 우선순위 큐와 최대 우선순위 큐로 분류를 나눌 수 있다.




1-3. 우선순위 큐의 표현방법

 

우선순위 큐를 구현하는 방법은 아래와 같다.

  1. 배열을 이용한 우선순위 큐
  2. 연결리스트를 이용한 우선순위 큐
  3. 히프(heap)를 이용한 우선수위 큐

 

  • 시간복잡도 비교
표현방법 삽 입 삭 제
  순서없는 배열     O(1)     O(n)  
  순서없는 연결 리스트     O(1)     O(n)  
  정렬된 배열     O(n)     O(1)  
  정렬된 연결 리스트     O(n)     O(1)  
  히프     O($log_2{n}$)     O($log_2{n}$)  

시간 복잡도에서 히프가 유리하다는 것을 알 수 있다.

 


2. 히프

 


2-1. 히프란?

 

히프(heap)는 뭔가가 쌓여있는 '더미' 모습과 비슷하며 붙여진 이름으로, 완전이진트리를 기반으로 하고 있다. 기본적으로 노드의 키들은 아래의 식을 만족한다.(최대 히프)

$$ 부모노드의; key\quad\geqq\quad 자식노드의 key; $$

 

또한 히프트리는 중복된 값을 허용할 수 있다. 히프는 우선순위 큐와 마찬가지로 우선순위의 기준에 따라 종류가 나뉜다.

  • 최대 히프(max heap): $ 부모노드의; key\quad\geqq\quad 자식노드의 key; $
  • 최소 히프(min heap): $ 부모노드의; key\quad\geqq\quad 자식노드의 key; $

 

n 개의 노드를 가지고 있는 히프의 높이 h는 $log_2{n}$ 과 같다

 
cf) 주의사항!! 자료구조 Heap과 메모리 영역인 Heap은 완전히 다른 개념이다!!

 


2-2. 배열을 이용한 구현

 

히프는 완전이진트리이므로 각 노드에 번호를 붙일 수 있다. 이 번호를 배열의 인덱스라고 생각하고 구현을 하면 된다.

배열로 히프를 구현하면, 부모노드와 자식노드를 찾는 것이 굉장히 쉽다. 이 방식은 아래와 같은 원리를 따른다.

  • 왼쪽 자식의 인덱스 = (부모의 인덱스)*2
  • 오른쪽 자식의 인덱스 = (부모의 인덱스)*2 + 1
  • 부모의 인덱스 = (자식의 인덱스)/2

 

히프는 아래와 같이 정의할 수 있다.

#define MAX_ELEMENT 200

typedef struct {
   int key;
} element;

typedef struct {
   element heap[MAX_ELEMENT];
   int heap_size;
} HeapType;

HeapType heap;             // 정적 메모리 할당 사용
HeapType *heap = create(); // 동적 메모리 할당 사용

 

히프에서 가장 중요한 연산은 삽입연산과 삭제연산이다. 자세한 설명은 아래와 같다.

  • 삽입 연산(upheap)
    1. 히프에 새로운 요소가 들어 오면, 일단 새로운 노드를 히프의 마지막 노드에 이어서 삽입
    2. 삽입 후에 새로운 노드를 부모 노드들과 교환해서 히프의 성질을 만족

 

  • 삭제 연산(downheap)
    1. 루트 노드를 삭제
    2. 마지막 노드를 루트 노드로 이동
    3. 루트에서부터 단말 노드까지의 경로에 있는 노드들을 교환하여 히프 성질을 만족

 

히프 코드: 링크




3. 우선순위 큐 응용

 


3-1. 히프 정렬

 

히프를 이용해 정렬을 하는 방법이다. 정렬할 요소들을 최대힙에 삽입한 다음, 한 번에 하나씩 요소를 히프에서 삭제해서 배열에 저장하면 내림차순으로 저장할 수 있다. 여기서 거꾸로 뒤집으면 오름차순으로 표현할 수 있다. 일반적으로 최소힙을 사용하면 오름차순으로 정렬할 수 있다.

 

삽입하거나, 삭제할 때 시간 복잡도가 O($\log{n}$)만큼 소요되고 요소의 개수가 n개이므로 전체적인 시간 복잡도는 O($n\log{n}$)이다. 히프 정렬이 유용히 쓰이는 경우는 가장 큰 값 혹은 작은 값 몇개만 필요할 때이다. (ex- top 10 등)

 

히프 정렬 코드: 링크

 


3-2. 머신 스케줄링

 

만약 어떤 작업을 처리하는 기계가 m개 존재하고 처리할 작업이 n개 존재하면 이 m개의 기계들로 최소의 시간안에 작업들을 모두 끝내는 것이 가장 효율적일 것이다. 이 문제에 대해 최적의 해를 구하는 것은 매우 어렵지만 근사 해는 우선순위 큐를 활용하여 쉽게 찾을 수 있다.

 

아래 코드는 여러 스케줄링 기법 중 가장 긴 작업을 우선적으로 기계에 할당하는 LPT(Longest Processing Time first)방식이다. 기계가 꽉 찼을 때는 Job을 할당하지 않다가 비는대로 남은 Job 중 제일 긴 것을 할당한다.

 

머신 스케줄링 코드: 링크

 


3-3. 허프만 코드

 

아래와 같은 빈도수를 가진 문자 5개를 3개의 고정 비트(총 8개의 문자 표현 가능)를 이용해 고유값을 각각 할당하면 아래와 같을 것이다.

글자 비트 코드 빈도수 총 비트 수
e 000 15 3 * 15 = 45
t 001 12 3 * 12 = 36
n 010 8 3 * 8 = 24
i 011 6 3 * 6 = 18
s 100 4 3 * 4 = 12
합계     135

총 135비트가 쓰인다. 위의 경우는 글자수가 별로 없지만 만약 글자 수가 엄청나게 많다면, 압축의 과정은 필수적일 것이다. 이 때 사용하는 것이 허프만 코드이다. 허프만 코드의 알고리즘은 메시지의 모든 글자를 카운트해 빈도수를 구하고, 빈도수에 따라 트리를 만든다. 최소힙을 이용해 빈도가 가장 적은 트리 2개씩 묶어 하나의 트리가 될 때가지 합친다. 그 과정은 아래의 그림과 같다.

트리가 완성되면 각 글자에 대한 코드를 비트로 만들 수 있다. 해당 글자로 가는 경로를 센다. 위 그림은 왼쪽에 가중치를 1을 두고, 오른쪽에 0을 뒀지만, 둘을 바꿔 반대로 할 수도 있다. 위 트리를 통해 만든 비트체계는 아래와 같다.

글자 트리로 만든 비트 코드 빈도수 총 비트 수
e 00 15 30
t 01 12 24
n 11 8 16
i 100 6 18
s 101 4 12
합계     88

135 - 85 = 50(비트)를 아낄 수 있다. 위의 경우, 약 37%의 용량을 아낄 수 있었다.

 

허프만 코드: 링크




'CS/자료구조' 카테고리의 다른 글
  • [자료구조] 그래프 - 최소 신장 트리(MST)와 최단경로
  • [자료구조] 그래프와 탐색 DFS BFS
  • [자료구조] 트리 Tree
  • [자료구조] 연결리스트 Linked List 2
gakko
gakko
좌충우돌 개발기
  • gakko
    MYVELOP 마이벨롭
    gakko
  • 전체
    오늘
    어제
    • 분류 전체보기 (203)
      • Spring (23)
        • Spring (10)
        • Spring Boot (7)
        • Spring Security (1)
        • Hibernate (4)
      • Test (3)
      • 끄적끄적 (6)
      • 활동 (35)
        • 부스트캠프 (23)
        • 동아리 (3)
        • 컨퍼런스 (3)
        • 글또 (5)
        • 오픈소스 컨트리뷰션 (1)
      • 디자인패턴 (0)
      • Git & GitHub (22)
        • Git (13)
        • Github Actions (1)
        • 오류해결 (5)
        • 기타(마크다운 등) (3)
      • 리눅스 (6)
        • 기초 (6)
        • 리눅스 서버 구축하기 (0)
      • Infra (2)
        • Docker (1)
        • Elastic Search (0)
        • Jenkins (1)
        • AWS (1)
      • MySQL (7)
        • 기초 (6)
        • Real MySQL (1)
      • 후기 (3)
        • Udemy 리뷰 (3)
      • CS (26)
        • 웹 기본지식 (0)
        • 자료구조 (13)
        • 운영체제 OS (12)
        • 데이터베이스 (1)
        • 시스템 프로그래밍 (0)
        • 기타 (0)
      • Tools (1)
        • 이클립스 (1)
        • IntelliJ (0)
      • 프로젝트 (1)
        • 모여모여(부스트캠프) (1)
      • JAVA (32)
        • Maven (6)
        • 오류해결 (11)
        • 자바 클래스&메소드 (1)
        • JSP & Servlet (12)
      • Javascript (5)
        • 기초 (3)
        • React (2)
      • Python (28)
        • 파이썬 함수 (9)
        • 알고리즘 문제풀이 (16)
        • 데이터 사이언스 (2)
        • 웹 크롤링 (1)
      • 단순정보전달글 저장소 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 우진님
  • 공지사항

  • 인기 글

  • 태그

    스프링부트
    운영체제
    부스트캠프 7기
    MySQL
    jsp
    파이썬
    os
    오류해결
    자바
    Git
    스프링
    부스트캠프 멤버십
    웹개발
    Python
    java
    부스트캠프
    알고리즘
    GitHub
    Spring
    자바스크립트
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.0
gakko
[자료구조] 우선순위 큐 Priority Queue
상단으로

티스토리툴바