[자료구조] c언어로 큐, 원형 큐 구현하기
큐(Queue)란?
큐 타입 구조체 정의 및 초기화 함수
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
typedef char element;
typedef struct
{
element data[SIZE];
int rear, front;
} QueueType;
void init(QueueType *Q)
{
Q->rear = Q->front = -1;
}
큐의 요소에 해당하는 data 배열과, 큐의 가장 앞과 뒤에 해당하는 front, rear이 포함된 QueueType 구조체를 선언한다.
에러체크함수 is_empty(), is_full()
에러체크함수 is_empty는 아무것도 차있지 않은 상태, 즉 front와 rear가 같은지 살핀다.
is_full은 큐가 가득 차있는 상태인 rear가 size -1이 같은지 살핀다. -1을 하는 이유는 큐 data 배열은 0부터 시작하기때문이다.
int is_empty(QueueType *Q)
{
return Q->front == Q->rear;
}
int is_full(QueueType *Q)
{
return Q->rear == SIZE - 1;
}
삽입함수 enqueue()
삽입을 하기위해 rear을 한칸 움직이고, 데이터를 한칸 움직인 공간에 삽입한다.
void enqueue(QueueType *Q, element e)
{
if (is_full(Q))
printf("Overflow\n");
else
{
Q->rear++;
Q->data[Q->rear] = e;
}
}
삭제함수 dequeue()
가장 먼저 들어온 데이터부터 삭제해야하므로 front를 한칸 움직이고 데이터를 return한다.
element dequeue(QueueType *Q)
{
if (is_empty(Q))
{
printf("Empty\n");
return 0;
}
else
{
Q->front++;
return Q->data[Q->front];
}
}
큐 출력함수 print()
void print(QueueType *Q)
{
printf("Front Pos : %d\n, Rear Pos : %d\n", Q->front, Q->rear);
for (int i = Q->front + 1; i <= Q->rear; i++)
{
printf("[%c] ", Q->data[i]);
}
printf("\n");
}
큐의 단점?
큐를 사용하면 할수록 front가 뒤로 밀려나게 되므로 마지막 공간의 front와 Rear가 같아지게 되어 삭제된 front 앞의 공간(이전에 할당된 공간)은 쓸 수 없게 된다.
원형 큐(Circular Queue)
큐의 이미 사용한 앞 공간은 쓸수 없다는 단점을 보완하기 위해 원형 큐를 사용할 수 있다. 원형 큐를 구현하기 위해서는 앞서 구현한 큐에서 일부 코드만 수정하면 된다.
에러체크함수 is_empty(), is_full()
is_empty함수는 큐의 코드와 동일하고, is_full함수는 공백 상태와 구분하기 위해서 한 칸 비워둔다. 그리고 원형큐를 구현하기 위해서는 나머지 모듈러 연산이 필요하다.(front == rear + 1을 전체 size로 나눈 나머지)
한 칸 비워두지 않으면 0번 index에 front==rear인 경우 공백 상태와 포화 상태가 중복되어서 구분할 수 없기 때문이다.
int is_empty(QueueType *Q)
{
return Q->front == Q->rear;
}
int is_full(QueueType *Q)
{
return Q->front == (Q->rear + 1) % SIZE;
}
삽입함수 enqueue()
삽입함수는 rear를 1만큼 증가시킨 값과 size와의 나머지로 설정하고 데이터를 저장한다.
예를들어 현재 rear가 4이고, size가 8이라면 (4 + 1) % 8 = 5번 인덱스, rear가 7이라면 (7 + 1) % 8 = 0번 인덱스에 위치한다.
void enqueue(QueueType *Q, element e)
{
if (is_full(Q))
printf("Overflow\n");
else
{
Q->rear = (Q->rear + 1) % SIZE;
Q->data[Q->rear] = e;
}
}
삭제함수 dequeue()
삽입함수와 마찬가지로 front를 증가시키고 데이터를 return한다.
element dequeue(QueueType *Q)
{
if (is_empty(Q))
{
printf("Empty\n");
return 0;
}
else
{
Q->front = (Q->front + 1) % SIZE;
return Q->data[Q->front];
}
}
원형큐 출력함수 print()
출력함수 print()는 while문을 통해 i값을 front부터 rear까지 순차적으로 증가시키면서 출력한다.
void print(QueueType *Q)
{
printf("Front Pos : %d\n, Rear Pos : %d\n", Q->front, Q->rear);
int i = Q->front; // 제일 앞에있는 원소 바로 하나 전부터 시작
while (i != Q->rear)
{
i = (i + 1) % SIZE;
printf("[%c]", Q->data[i]);
}
printf("\n");
}
전체 코드
큐 (더보기)
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
typedef char element;
typedef struct
{
element data[SIZE];
int rear, front;
} QueueType;
void init(QueueType *Q)
{
Q->rear = Q->front = -1;
}
int is_empty(QueueType *Q)
{
return Q->front == Q->rear;
}
int is_full(QueueType *Q)
{
return Q->rear == SIZE - 1;
}
void enqueue(QueueType *Q, element e)
{
if (is_full(Q))
printf("Overflow\n");
else
{
Q->rear++;
Q->data[Q->rear] = e;
}
}
element dequeue(QueueType *Q)
{
if (is_empty(Q))
{
printf("Empty\n");
return 0;
}
else
{
Q->front++;
return Q->data[Q->front];
}
}
void print(QueueType *Q)
{
printf("Front Pos : %d\n, Rear Pos : %d\n", Q->front, Q->rear);
for (int i = Q->front + 1; i <= Q->rear; i++)
{
printf("[%c] ", Q->data[i]);
}
printf("\n");
}
int main()
{
QueueType Q;
init(&Q);
enqueue(&Q, 'A');
enqueue(&Q, 'B');
enqueue(&Q, 'C');
print(&Q);
printf("[%c] \n", dequeue(&Q));
}
원형 큐 (더보기)
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
typedef char element;
typedef struct
{
element data[SIZE];
int rear, front;
} QueueType;
void init(QueueType *Q)
{
Q->rear = Q->front = 0;
}
int is_empty(QueueType *Q)
{
return Q->front == Q->rear;
}
int is_full(QueueType *Q)
{
return Q->front == (Q->rear + 1) % SIZE;
}
void enqueue(QueueType *Q, element e)
{
if (is_full(Q))
printf("Overflow\n");
else
{
Q->rear = (Q->rear + 1) % SIZE;
Q->data[Q->rear] = e;
}
}
element dequeue(QueueType *Q)
{
if (is_empty(Q))
{
printf("Empty\n");
return 0;
}
else
{
Q->front = (Q->front + 1) % SIZE;
return Q->data[Q->front];
}
}
element peek(QueueType *Q)
{
if (is_empty(Q))
{
printf("Empty\n");
return 0;
}
return Q->data[(Q->front + 1) % SIZE];
}
void print(QueueType *Q)
{
printf("Front Pos : %d\n, Rear Pos : %d\n", Q->front, Q->rear);
int i = Q->front; // 제일 앞에있는 원소 바로 하나 전부터 시작
while (i != Q->rear)
{
i = (i + 1) % SIZE;
printf("[%c]", Q->data[i]);
}
printf("\n");
}
int main()
{
QueueType Q;
init(&Q);
enqueue(&Q, 'A');
enqueue(&Q, 'B');
enqueue(&Q, 'C');
print(&Q);
printf("[%c] \n", dequeue(&Q));
}
도움이 되었다면 아래 '공감' 버튼을 눌러주세요! 읽어주셔서 감사합니다 :)