[C언어] 큐(Queue) 구현 실습하기

2025. 4. 13. 17:12·크래프톤 정글/Code 정글(C언어)

큐(Queue) 구현 실습하기

이번 큐 구현 실습은 이전에 다뤘던 연결 리스트(Linked List) 구현체를 그대로 활용하여 진행됩니다. 즉, 연결 리스트를 기반으로 한 큐(Queue) 를 C 언어로 구현해보는 실습입니다.

 

따라서, 연결 리스트를 구현해본 적이 없다면 [연결 리스트 구현 실습하기]를 한 번 따라가 보셔도 좋고, 큐 구현부터 시작하고 싶다면 해당 글에서 연결 리스트의 구성과 기본 함수 정의만 빠르게 훑고 넘어오셔도 괜찮습니다.

 

 

필요한 구조체, 함수 정의하기

구조체

  • Queue: (struct) 큐 구조체
    • ll: (LinkedList) 큐 연산 구현을 위한 연결 리스트 구조체
  • LinkedList: (struct) 연결 리스트 구조체
  • ListNode: (struct) 노드 구조체

함수 (추천 구현 순서)

  • void enqueue(Queue *q, int item): 큐의 뒤에 요소 추가
  • int isEmptyQueue(Queue *q): 큐가 비어있는지 확인
  • int dequeue(Queue *q): 큐의 앞에서 요소를 꺼내고 제거
  • void removeAllItemsFromQueue(Queue *q): 큐의 모든 요소를 제거
  • ListNode *findNode(LinkedList *ll, int index): 연결 리스트에서 index에 해당하는 노드의 주소를 찾아 반환
  • int insertNode(LinkedList *ll, int index, int value): index 위치에 새 노드를 삽입. 성공 시 0, 실패 시 -1 반환
  • int removeNode(LinkedList *ll, int index): index 위치의 노드를 삭제. 성공 시 0, 실패 시 -1 반환
  • void printList(LinkedList *ll): 연결 리스트의 모든 노드 값을 순서대로 출력
  • void removeAllItems(LinkedList *ll): 연결 리스트의 모든 노드를 제거하고 초기화

 

전체 실습 코드

연결 리스트를 활용한 큐 구현 실습용 뼈대 코드입니다. 각 함수에는 간단한 힌트가 주석으로 포함되어 있어, 스스로 고민하며 구현해볼 수 있게끔 되어 있습니다. 칠판이나 노트에 그림을 그려 보면서 기본 함수들을 하나씩 구현해 보세요.

#include <stdio.h>
#include <stdlib.h>

// 연결 리스트 구조체
typedef struct _listnode{
	int item;
	struct _listnode *next;
} ListNode;
// 노드 구조체
typedef struct _linkedlist{
	int size;
	ListNode *head;
} LinkedList;
// 큐 구조체
typedef struct _queue
{
	LinkedList ll;
} Queue;

// 기본 함수 선언
void enqueue(Queue *q, int item);
int isEmptyQueue(Queue *q);
int dequeue(Queue *q);
void removeAllItemsFromQueue(Queue *q);

ListNode *findNode(LinkedList *ll, int index);
int insertNode(LinkedList *ll, int index, int value);
int removeNode(LinkedList *ll, int index);
void printList(LinkedList *ll);
void removeAllItems(LinkedList *ll);

// 큐 기본 함수 확인용 프로그램
// 함수 구현 후 C파일을 실행해 제대로 동작하는지 테스트해볼 수 있습니다.
int main() {
    Queue q;
    q.ll.head = NULL;
    q.ll.size = 0;

    int c = 1;
    int value, result;

    printf("===== 큐 테스트 메뉴 =====\n");
    printf("1: enqueue(value)\n");
    printf("2: dequeue()\n");
    printf("3: isEmptyQueue()\n");
    printf("4: printList()\n");
    printf("5: removeAllItemsFromQueue()\n");
    printf("0: 종료\n");

    while (c != 0) {
        printf("\n메뉴 선택 (0~5): ");
        scanf("%d", &c);

        switch (c) {
        case 1:
            printf("삽입할 값을 입력하세요: ");
            scanf("%d", &value);
            enqueue(&q, value);
            printf("삽입 성공!\n");
            printList(&(q.ll));
            break;

        case 2:
            result = dequeue(&q);
            if (result != -1) {
                printf("꺼낸 값: %d\n", result);
            } else {
                printf("큐가 비어 있습니다.\n");
            }
            printList(&(q.ll));
            break;

        case 3:
            if (isEmptyQueue(&q))
                printf("큐는 비어 있습니다.\n");
            else
                printf("큐에 값이 존재합니다.\n");
            break;

        case 4:
            printList(&(q.ll));
            break;

        case 5:
            removeAllItemsFromQueue(&q);
            printf("모든 요소 제거 완료!\n");
            printList(&(q.ll));
            break;

        case 0:
            removeAllItemsFromQueue(&q);
            printf("프로그램 종료.\n");
            break;

        default:
            printf("알 수 없는 선택입니다.\n");
            break;
        }
    }

    return 0;
}

// 큐의 뒤에 요소를 추가하는 함수
void enqueue(Queue *q, int item) {
    /*  리스트의 어느 위치에 넣는 게 적절할까요?
        add your code here  */
}

// 큐가 비어있는지 확인하는 함수
// 큐가 비어있으면 1, 아니면 0을 반환
int isEmptyQueue(Queue *q) {
    /*  연결 리스트의 어떤 값을 활용하면 될까요?
        add your code here  */
}

// 큐의 앞에서 요소를 꺼내고 제거하는 함수
// 큐가 비어있다면 -1, 아니면 꺼낸 값을 반환
int dequeue(Queue *q) {
    /*  먼저 확인해야 할 조건은 무엇일까요? 
        꺼낸 뒤에는 어떤 처리가 필요할까요?
        add your code here  */
}

// 큐의 모든 요소를 제거하는 함수
void removeAllItemsFromQueue(Queue *q) {
    /*  큐가 빌 때까지 어떤 작업을 반복하면 될까요?
        add your code here  */
}

// ==================== 기존 연결 리스트 기본 함수 ==================== //
// index에 해당하는 노드의 주소를 반환하는 함수
// 노드를 찾았다면 해당 노드, 노드를 찾을 수 없다면 NULL 반환
ListNode *findNode(LinkedList *ll, int index)
{
    if (ll == NULL || ll->head == NULL || index < 0 || index >= ll->size) return NULL;

    ListNode *cur = ll->head;
    int i = 0;
    while (i < index) {
        cur = cur->next;
        i++;
    }
    return cur;
}

// index 위치에 새로운 노드를 삽입하는 함수
// 성공 시 0, 실패 시 -1 반환
int insertNode(LinkedList *ll, int index, int value)
{
    if (index < 0 || index > ll->size) return -1;

    ListNode *pre;
    ListNode *new_node = malloc(sizeof(ListNode));
    new_node->item = value;
    new_node->next = NULL;
    if (index == 0) {
        new_node->next = ll->head;
        ll->head = new_node;
    } else {
        pre = findNode(ll, index -1);
        new_node->next = pre->next;
        pre->next = new_node;
    }

    ll->size++;
    return 0;
}

// index 위치의 노드를 삭제하는 함수
// 성공 시 0, 실패 시 -1 반환
int removeNode(LinkedList *ll, int index)
{
    if (ll == NULL || ll->head == NULL || index < 0 || index >= ll->size) return -1;

    ListNode *pre, *cur;
    if (index == 0) {
        cur = ll->head;
        ll->head = cur->next;
        free(cur);
    } else {
        pre = findNode(ll, index-1);
        cur = pre->next;
        
        pre->next = cur->next;
        free(cur);
    }

    ll->size--;
    return 0;
}

// 연결 리스트의 모든 노드 값을 순서대로 출력하는 함수
void printList(LinkedList *ll)
{
    ListNode *cur;
    printf("현재 연결 리스트: ");
    if (ll == NULL || ll->head == NULL) {
        printf("Empty\n");
    } else {
        cur = ll->head;
        while (cur != NULL) {
            printf("%d ", cur->item);
            cur = cur->next;
        }
        printf("\n");
    }
}

// 연결 리스트의 모든 노드를 제거하고 초기화하는 함수
void removeAllItems(LinkedList *ll)
{
    if (ll == NULL || ll->head == NULL) {
        return;
    }

    ListNode *cur;
    while (ll->head != NULL) {
        cur = ll->head;
        ll->head = cur->next;
        free(cur);
        ll->size--;
    }
    printf("리스트 초기화 완료\n");
}

 

 

큐 구현하기

각 함수에 주어진 매개변수(parameter)를 바탕으로, 먼저 해당 함수가 어떤 기능을 수행해야 하는지 논리적으로 생각해보고, 실제로 구현해봅니다.

 

각 함수는 어떤 기본 동작 흐름을 따르는지, 어떤 포인터 변수를 새로 만들어야 할지, 그리고 예외 상황(큐가 비어 있는 경우)에는 어떻게 대응해야 할지도 함께 고민해보면 더 좋습니다. 그리고 연결 리스트 기반 큐이므로, 기존 연결 리스트 기본 함수들을 사용해서 큐의 기본 함수들을 구현해도 상관 없습니다.

 

enqueue 함수

큐의 뒤에 요소를 추가하는 함수

  • *q: (pointer) 큐 주소
  • item: (int) 추가할 요소의 값

enqueue 구현하기

// 큐의 뒤에 요소를 추가하는 함수
void enqueue(Queue *q, int item) {
    // 연결 리스트의 size 위치(=맨 뒤)에 노드를 삽입
    insertNode(&(q->ll), q->ll.size, item);
}

 

isEmptyQueue 함수

큐가 비어있는지 확인하는 함수

  • *q: (pointer) 큐 주소

isEmptyQueue 구현하기

// 큐가 비어있는지 확인하는 함수
// 큐가 비어있으면 1, 아니면 0을 반환
int isEmptyQueue(Queue *q) {
    if (q->ll.size == 0) {
        return 1;
    }
    return 0;
}

 

dequeue 함수

큐의 앞에서 요소를 꺼내고 제거하는 함수

  • *q: (pointer) 큐 주소

dequeue 구현하기

// 큐의 앞에서 요소를 꺼내고 제거하는 함수
// 큐가 비어있다면 -1, 아니면 꺼낸 값을 반환
int dequeue(Queue *q) {
    if (isEmptyQueue(q)) return -1;           // 비어 있으면 -1 반환

    int val = q->ll.head->item;               // 맨 앞 노드의 값 꺼내기
    removeNode(&(q->ll), 0);                  // index 0 위치 제거
    return val;                               // 꺼낸 값 반환
}

 

removeAllItemsFromQueue 함수

큐의 모든 요소를 제거하는 함수

  • *q: (pointer) 큐 주소

removeAllItemsFromQueue 구현하기

// 큐의 모든 요소를 제거하는 함수
void removeAllItemsFromQueue(Queue *q) {
    // 이미 비어 있다면 return
    if (isEmptyQueue(q)) return;
    // 큐가 빌 때까지 dequeue 반복
    while (!isEmptyQueue(q)) dequeue(q);
}
저작자표시 비영리 변경금지 (새창열림)

'크래프톤 정글 > Code 정글(C언어)' 카테고리의 다른 글

[C언어] Stack&Queue(1) - createQueueFromLinkedList 함수 구현하기  (0) 2025.04.13
[C언어] 스택(Stack) 구현 실습하기  (0) 2025.04.13
[C언어] Linked List (7) - recursiveReverse함수 구현하기  (0) 2025.04.13
[C언어] Linked List (6) - moveMaxToFront 함수 구현하기  (0) 2025.04.13
[C언어] Linked List (5) - frontBackSplitLL 함수 구현하기  (0) 2025.04.13
'크래프톤 정글/Code 정글(C언어)' 카테고리의 다른 글
  • [C언어] Stack&Queue(1) - createQueueFromLinkedList 함수 구현하기
  • [C언어] 스택(Stack) 구현 실습하기
  • [C언어] Linked List (7) - recursiveReverse함수 구현하기
  • [C언어] Linked List (6) - moveMaxToFront 함수 구현하기
그냥사람_
그냥사람_
IT 관련 포스팅을 합니다. 크래프톤 정글 8기 정경호
  • 그냥사람_
    그냥코딩
    그냥사람_
  • 전체
    오늘
    어제
    • 글 전체보기 N
      • 크래프톤 정글 N
        • 로드 투 정글(입학시험)
        • CS기초(키워드, 개념정리)
        • 컴퓨터구조(CSAPP)
        • Code 정글(C언어)
        • Equipped in 정글(나만무) N
        • 마이 정글(WIL, 에세이)
      • 자료구조&알고리즘
        • 자료구조
        • 알고리즘
      • 일상
  • 블로그 메뉴

    • 홈
  • 링크

    • Github
  • hELLO· Designed By정상우.v4.10.3
그냥사람_
[C언어] 큐(Queue) 구현 실습하기
상단으로

티스토리툴바