스택이란? 항목들이 쌓여 있는 구조로 LIFO(Last-In, First-Out) 원칙을 따른다.
주요 기능에는 push, pop이 있고 이 기능을 수행하기 위해서는 여러가지 요소가 필요하다.
push : 데이터를 삽입한다.pop : 데이터를 삭제한다.peek : 스택의 요소를 리턴한다.top : 스택의 맨 위에 있는 자료를 가리키는 변수(비어있을 때 top = -1)MAX : 스택의 최대 크기isEmpty : 스택이 비어있는지 검사한다.isFull : 스택이 꽉 차있는지 검사한다.스택을 직접 구현 할때는 아래의 그림을 보고 구현하시면 됩니다.
배열 기반 스택 구현 - C
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MAX 100 // 스택의 최대 크기
int stack[MAX]; // 스택 배열
int top = -1; // top 인덱스 초기값
// 스택이 비었는지 확인
bool isEmpty() {
return top == -1;
}
// 스택이 가득 찼는지 확인
bool isFull() {
return top == MAX - 1;
}
// 요소를 스택에 삽입
void push(int data) {
if (isFull()) {
printf("Stack Overflow! 더 이상 삽입할 수 없습니다.\n");
return;
}
stack[++top] = data;
printf("Pushed: %d\n", data);
}
// 스택에서 요소 제거
int pop() {
if (isEmpty()) {
printf("Stack Underflow! 제거할 요소가 없습니다.\n");
return -1;
}
return stack[top--];
}
// 스택의 최상단 요소를 반환 (제거 X)
int peek() {
if (isEmpty()) {
printf("Stack is empty! 조회할 요소가 없습니다.\n");
return -1;
}
return stack[top];
}
// 직접 구현하기
int main() {
}
일반 큐
일반 큐란? 선형 자료구조로 FIFO(First-In-First-Out) 원칙을 따른다.
큐는 상황에 따라 선형 외에도 원 형태로 된 큐도 존재합니다.
큐의 주요 기능은 스택과 마찬가지로 Enqueue(push()), Dequeue(pop())가 있고 이 기능들을 수행하기 위해서는 여러가지 요소가 필요하다.
Enqueue : 데이터를 삽입한다.Dequeue : 데이터를 삭제한다.rear : 가장 뒤에 있는 데이터의 indexisEmpty : 큐가 비어 있는지 검사한다.isFull : 큐가 꽉 차있는지 검사한다.일반 큐 구현 - C
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5
typedef struct {
int items[SIZE];
int rear; // 요소 개수 및 다음 삽입 위치
} Queue;
// 큐 초기화
void initQueue(Queue *q) {
q->rear = 0;
}
// 큐가 비었는지 확인
int isEmpty(Queue *q) {
return q->rear == 0;
}
// 큐가 가득 찼는지 확인
int isFull(Queue *q) {
return q->rear == SIZE;
}
// Enqueue: 큐에 요소 삽입
void enqueue(Queue *q, int value) {
if (isFull(q)) {
printf("Queue is Full!\n");
return;
}
q->items[q->rear++] = value;
printf("Enqueued: %d\n", value);
}
// Dequeue: 요소 제거 (앞으로 이동)
int dequeue(Queue *q) {
if (isEmpty(q)) {
printf("Queue is Empty!\n");
return -1;
}
int value = q->items[0]; // 맨 앞 요소 추출
// 모든 요소를 한 칸씩 앞으로 당김
for (int i = 1; i < q->rear; i++) {
q->items[i - 1] = q->items[i];
}
q->rear--; // rear 한 칸 감소
printf("Dequeued: %d\n", value);
return value;
}
// 큐 상태 출력
void display(Queue *q) {
if (isEmpty(q)) {
printf("Queue is Empty!\n");
return;
}
printf("Queue: ");
for (int i = 0; i < q->rear; i++) {
printf("%d ", q->items[i]);
}
printf("\n");
}
// 직접 구현
int main() {
}
원형 큐
원형 큐란? 일반 큐의 단점을 보완한 원형 자료구조다.
일반 큐 즉, 선형 큐의 단점은 데이터를 삭제할 때마다 데이터를 한칸씩 당겨 front 없이도 가능하지만 이러면 불필요한 움직이 있어 효울적이지 못합니다.
그래서 이 문제를 해결하기 위해 이 원형 큐가 나왔습니다.
이렇게 되면 데이터를 움직이지 않아도 순환하는 특징을 이용해 데이터를 효율적이게 삭제할 수 있습니다.
Enqueue : 데이터를 삽입한다.Dequeue : 데이터를 삭제한다.front : 가장 앞에 있는 데이터의 indexrear : 가장 뒤에 있는 데이터의 indexisEmpty : 큐가 비어 있는지 검사한다.isFull : 큐가 꽉 차있는지 검사한다.원형 큐 구현 - C
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5 // 사용할 실제 데이터 수는 4개 (하나는 빈칸으로 둬야 구분 가능)
typedef struct {
int items[SIZE];
int front;
int rear;
} CircularQueue;
// 초기화
void initQueue(CircularQueue *q) {
q->front = 0;
q->rear = 0;
}
// 큐가 비었는지 확인
int isEmpty(CircularQueue *q) {
return q->front == q->rear;
}
// 큐가 가득 찼는지 확인
int isFull(CircularQueue *q) {
return (q->rear + 1) % SIZE == q->front;
}
// 삽입 (enqueue)
void enqueue(CircularQueue *q, int value) {
if (isFull(q)) {
printf("Queue is Full!\n");
return;
}
q->items[q->rear] = value;
q->rear = (q->rear + 1) % SIZE;
printf("Enqueued: %d\n", value);
}
// 제거 (dequeue)
int dequeue(CircularQueue *q) {
if (isEmpty(q)) {
printf("Queue is Empty!\n");
return -1;
}
int value = q->items[q->front];
q->front = (q->front + 1) % SIZE;
printf("Dequeued: %d\n", value);
return value;
}
// 상태 출력
void display(CircularQueue *q) {
if (isEmpty(q)) {
printf("Queue is Empty!\n");
return;
}
printf("Queue: ");
int i = q->front;
while (i != q->rear) {
printf("%d ", q->items[i]);
i = (i + 1) % SIZE;
}
printf("\n");
}
// 직접 구현
int main() {
}
덱이란? 일반 큐, 원형 큐의 확장된 자료 구조다.
이전에 봤던 큐는 fornt에서만 데이터를 삽입 삭제 할 수 있었는데 덱(deque)에서는 뒤에서 삽입, 삭제가 가능하다.
Deque : 비어 있는 새로운 덱을 생성isEmpty : 덱이 비어있으면 True를 아니면 False 반환addFront : 덱의 맨 앞에 추가deleteFront : 맨 앞의 항목을 꺼내서 반환getFront : 맨 앞의 항목을 꺼내지 않고 반환addRear : 덱의 맨 뒤에 추가deleteRear : 맨 뒤의 항목을 꺼내서 반환getRear : 맨 뒤의 항목을 꺼내지 않고 반환isFull : 덱이 가득 차 있으면 True를 아니면 False 반환size : 덱의 모든 항목들의 개수 반환clear : 덱을 공백상태로 만듬덱 구현 - C
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define SIZE 5 // 덱의 최대 크기 +1 (공간 하나는 비워둬야 full/empty 구분 가능)
typedef struct {
int items[SIZE];
int front; // 실제 front는 (front + 1) % SIZE
int rear; // 실제 rear는 rear % SIZE
} Deque;
// 덱 초기화
void initDeque(Deque *dq) {
dq->front = 0;
dq->rear = 0;
}
// 덱이 비었는지
bool isEmpty(Deque *dq) {
return dq->front == dq->rear;
}
// 덱이 가득 찼는지
bool isFull(Deque *dq) {
return (dq->rear + 1) % SIZE == dq->front;
}
// 덱의 크기
int size(Deque *dq) {
return (dq->rear - dq->front + SIZE) % SIZE;
}
// 덱 비우기
void clear(Deque *dq) {
dq->front = dq->rear = 0;
}
// 앞에 삽입
void addFront(Deque *dq, int value) {
if (isFull(dq)) {
printf("Deque is Full!\n");
return;
}
dq->front = (dq->front - 1 + SIZE) % SIZE;
dq->items[dq->front] = value;
printf("addFront: %d\n", value);
}
// 뒤에 삽입
void addRear(Deque *dq, int value) {
if (isFull(dq)) {
printf("Deque is Full!\n");
return;
}
dq->items[dq->rear] = value;
dq->rear = (dq->rear + 1) % SIZE;
printf("addRear: %d\n", value);
}
// 앞에서 삭제
int deleteFront(Deque *dq) {
if (isEmpty(dq)) {
printf("Deque is Empty!\n");
return -1;
}
int value = dq->items[dq->front];
dq->front = (dq->front + 1) % SIZE;
printf("deleteFront: %d\n", value);
return value;
}
// 뒤에서 삭제
int deleteRear(Deque *dq) {
if (isEmpty(dq)) {
printf("Deque is Empty!\n");
return -1;
}
dq->rear = (dq->rear - 1 + SIZE) % SIZE;
int value = dq->items[dq->rear];
printf("deleteRear: %d\n", value);
return value;
}
// 앞 항목 반환 (삭제 X)
int getFront(Deque *dq) {
if (isEmpty(dq)) {
printf("Deque is Empty!\n");
return -1;
}
return dq->items[dq->front];
}
// 뒤 항목 반환 (삭제 X)
int getRear(Deque *dq) {
if (isEmpty(dq)) {
printf("Deque is Empty!\n");
return -1;
}
return dq->items[(dq->rear - 1 + SIZE) % SIZE];
}
// 덱 출력
void display(Deque *dq) {
if (isEmpty(dq)) {
printf("Deque is Empty!\n");
return;
}
printf("Deque: ");
int i = dq->front;
while (i != dq->rear) {
printf("%d ", dq->items[i]);
i = (i + 1) % SIZE;
}
printf("\n");
}
// 직접 구현
int main() {
}