크래프톤 정글

링크드리스트(LinkedList) 구현 (C언어) : Part.3 - insert_front, print_list, find_node

고웅 2025. 4. 16. 11:03

이 전 포스팅에서는 링크드 리스트를 생성하고 값을 넣고 링크드 리스트를 해제하는 과정을 다루었다. 이번에는 링크드 리스트의 가장 앞에 노드를 추가하는 insert_front 함수가 현재 링크드 리스트에 있는 값을 전부 출력하는 print_list 마지막으로 링크드 리스트에서 특정 노드를 찾는 find_node까지 구현할 것이다.


1. 구현 목표

다음과 같은 기능을 이번에 구현할 것이다.

  • insert_front : 링크드 리스트 가장 앞에 추가
  • print_list : 현재 리스트 안의 값 전부 출력하기
  • find_node : 링크드 리스트 안의 특정 값 찾기

2. 기능 구현

🔨 insert_front

이 전 포스팅에서 insert_end를 구현했다. 마지막에 추가할 때는 링크드 리스트의 끝까지 찾아가는 반복문을 실행했는데 오히려 insert_front는 더 쉽게 느낄 수 있다.

구현 아이디어는 다음과 같다.

  1. 새로운 노드를 만든다. : create_node 함수 사용
  2. 링크드 리스트가 비어있는 상태 즉 최초로 삽입할 때는 그냥 바로 생성된 노드를 연결한다.
  3. 노드가 비어있지 않는 상태인 경우 새로 생성한 노드의 next값을 현재 head로 지정한다.
  4. head 값을 새로 생성한 노드로 재 지정한다.
void insert_front(Node** head, int data) {
    Node* new_node = create_node(data);
    if (new_node == NULL) {
        return;
    }
    if (*head == NULL) {
        *head = new_node;
        return;
    }
    new_node->next = *head;
    *head = new_node;
}

이게 끝이다. 간단하지 않은가?

🔨 print_list

print_list는 링크드 리스트 내부에 있는 값을 전부 출력하는 함수이다.

해당 기능의 구현 아이디어다.

  1. head 가 비었는지 확인하고 비어 있다면 NULL을 출력한다.
  2. cur 노드를 구성해서 cur 노드가 NULL일 때 까지 while을 이용해 반복한다.
  3. while을 통해 반복문을 돌면서 노드의 data를 출력한다.
  4. cur 노드를 cur->next 값으로 설정한다.
void print_list(Node* head) {
    Node* cur = head;

    while (cur) {
        printf("%d ", cur->data);
        cur = cur->next;
    }
    printf("NULL\n");
}

🔨 find_node

find_node 함수를 구현할 것이다. 이 함수는 인자로 들어온 값이 링크드 리스트 내부에 있는지 확인하고 있다면 해당되는 노드를 반환한다.

구현 아이디어는 다음과 같다.

  1. head가 NULL이면 찾을 수 있는 노드가 없으니 그냥 NULL을 리턴한다.
  2. cur이라는 현재 노드를 저장할 포인터 변수를 만들고 인자로 들어왔던 head를 지정한다.
  3. cur 이 NULL이 될때 까지 while을 이용해 반복을 한다.
  4. while 안에서 if 조건문을 사용하여 cur 노드의 data 값이 찾고 있는 데이터와 일치하는지 비교한다.
  5. 데이터가 맞다면 바로 해당 노드를 return을 한다.
  6. 찾고 있는 데이터가 아닌 경우 cur = cur->next로 하여 계속 반복을 진행하다.
  7. while을 전부 수행할 때까지 원하는 값이 링크드리스트에 없었을 경우 NULL을 반환한다.
Node* find_node(Node* head, int data) {
    if (head == NULL) return NULL;
    Node* cur = head;

    while (cur != NULL) {
        if (cur->data == data) {
            return cur;
        }
        cur = cur->next;
    }
    return NULL;
}

3. 기능 검증

이제 3개의 기능을 전부 구현했다. 이전과 마찬가지로 구현이 정상적으로 되었는지 검증을 진행할 것이다.

static char * test_insert_front() {
    Node* head = NULL;
    insert_front(&head, 10);
    insert_front(&head, 20);
    insert_front(&head, 30);
    // 리스트: 30 -> 20 -> 10
    print_list(head);
    mu_assert("insert_front failed at head", head->data == 30);
    mu_assert("insert_front failed at 2nd", head->next->data == 20);
    mu_assert("insert_front failed at 3rd", head->next->next->data == 10);
    free_list(head);
    return 0;
}

static char * test_find_node() {
    Node* head = NULL;
    insert_end(&head, 5);
    insert_end(&head, 10);
    insert_end(&head, 15);
    Node* found = find_node(head, 10);
    mu_assert("find_node failed to find 10", found != NULL && found->data == 10);

    Node* not_found = find_node(head, 99);
    mu_assert("find_node should return NULL for 99", not_found == NULL);
    free_list(head);
    return 0;
}

static char * test_find_in_empty_list() {
    Node* head = NULL;
    Node* found = find_node(head, 10);
    mu_assert("find_node on empty list should return NULL", found == NULL);
    return 0;
}

static char * all_tests() {
    mu_run_test(test_insert_end);
    mu_run_test(test_insert_front);
    mu_run_test(test_find_node);
    mu_run_test(test_find_in_empty_list);

    if (tests_failed > 0) {
        return "Some tests failed.";
    }

    return 0;
}


int tests_run = 0;
int tests_failed = 0;

int main(void) {
    char *result = all_tests();

    printf("========================================\n");
    printf("Tests run: %d\n", tests_run);
    printf("Tests passed: %d\n", tests_run - tests_failed);
    printf("Tests failed: %d\n", tests_failed);

    if (result != 0) {
        printf("❌ TESTS FAILED\n");
        return 1;
    }
    printf("✅ ALL TESTS PASSED\n");
    return 0;
}

print_list의 경우 실제 테스트를 하기는 어려워 그냥 테스트 코드 사이에 추가를 해서 출력 결과를 확인할 수 있도록 구성했다.

▶ Running test_insert_end...
10 20 30 NULL
✅ Passed test_insert_end (0.03 ms) // 이전 테스트 내용

▶ Running test_insert_front...
30 20 10 NULL
✅ Passed test_insert_front (0.01 ms)

▶ Running test_find_node...
✅ Passed test_find_node (0.00 ms)

▶ Running test_find_in_empty_list...
✅ Passed test_find_in_empty_list (0.00 ms)

========================================
Tests run: 4
Tests passed: 4
Tests failed: 0
✅ ALL TESTS PASSED

이렇게 출력이 되었다면 성공적으로 구현에 성공한 것이다.