Stack이란 Last In First Out(LIFO) 구조를 가진 자료구조입니다. 즉, 마지막으로 들어온 데이터가 가장 먼저 나가는 구조를 가집니다.
이를 구현하기 위해서는 push와 pop이라는 연산이 필요합니다. push는 스택에 데이터를 삽입하는 연산이고, pop은 스택에서 데이터를 꺼내는 연산입니다.
C언어에서는 구조체를 이용하여 스택을 구현할 수 있습니다. 아래는 구조체를 이용한 스택 구현 예시입니다.
#define MAX_SIZE 100 // 스택의 최대 크기
typedef struct Stack {
int arr[MAX_SIZE];
int top;
} Stack;
void initStack(Stack* stack) {
stack->top = -1;
}
bool isFull(Stack* stack) {
return stack->top == MAX_SIZE - 1;
}
bool isEmpty(Stack* stack) {
return stack->top == -1;
}
void push(Stack* stack, int data) {
if (isFull(stack)) {
printf("Stack is full.\n");
return;
}
stack->arr[++stack->top] = data;
}
int pop(Stack* stack) {
if (isEmpty(stack)) {
printf("Stack is empty.\n");
return -1;
}
return stack->arr[stack->top--];
}
위 코드에서는 구조체를 이용하여 스택을 정의하고, initStack 함수를 통해 스택을 초기화합니다. push 함수에서는 스택이 가득 찼는지 여부를 검사하고, 꽉 차지 않았다면 데이터를 삽입합니다. pop 함수에서는 스택이 비어있는지 여부를 검사하고, 비어있지 않다면 가장 위에 있는 데이터를 꺼내 반환합니다.
[구조체를 이용한 Queue 구현]
Queue는 First In First Out(FIFO) 구조를 가진 자료구조입니다. 즉, 가장 먼저 들어온 데이터가 가장 먼저 나가는 구조를 가집니다.
C언어에서는 구조체를 이용하여 큐를 구현할 수 있습니다. 아래는 구조체를 이용한 큐 구현 예시입니다.
#define MAX_SIZE 100 // 큐의 최대 크기
typedef struct Queue {
int arr[MAX_SIZE];
int front;
int rear;
} Queue;
void initQueue(Queue* queue) {
queue->front = -1;
queue->rear = -1;
}
bool isFull(Queue* queue) {
return queue->rear == MAX_SIZE - 1;
}
bool isEmpty(Queue* queue) {
return queue->front == queue->rear;
}
void enqueue(Queue* queue, int data) {
if (isFull(queue)) {
printf("Queue is full.\n");
return;
}
queue->arr[++queue->rear] = data;
}
int dequeue(Queue* queue) {
if (isEmpty(queue)) {
printf("Queue is empty.\n");
return -1;
}
구조체를 이용해 스택과 큐를 구현할 때 어려웠던 점은 구조체를 다루는 방법과 포인터 개념을 이해하는 것이었습니다. 특히, 포인터를 사용할 때는 메모리 주소를 다루기 때문에 실수하기 쉬웠습니다.
해결 방법으로는 먼저 구조체의 사용법과 멤버 변수를 다루는 방법을 숙지하는 것이 중요합니다. 구조체를 정의할 때 각 멤버 변수의 타입과 이름을 정확하게 지정해야 합니다. 또한, 구조체를 선언할 때는 구조체 변수의 이름을 지정하고, 구조체 멤버 변수에 접근할 때는 점 연산자(.)를 사용해야 합니다.
또한, 포인터를 사용할 때는 주소 연산자(&)와 간접 참조 연산자(*)를 제대로 이해해야 합니다. 주소 연산자를 사용하면 변수의 메모리 주소를 구할 수 있고, 간접 참조 연산자를 사용하면 포인터가 가리키는 변수에 접근할 수 있습니다.
구조체를 이용해 스택과 큐를 구현할 때는 구조체 변수와 포인터를 적절히 활용해야 합니다. 스택의 경우에는 구조체 변수를 배열처럼 사용하여 원소를 저장하고, 포인터를 이용해 스택의 맨 위에 있는 원소를 가리키도록 합니다. 큐의 경우에는 구조체 변수를 이용해 원소와 그에 대한 포인터를 저장하고, 포인터를 이용해 큐의 맨 앞과 맨 뒤를 가리키도록 합니다.
또한, 스택과 큐의 동작 방식을 명확하게 이해하고, 알고리즘을 구현할 때는 코드의 일관성과 가독성을 유지해야 합니다. 이를 위해 함수를 적절히 나누고, 함수의 인자와 반환값을 명확하게 지정하는 것이 좋습니다.