[Data Structures | C++] Queue & Deque : 큐 & 데큐
[Data Structures | C++] Queue & Deque : 큐 & 데큐
큐(Queue)
- 큐는 처음에 저장한 데이터를 가장 먼저 꺼내는 선입선출(FIFO:First In First Out) 구조로 되어 있다.
- 입출력이 양방향에서 이루어지는 데이터 구조이다.
- FRONT)는 가장 먼저 삽입된 자료의 기억공간을 가리키는 포인터이고 , REAR는 가장 마지막에 삽입된 자료가 위치한 기억장소를 가리키는 포인터이다.
- 데이터 입력은 FRONT 포인터를 통해서 하고, 데이터 삭제는 REAR 포인터를 통해서 한다.
- 삽입연산을 Enqueue 또는 Put, 삭제연산을 Dequeue 또는 Get라고 한다.
- 큐에서는 FRONT와 REAR가 같을 때 비어있는 공백큐 임을 알수 있다.
- overflow : 큐의 모든 기억장소가 꽉 채워져 있어서 더 이상 데이터를 삽입(Enqueue할 때)할 수 없다.
- underflow : 자료가 없다면 스택에는 삭제(Dequeue할 때)할 자료가 없다.
큐(Queue)의 연산
큐(Queue)는 FIFO(First-In-First-Out) 를 따른다.
- add(item) : item을 리스트의 끝부분에 추가한다.
- remove() : 리스트의 첫 번째 항목을 제거한다.
- peek() : 큐에서 가장 위에 있는 항목을 반환한다.
- isEmpty() : 큐가 비어 있을 때에 true를 반환한다.
큐(Queue)에서 처음과 마지막 노드를 갱신할 때 실수가 나오기 쉽다.
큐의 단점
- 데이터 삽입 후 계속 항목을 삭제하면 REAR와 FRONT가 만나게 되어 공백큐가 됨에도 불구하고 오버 플로우 현상이 발생한다. 즉, 메모리 낭비가 생기게 된다.
개선된 원형 큐가 나옴.
- 원형 큐의 단점 : 메모리 공간은 잘 활용하나 배열로 구현되어 있기 때문에 큐의 크기가 제한되는 단점이 존재한다.
링크드 리스트로 큐가 나옴.
- 링크드 리스트로 구현한 큐는 큐의 크기가 제한이 없고, 삽입, 삭제가 효과적이다.
큐의 용도
데이터가 입력된 시간 순서대로 처리해야 할 필요가 있는 상황에 이용한다.
- 너비 우선 탐색(BFS, Breadth-First Search) 구현
- 처리해야 할 노드의 리스트를 저장하는 용도로 큐(Queue)를 사용한다.
- 노드를 하나 처리할 때마다 해당 노드와 인접한 노드들을 큐에 다시 저장한다.
- 노드를 접근한 순서대로 처리할 수 있다.
- 캐시(Cache) 구현
- 우선순위가 같은 작업 예약 (인쇄 대기열)
- 선입선출이 필요한 대기열 (티켓 카운터)
- 콜센터 고객 대기시간
- 프린터의 출력 처리
- 윈도 시스템의 메시지 처리기
- 프로세스 관리
- 운영체제 작업 스케쥴링
- 컴퓨터 버퍼에서 주로 사용, 마구 입력이 되었으나 처리를 하지 못할 때, 버퍼(큐)를 만들어 대기 시킨다.
- 대기행렬 처리
인쇄작업 대기목록
- 큐는 데이터를 꺼낼 때 항상 첫 번째 저장된 데이터를 삭제하므로 배열리스트와 같은 배열 기반의 컬렉션 클래스를 사용한다면 데이터를 꺼낼 때마다 빈 공간을 채우기 위해서 데이터의 복사가 발생하므로 비효율적이다. 따라서 큐를 사용할때는 연결 리스트(Linked List)로 구현하는 것이 적합하다.
데큐(Double-Ended Queue)
- 큐와 스택의 장점을 합쳐놓은 개념이다.
- 양쪽 끝에서 삽입과 삭제가 모두 가능한 자료구조이다.
- 두 개의 포인터를 사용하여, 양쪽에서 삽입과 삭제를 발생시킬 수 있다.
- 입력이 한쪽 끝으로만 가능하도록 설정한 데크인 입력제한데크(Scroll), 출력이 한쪽 끝으로만 가능하도록 설정한 데크인 출력제한데크(Shelf)가 있다.
C++로 구현한 큐 & 덱 (Queue & Deque)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class Queue
{
private:
DoubleList *doublelist;
public:
Queue();
~Queue();
DoubleList *getdouble() { return doublelist; }
void enqueue(int data, int position);
void dequeue(int position);
void display();
};
#include "Queue.h"
Queue::Queue()
{
doublelist = new DoubleList;
}
Queue::~Queue()
{
}
void Queue::enqueue(int data, int _position) {
doublelist->insertNode(data, _position);
}
void Queue::dequeue(int position) {
doublelist->delNode(position);
}
void Queue::display() {
doublelist->displayNode();
}
//Manager.cpp
void Manager::QueueRun() {
int menu = 0;
int _data = 0;
while (true)
{
cout << "1.삽입\n2.반환\n3.출력\n입력 : ";
cin >> menu;
switch (menu)
{
case INSERT:
cout << "추가 할 데이터 : ";
cin >> _data;
queue->enqueue(_data, -1);
queue->display();
break;
case DEL:
queue->dequeue(0);
queue->display();
break;
case COUT:
if (queue->getdouble()->getHead() == NULL) {
cout << "데이터가 없습니다." << endl << endl;
}
else {
queue->display();
}
break;
default:
break;
}
}
}
This post is licensed under CC BY 4.0 by the author.