덱, Deque(Double- ended- Queue)는 큐의 front 와 rear에서 모두 삽입,삭제가 가능한 큐로서, 스택과 큐의 특성을 모두 가지고 있다. 이는 덱을 스택으로도, 큐로도 사용할 수 있음을 의미한다.
- 스택으로 사용시: top > rear일때, push() >> deque의 insertRear()와 비슷, Pop() > deleteRear()와 비슷함
- 큐로 사용시 : enqueue > insertRear()와 비슷, Dequeue() > deleteFront()와 비슷
덱도 스택과 큐에서 구현한 방식처럼, 1) 배열로 구현하는 방법과, 2) 연결 리스트를 이용한 방법이 있다. 배열로 구현한 경우, 양쪽 끝에서 삽입/삭제 연산을 수행하면서 크기 변화와 저장된 원소의 순서변화가 많으므로 배열은 비효율적이다.
따라서 연결리스트를 이용한 방법을 많이 사용한다. 양방향으로 연산이 가능한 이중 연결 리스트를 사용한다.
[이중 연결 리스트를 이용한 Deque 구현]
#include <stdio.h>
#include <stdlib.h>
// 덱의 노드 구조체 정의
typedef struct Node {
int data;
struct Node *prev;
struct Node *next;
} Node;
// 덱 구조체 정의
typedef struct Deque {
Node *front;
Node *rear;
} Deque;
// 덱 초기화 함수
void initializeDeque(Deque *deque) {
deque->front = NULL;
deque->rear = NULL;
}
// 덱이 비어있는지 확인하는 함수
int isEmpty(Deque *deque) {
return (deque->front == NULL);
}
// 덱의 앞에 원소 추가 함수
void insertFront(Deque *deque, int data) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (newNode == NULL) {
fprintf(stderr, "메모리 할당 오류\n");
exit(EXIT_FAILURE);
}
newNode->data = data;
newNode->prev = NULL;
newNode->next = deque->front;
if (isEmpty(deque)) {
// 덱이 비어있을 경우 front와 rear를 새로 추가한 노드로 설정
deque->front = newNode;
deque->rear = newNode;
} else {
// 덱이 비어있지 않을 경우 기존 front의 prev를 새로 추가한 노드로 설정
deque->front->prev = newNode;
deque->front = newNode;
}
}
// 덱의 뒤에 원소 추가 함수
void insertRear(Deque *deque, int data) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (newNode == NULL) {
fprintf(stderr, "메모리 할당 오류\n");
exit(EXIT_FAILURE);
}
newNode->data = data;
newNode->prev = deque->rear;
newNode->next = NULL;
if (isEmpty(deque)) {
// 덱이 비어있을 경우 front와 rear를 새로 추가한 노드로 설정
deque->front = newNode;
deque->rear = newNode;
} else {
// 덱이 비어있지 않을 경우 기존 rear의 next를 새로 추가한 노드로 설정
deque->rear->next = newNode;
deque->rear = newNode;
}
}
// 덱의 앞에서 원소 삭제 함수
void deleteFront(Deque *deque) {
if (isEmpty(deque)) {
fprintf(stderr, "덱이 비어있습니다.\n");
return;
}
Node *temp = deque->front;
deque->front = deque->front->next;
if (deque->front == NULL) {
// 덱이 비어있게 되면 rear도 NULL로 설정
deque->rear = NULL;
} else {
// 덱이 비어있지 않을 경우 새로운 front의 prev를 NULL로 설정
deque->front->prev = NULL;
}
free(temp);
}
// 덱의 뒤에서 원소 삭제 함수
void deleteRear(Deque *deque) {
if (isEmpty(deque)) {
fprintf(stderr, "덱이 비어있습니다.\n");
return;
}
Node *temp = deque->rear;
deque->rear = deque->rear->prev;
if (deque->rear == NULL) {
// 덱이 비어있게 되면 front도 NULL로 설정
deque->front = NULL;
} else {
// 덱이 비어있지 않을 경우 새로운 rear의 next를 NULL로 설정
deque->rear->next = NULL;
}
free(temp);
}
// 덱의 전체 원소 출력 함수
void printDeque(Deque *deque) {
if (isEmpty(deque)) {
printf("덱이 비어있습니다.\n");
return;
}
Node *current = deque->front;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
// 덱 메모리 해제 함수
void freeDeque(Deque *deque) {
while (!isEmpty(deque)) {
deleteFront(deque);
}
}
int main() {
Deque myDeque;
initializeDeque(&myDeque);
insertFront(&myDeque, 1);
insertRear(&myDeque, 2);
insertFront(&myDeque, 3);
printf("덱의 원소: ");
printDeque(&myDeque);
deleteFront(&myDeque);
printf("덱의 원소(앞에서 하나 삭제 후): ");
printDeque(&myDeque);
deleteRear(&myDeque);
printf("덱의 원소(뒤에서 하나 삭제 후): ");
printDeque(&myDeque);
freeDeque(&myDeque);
return 0;
}
'Computer Science' 카테고리의 다른 글
[자료구조] 트리(Tree) 정의 및 용어 정리 (0) | 2024.02.09 |
---|---|
[자료구조] 이진 트리의 순회(중위순회/전위순회/후위순회) (0) | 2024.02.08 |
[자료구조] 큐 구현: 연결리스트 이용 방법 (0) | 2024.02.06 |
[자료구조] 큐 구현: 배열 이용방법(feat. enqueue, dequeue, peek 알고리즘), queue가 가지는 한계점 (0) | 2024.02.05 |
[자료구조] 스택 구현 : 연결리스트 이용 방법 (0) | 2024.02.04 |