—ฅ/ᐠ. ̫ .ᐟ\ฅ —

과목 일반

[자료구조] 0930 Review - 자기 참조 구조체 Node 문제

WIFI-Aircat 2024. 12. 24. 22:30
💾 Data Structure
: 0930 Review - Self-referential structure - Node

🤍 self-referential structure

Output : `1 -> 2 -> 3 -> NULL`

1. 구조체 선언

typedef struct Node {
    int data; // 노드에 저장할 데이터
    struct Node* next; // 다음 노드를 가리키는 포인터
} Node;

 


2. main

int main(){
    Node* head = NULL; // 연결 리스트의 첫 번째 노드를 가리키는 포인터
    int newData[] = {1, 2, 3}; // 추가할 데이터

    for (int i = 0; i < 3; i++){
        appendNode(&head, newData[i]); // 생성한 노드를 리스트에 추가하는 함수
    }

    printList(head); // 리스트 출력하는 함수
    freeList(head); // 리스트 메모리 해제하는 함수

    return 0;
}



3. `Node* createNode(int data)` : 노드 생성

Node* createNode(int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) {
        printf("alloc err\n");
        exit(1);
    }
    newNode->data = data;
    newNode->next = NULL;
    return newNode; // 새 노드 반환
}


- `Node* newNode`
    - 새로 생성될 노드를 가리키는 포인터.
    - `malloc`으로 메모리를 동적으로 할당하고 이 메모리 주소를 `newNode`에 저장
    - `newNode` : Node 구조체를 가리키는 구조체 포인터. 구조체 Node가 할당된 메모리 위치를 가리킴.

- `newNode->data = data;`
    - newNode가 가리키는 Node 구조체의 data 필드에 data 값 저장

- `newNode->next = NULL;`
    - newNode가 가리키는 Node 구조체의 next 필드에 NULL 값 저장
    - next 필드는 또 다른 Node 구조체를 가리키는 포인터


4. `void appendNode(Node** head, int data)` : 노드 추가

void appendNode(Node** head, int data) {
    Node* newNode = createNode(data); // 새로운 노드 생성

    if (*head == NULL) {
        *head = newNode; // head가 NULL을 가리키면(리스트가 비어있으면) 새 노드를 헤드로
    } else {
        Node* temp = *head; // 리스트 탐색을 위한 임시 포인터
        while (temp->next != NULL) {
            temp = temp->next; // 리스트 끝으로 이동
        }
        temp->next = newNode; // 새 노드를 리스트의 끝에 추가
    }
}



- `Node** head` : 연결 리스트의 첫 번째 노드를 가리킴
    - 이중 포인터( `Node**` )를 사용하는 이유 : 리스트가 비어 있다면 새로운 노드를 첫 번째 노드로 할당해야 하므로, 이중 포인터를 사용해야 head가 가리키는 값(리스트의 첫 번째 노드)이 직접 변경

- 리스트가 비어 있을 때 ( `if (*head == NULL)` )
    - `*head = newNode`로 `head`가 가리키는 위치를 새로운 노드로 변경해서 새로운 노드를 리스트의 첫 번재 노드로 설정.

- 리스트가 비어 있지 않을 때 ( `*head != NULL` )
    - 새로운 노드를 리스트 끝에 추가해야 하므로 임시 포인터 `temp`로 리스트 끝까지 탐색
    - `temp = *head` : `temp` 포인터를 첫 번째 노드로 초기화
    - `while (temp->next != NULL)`으로 `temp`가 가리키는 노드가 리스트의 마지막 노드에 도달할 때까지 반복문을 통해 이동.

- 새 노드를 리스트 끝에 추가:
    - `temp->next = newNode;` : 마지막 노드의 `next` 포인터가 새로운 노드를 가리키도록 설정

 


5. `void printList(Node* head)` : 리스트 출력

void printList(Node* head) {
    Node* temp = head; // 리스트의 첫 번째 노드를 가리키는 임시 포인터
    while (temp != NULL) {
        printf("%d -> ", temp->data); // 현재 노드의 데이터 출력
        temp = temp->next; // 다음 노드로 이동
    }
    printf("NULL\n"); // 리스트 끝을 나타내기 위해 NULL 출력
}


- `Node* temp` : 리스트의 현재 노드를 가리키는 포인터. `head` 포인터에서 시작하여 리스트를 순회.
- 각 노드를 방문하며 `temp->data`로 노드의 데이터를 출력. `->` 연산자로 포인터가 가리키는 구조체의 필드에 접근
- 리스트의 모든 노드를 출력한 후 NULL을 출력하여 리스트의 끝 나타냄

 


6. `void freeList(Node* head)` : 리스트 메모리 해제

void freeList(Node* head) {
    Node* temp;
    while (head != NULL) {
        temp = head; // 현재 노드를 임시 변수에 저장
        head = head->next; // 다음 노드로 이동
        free(temp); // 현재 노드 메모리 해제
    }
}


- `temp = head;` : `head` 포인터가 가리키는 현재 노드를 temp에 저장
- `head = head->next;` : `head`를 다음 노드로 이동
- while문으로 리스트의 모든 노드에 반복
- `head == NULL`이면 모든 노드의 메모리가 해제된 상태


 

반응형