자료구조실습 수업

[2주차 과제]

2022. 9. 18. 13:29

 

 

1. 우선순위 큐와 힙 내용 정리

● 우선순위 큐 (Priority Queue)

    - 우선순위를 가진 항목들을 저장하는 큐

    - 우선 순위가 높은 데이터가 먼저 나가게 됨

    - 가장 일반적인 큐라고 할 수 있으며, 스택이나 큐를 우선순위 큐로 구현할 수 있음

    - 시뮬레이션, 네트워크 트래픽 제어, OS의 작업 스케쥴링 등을 하는데 사용됨

    - 우선순위 큐 연산

        1) insert(item) : 우선순위 큐에 항목 item을 추가

        2) remove() : 우선순위 큐로부터 가장 우선순위가 높은 요소를 삭제하고 이 요소를 반환

        3) find() : 우선순위가 가장 높은 요소를 삭제하지 않고 반환

        4) isEmpty() : 우선순위 큐가 공백 상태인지를 검사

        5) isFull() : 우선순위 큐가 포화상태인지를 검사

        6) display() : 우선순위 큐의 모든 요소들을 출력

    - 우선순위 큐는 두가지로 구분: 최소 우선순위 큐, 최대 우선순위 큐

    - 우선순위 큐 구현 방법: 배열을 통한 구현, 연결리스트를 통한 구현, 힙(heap)을 이용한 구현

    - 우선순위 큐 구현 방법 비교 표:

 

 힙 (Heap)

    - 완전이진트리 형태 (더미)

    - 우선순위 큐를 구현하기 위해 만들어진 자료구조

    - 일종의 반 정렬 상태를 유지

    - 최대 힙(max heap): 부모 노드의 키값이 자식 노드의 키값보다 크거나 같은 완전 이진 트리

key(부모노드) ≥key(자식노드)

    - 최소 힙(min heap): 부모 노드의 키값이 자식 노드의 키값보다 작거나 같은 완전 이진 트리

key(부모노드) ≤key(자식노드)

    - 힙의 높이: n개의 노드를 가지고 있는 힙의 높이는 O(logn), 마지막 레벨을 제외하고 각 레벨 i 에 (2의 i제곱 - 1)개의 노드가 존재

    - 힙은 보통 배열을 이용하여 구현, 각 노드에 배열을 인덱스를 1부터 붙임

    - 부모노드와 자식노드의 관계

        1) 왼쪽 자식의 인덱스 = (부모의 인덱스) * 2

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

        3) 부모의 인덱스 = (자식의 인덱스) / 2

 

 

 

2. C++을 이용한 우선순위 큐 프로그래밍 방법

    1) 힙 노드 클래스를 만든다.

        class HeapNode {

            int형의 key 값을 멤버변수로 선언

            생성자를 통해 클래스 선언 시 key 값도 함께 저장되도록 함

            key 값을 변경할 수 있는 setkey 함수를 선언

            key 값을 가져올 수 있는 getkey 함수를 선언

            key값을 출력해주는 display 함수를 선언

        };

    2) 최대 힙 클래스를 만든다.

        HeapNode 클래스를 #include받아옴

        class MaxHeap {

            HeapNode node[MAX_ELEMENT]를 통해 힙 노드 클래스를 생성하도록 함

            int형의 size 값을 멤버변수로 선언

            생성자 생성

            isEmpty, isFull함수를 통해 MaxHeap의 size를 반환받을 수 있도록 함

            힙에서 부모노드, 왼쪽 자식노드, 오른쪽 자식노드를 반환받을 수 있도록함

            heap에 insert, remove 할 수 있는 함수를 생성

        };

    3) 최대 힙 클래스에 삽입함수와 삭제함수를 구현한다.

        - 삽입함수: 힙에 키값 key를 갖는 새로운 요소를 삽입

            void insert ( int  key ) {

                힙이 가득찬 경우는 더이상 insert되지 않도록 return

                ++size를 통해 하나 증가한 상태에서 힙을 추가할 수 있도록 함

                while문을 통해 트리를 거슬러 올라가며 부모노드와 비교해 부모보다 키값이 크면 부모와 값을 바꿔 위로 올라감

            };

        - 삭제함수

            HeapNode remove ( ) {

                힙이 비어있는 경우는 더이상 remove되지 않도록 return

                마지막노드를 루트노드로 올린 후, while문을 통해 루트노드에서부터 자식노드와 비교해

                자식보다 키값이 작으면 자식과 값을 바꿔 아래로 내려감

                원래 루트노드에 있던 값을 반환

            };

    4) main 함수에서 Maxheap heap; 코드를 통해 최대 힙 클래스를 만든 후,

        insert, remove, display 등의 함수를 사용하며 원하는 계산을 실행한다.

main함수 사용 예시

 

 

3. 문제 풀이

3.1 백준 1966번 - 프린터 큐

    1) case_number을 입력받는다.

    2) for문을 case_number번 반복하며 코드를 실행한다.

        - n과 m을 입력받는다.

        - queue에 입력되는 순서(first)와 n개의 입력값(second)을 pair로 묶어 저장한다.

        - priority_queue (우선순위 큐)에 n개의 입력값을 저장한다.

        - while문을 queue가 비어있을 때까지 반복한다.

            queue의 제일 앞에 있는 수를 pop한다.

            if-> 우선순위 큐의 값과 queue의 값(second)이 일치한다면

            우선순위 값을 pop하고 count도 하나 증가시켜준 후,

            queue에 입력되는 순서값(first)과 m이 같다면 count값을 출력한 후 반복문을 종료한다.

            else-> queue의 제일 앞에 있는 수가 제일 큰 수가 아니라면 다시 뒤로 push한다.

 

3.2 백준 1655번 - 가운데를 말해요

    1) t를 입력받는다.

    2) 우선순위 큐를 선언한다.

        (최댓값이 top에 있는 최대힙과 최솟값이 top에 있는 최소힙 두 개를 선언)

        => 최대힙과 최소힙에 값을 넣을 땐 두가지 조건이 있음

              1. 최대힙의 크기는 항상 최소합의 크기보다 같거나 1만큼 더 크다.

              2. 최소힙의 모든 원소는 최대힙의 모든 원소보다 항상 같거나 커야한다.

    3) while문을 t번 반복하며 말해야하는 값을 출력한다.

        - a를 입력받는다.

        - 최대힙과 최소힙의 크기가 같다면 max(최대 힙)에 a를 저장한다. 

          그렇지 않다면 min(최소 힙)에 a를 저장한다.

        - 최대힙의 top값이 최소힙의 top값보다 크다면 두 값을 swap한다.

        - max (최대 힙)의 top에 있는 값을 출력한 후 다시 while문을 반복한다.

           (max (최대 힙)의 top에 있는 값이 중간값이거나 가장 작은 수임 == 말해야하는 수임)

 

 

(+ 이미지 출처: DATA STRUCTURES USING C++ PPT Chapter 10 우선순위 큐)

'자료구조실습 수업' 카테고리의 다른 글

[9주차 과제]  (0) 2022.11.06
[MID] 중간 프로젝트  (0) 2022.10.16
[4주차 과제]  (0) 2022.10.02
[3주차 과제]  (0) 2022.09.25
[1주차 과제] 리포트 요약 과제  (0) 2022.09.12