[자료구조] 우선순위 큐(Priority Queue)와 힙(Heap)

2022. 4. 24. 11:26· 자료구조
목차
  1. [우선순위 큐의 종류]
  2.  
  3. [힙을 이용하여 만드는 우선순위 큐]
들어간 순서에 상관없이 우선순위가 높은 데이터가 먼저 나온다

[우선순위 큐의 종류]

  • 배열을 기반으로 구현하는 방법 (삽입/삭제시 모든 데이터 뒤로 밀거나 당겨야함, 모든 데이터와 우선순위를 비교해야함)
  • 연결리스트를 기반으로 구현하는 방법 (모든 데이터와 우선순위를 비교해야함)
  • 힙을 이용하는 방법

 

힙 = 완전이진트리 + 모든 노드에 저장된 값은 자식노드에 저장된 값보다 크거나 같음(최대 힙)

 

 

[힙을 이용하여 만드는 우선순위 큐]

 

힙≠우선순위 큐 이다 → 힙은 우선순위 큐 구현에 딱 어울리는 자료구조일 뿐이다.

 

<힙의 특징>

(데이터 추가 방식)
1. 새로운 데이터는 우선순위가 가장 낮다고 가정하고 마지막 위치에 저장함
2. 부모 노드와 비교해서 위치가 바뀌어야 하면 바꿈
3. 제대로 된 위치를 찾을때 까지 반복

(데이터 삭제 방식) → 우선순위 큐의 삭제 = 가장 높은 우선순위의 데이터 삭제
1. 루트노드를 삭제하고 마지막 노드를 루트노드로 옮김
2. 새로운 루트노드를 자식 노드와의 비교를 통해서 둘중 우선순위가 높은 자식노드와 교환하여 제자리를 찾아가게 함

최대 힙의 데이터 추가과정

 

 

힙은 배열 기반으로 구현해야함
➡️ 연결리스트 기반으로 구현하면 새로운 노드를 마지막 위치에 추가하는것이 쉽지않다

 

배열 기반의 이진트리

 

왼쪽 자식노드의 인덱스 값 = 부모노드 인덱스 * 2
오른쪽 자식노드의 인덱스 값 = 부모노드 인덱스 * 2 + 1
부모노드의 인덱스 값 = 자식노드 / 2

 

▶ 힙의 ADT


필요한 기능 : 데이터의 추가/삭제, 힙 초기화, 데이터 empty 여부

void HeapInit(Heap * ph, PriorityComp pc);
int HIsEmpty(Heap * ph);
void HInsert(Heap * ph, HData data); //데이터 추가
HData HDelete(Heap * ph); //데이터 삭제

 

▶ 힙의 구현

 

  • 힙을 의미하는 구조체
typedef struct _heap
{
	PriorityComp * comp; //우선순위의 기준을 정하는 함수
	int numOfData;
	HData heapArr[HEAP_LEN]; //데이터를 저장하는 공간
} Heap;

PriorityComp * comp -> 함수 포인터 변수에 사용자가 지정한 우선순위 함수를 받는다

프로그래머가 우선순위의 판단 기준을 힙에 설정할 수 있다
(첫번째 인자가 우선순위 높으면 양수 반환, 두번째 인자가 우선순위 높으면 음수 반환)

 

  • 힙 ADT의 구현
void HeapInit(Heap * ph, PriorityComp pc)
{
	ph->numOfData = 0;
	ph->comp = pc;
}

int HIsEmpty(Heap * ph)
{
	if(ph->numOfData == 0)
		return TRUE;
	else
		return FALSE;
}

int GetParentIDX(int idx) 
{ 
	return idx/2; 
}

int GetLChildIDX(int idx) 
{ 
	return idx*2; 
}

int GetRChildIDX(int idx) 
{ 
	return GetLChildIDX(idx)+1; 
}

int GetHiPriChildIDX(Heap * ph, int idx)
{
	if(GetLChildIDX(idx) > ph->numOfData)
		return 0;

	else if(GetLChildIDX(idx) == ph->numOfData)
		return GetLChildIDX(idx);

	else
	{// 두번째 인자가 더 우선순위 높은경우
		if(ph->comp(ph->heapArr[GetLChildIDX(idx)], ph->heapArr[GetRChildIDX(idx)]) < 0)
			return GetRChildIDX(idx);
		else
			return GetLChildIDX(idx);
	}
}

void HInsert(Heap * ph, HData data)
{
	int idx = ph->numOfData+1;

	while(idx != 1)
	{//입력받은 데이터가 부모노드보다 우선순위 높은경우
		if(ph->comp(data, ph->heapArr[GetParentIDX(idx)]) > 0)
		{
			ph->heapArr[idx] = ph->heapArr[GetParentIDX(idx)];
			idx = GetParentIDX(idx);
		}
		else
		{
			break;
		}
	}
	
	ph->heapArr[idx] = data;
	ph->numOfData += 1;
}

HData HDelete(Heap * ph)
{
	HData retData = ph->heapArr[1];
	HData lastElem = ph->heapArr[ph->numOfData];

	int parentIdx = 1;
	int childIdx;

	while(childIdx = GetHiPriChildIDX(ph, parentIdx))
	{//마지막 노드가 자식노드보다 우선순위 높은경우
		if(ph->comp(lastElem, ph->heapArr[childIdx]) >= 0)
			break;

		ph->heapArr[parentIdx] = ph->heapArr[childIdx];
		parentIdx = childIdx;
	}

	ph->heapArr[parentIdx] = lastElem;
	ph->numOfData -= 1;
	return retData;
}

 

<특징>

void HInsert(Heap * ph, HData data) -> 새로운 데이터를 마지막 인덱스에 저장하고 부모노드에 있는 데이터는 밑으로 내리되 새로 저장된 데이터는 인덱스값만 갱신하다가 마지막에 삽입

HData HDelete(Heap * ph) -> 마지막 데이터를 일일이 옮겨가면서 값을 내리지 않고 우선순위가 더 높은 자식노드만 위로 올리고 마지막에 제자리에 삽입

▶ 우선순위 큐의 ADT


필요한 기능 : 데이터의 추가/삭제, 우선순위 큐 초기화, 데이터 empty 여부

void PQueueInit(PQueue * ppq, PriorityComp pc);
int PQIsEmpty(PQueue * ppq);
void PEnqueue(PQueue * ppq, PQData data);
PQData PDequeue(PQueue * ppq);

 

▶ 우선순위 큐의 구현 = 힙과 거의 같음

 

void PQueueInit(PQueue * ppq, PriorityComp pc)
{
	HeapInit(ppq, pc);
}

int PQIsEmpty(PQueue * ppq)
{
	return HIsEmpty(ppq);
}

void PEnqueue(PQueue * ppq, PQData data)
{
	HInsert(ppq, data);
}

PQData PDequeue(PQueue * ppq)
{
	return HDelete(ppq);
}

'자료구조' 카테고리의 다른 글

[자료구조] 그래프 (Graph)  (0) 2022.05.07
[자료구조] 해쉬(Hash)와 테이블(Table)  (0) 2022.05.02
[자료구조] 트리(Tree)  (0) 2022.04.17
[자료구조] 덱(Deque)  (0) 2022.04.10
[자료구조] 큐(Queue)  (0) 2022.04.10
  1. [우선순위 큐의 종류]
  2.  
  3. [힙을 이용하여 만드는 우선순위 큐]
'자료구조' 카테고리의 다른 글
  • [자료구조] 그래프 (Graph)
  • [자료구조] 해쉬(Hash)와 테이블(Table)
  • [자료구조] 트리(Tree)
  • [자료구조] 덱(Deque)
생선묵김치찌개
생선묵김치찌개
생선묵김치찌개
준혁's 코딩 연구기록
생선묵김치찌개
전체
오늘
어제
  • 분류 전체보기 (96)
    • Java (5)
    • Spring Boot (3)
    • 자료구조 (8)
    • 네트워크 (4)
    • 데이터베이스 (4)
    • 기술적 고민 (17)
      • Side Match (13)
      • 자리나따 (4)
    • C++ (3)
    • Algorithm (4)
    • PS 연습 (38)
    • 잡동사니 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • ㄱ
  • aws rds
  • 큐
  • 배열 리스트
  • 브루트 포스
  • 스택
  • 이진트리
  • DN
  • 자료구조
  • 원형 연결 리스트
  • 열혈 자료구조
  • 백준
  • Stream
  • 파일 업로드
  • CPP
  • backend
  • 단순 연결 리스트
  • 완전탐색
  • 백준 골드
  • 트리
  • dp
  • open api
  • 수식트리
  • 예외처리
  • 재귀
  • 알고리즘
  • 해커톤
  • 양방향 연결 리스트
  • 스프링
  • sentry

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.1
생선묵김치찌개
[자료구조] 우선순위 큐(Priority Queue)와 힙(Heap)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.