C 언어로 이중 연결 리스트 구현하기

CBeginner
지금 연습하기

소개

이 프로젝트에서는 C 언어로 이중 연결 리스트 자료 구조를 구현하는 방법을 배우게 됩니다. 이중 연결 리스트는 각 노드가 이전 노드와 다음 노드 모두에 대한 포인터를 포함하는 연결 리스트의 한 유형으로, 정방향 및 역방향 모두에서 효율적인 탐색을 가능하게 합니다.

👀 미리보기

$ gcc test_list.c list.c -o test
$ ./test
welcome
to
labex
online

🎯 과제

이 프로젝트에서 다음을 배우게 됩니다:

  • 이중 연결 리스트를 초기화하는 방법
  • 이중 연결 리스트를 탐색하고 각 노드에 대해 콜백 함수를 실행하는 방법
  • 이중 연결 리스트에서 주어진 노드 뒤에 새 노드를 삽입하는 방법
  • 이중 연결 리스트에서 주어진 노드 앞에 새 노드를 삽입하는 방법
  • 이중 연결 리스트에서 노드를 삭제하는 방법

🏆 성과

이 프로젝트를 완료하면 다음을 수행할 수 있습니다:

  • 이중 연결 리스트의 기본 구조와 연산을 이해합니다.
  • 이중 연결 리스트 관리에 필요한 핵심 함수를 구현합니다.
  • C 언어에서 포인터와 동적 메모리 할당을 사용하는 능력을 보여줍니다.
  • 제공된 이중 연결 리스트 구현을 수정하고 개선하기 위해 지식을 적용합니다.

세그멘테이션 오류 수정

이 단계에서는 free_list 함수가 노드를 해제한 후 current 포인터를 업데이트하지 않아 세그멘테이션 오류가 발생합니다. 이 문제를 지금 수정해야 합니다.

  1. list.c 파일에서 free_list() 함수를 찾습니다.
  2. 업데이트된 free_list() 함수는 다음과 같습니다:
void free_list(struct List* list) {
    struct Node* current = list->head;
    struct Node* next = NULL;

    while (current) {
        next = current->next;
        free(current);
        current = next; // Updated
    }
    free(list);
}
✨ 솔루션 확인 및 연습

주어진 노드 뒤에 노드 삽입

이 단계에서는 이중 연결 리스트에서 주어진 노드 뒤에 새 노드를 삽입하는 방법을 배우게 됩니다.

  1. list.c 파일에서 insert_after() 함수를 찾습니다.
  2. 이 함수는 struct List*, struct Node* (새 노드를 삽입할 노드), 그리고 새 노드의 data를 인수로 받습니다.
  3. 이 함수는 새로운 struct Node를 생성하고 제공된 data로 해당 data 필드를 초기화해야 합니다.
  4. 그런 다음 함수는 새 노드와 prev 노드의 nextprev 포인터를 업데이트하여 새 노드를 올바르게 삽입해야 합니다.
  5. 마지막으로, 새 노드가 리스트의 끝에 삽입되는 경우 함수는 tail 포인터를 업데이트해야 합니다.

업데이트된 insert_after() 함수는 다음과 같습니다:

void insert_after(struct List* list, struct Node* prev, void* data) {
    struct Node* newnode = (struct Node *) malloc(sizeof(struct Node));
    newnode->data = data;

    if (prev) { // Updated
        newnode->next = prev->next;
        newnode->prev = prev;
        prev->next = newnode;
        if (newnode->next) newnode->next->prev = newnode;
        else list->tail = newnode; // Updated
    } else {
        newnode->next = list->head;
        newnode->prev = NULL;
        if (list->head) list->head->prev = newnode;
        else list->tail = newnode; // Updated
        list->head = newnode;
    }
}
  1. insert_after (list, NULL, data);를 찾아 다음 코드로 변경합니다:
insert_after (list, list->tail, data);
✨ 솔루션 확인 및 연습

주어진 노드 앞에 노드 삽입

이 단계에서는 이중 연결 리스트에서 주어진 노드 앞에 새 노드를 삽입하는 방법을 배우게 됩니다.

  1. list.c 파일에서 insert_before() 함수를 찾습니다.
  2. 이 함수는 struct List*, struct Node* (새 노드를 삽입할 노드), 그리고 새 노드의 data를 인수로 받습니다.
  3. 이 함수는 새로운 struct Node를 생성하고 제공된 data로 해당 data 필드를 초기화해야 합니다.
  4. 그런 다음 함수는 새 노드와 next 노드의 nextprev 포인터를 업데이트하여 새 노드를 올바르게 삽입해야 합니다.
  5. 마지막으로, 새 노드가 리스트의 시작 부분에 삽입되는 경우 함수는 head 포인터를 업데이트해야 합니다.

업데이트된 insert_before() 함수는 다음과 같습니다:

void insert_before(struct List* list, struct Node* next, void* data) {
    struct Node* newnode = (struct Node *) malloc(sizeof(struct Node));
    newnode->data = data;

    if (next) { // Updated
        newnode->prev = next->prev;
        newnode->next = next;
        next->prev = newnode;
        if (newnode->prev) newnode->prev->next = newnode;
        else list->head = newnode; // Updated
    } else {
        newnode->prev = list->tail;
        newnode->next = NULL;
        if (list->tail) list->tail->next = newnode;
        else list->head = newnode; // Updated
        list->tail = newnode;
    }
}
  1. insert_before (list, NULL, data);를 찾아 다음 코드로 변경합니다:
insert_before (list, list->head, data);
✨ 솔루션 확인 및 연습

이중 연결 리스트에서 노드 삭제

이 단계에서는 이중 연결 리스트에서 노드를 삭제하는 방법을 배우게 됩니다.

  1. list.c 파일에서 delete_from() 함수를 찾습니다.
  2. 이 함수는 struct List*struct Node* (삭제할 노드) 를 인수로 받습니다.
  3. 이 함수는 주어진 노드를 리스트에서 제거하기 위해 인접 노드의 nextprev 포인터를 업데이트해야 합니다.
  4. 또한, 삭제된 노드가 리스트의 head 또는 tail인 경우 함수는 headtail 포인터도 업데이트해야 합니다.
  5. 마지막으로, 함수는 삭제된 노드가 차지하는 메모리를 해제해야 합니다.

업데이트된 delete_from() 함수는 다음과 같습니다:

void delete_from(struct List* list, struct Node* node) {
    if (node->prev) node->prev->next = node->next;
    else list->head = node->next; // Updated

    if (node->next) node->next->prev = node->prev;
    else list->tail = node->prev; // Updated

    free(node);
}

이제 list.c 파일의 이중 연결 리스트 구현이 올바르게 작동해야 합니다. 제공된 test_list.c 파일을 사용하여 이중 연결 리스트의 기능을 테스트할 수 있습니다. 테스트 결과는 다음과 같습니다:

$ gcc test_list.c list.c -o test
$ ./test
welcome
to
labex
online
✨ 솔루션 확인 및 연습

요약

축하합니다! 이 프로젝트를 완료했습니다. LabEx 에서 더 많은 랩을 연습하여 기술을 향상시킬 수 있습니다.