별의 공부 블로그 🧑🏻‍💻
728x90
728x170

단순 연결 리스트(Singly Linked List)

- 단순 연결 리스트는 노드들이 하나의 링크 필드를 가지며 이 링크 필드를 이용하여 모든 노드들이 연결되어 있음.

- 마지막 노드의 링크 필드 값은 NULL.

- 첫 번째 노드를 가리키는 포인터(헤드 포인터) 값만 알고 있으면 연결 리스트 안의 모든 노드에 접근이 가능함.

-> 하나의 단순 연결 리스트는 첫 번째 노드를 가리키는 하나의 포인터만 있으면 충분함.

- 헤드 포인터(head pointer) : 첫 번째 노드를 가리키는 포인터

 

코드

#include <stdio.h>

typedef int element;

typedef struct ListNode {
    element data;
    struct ListNode *link;
} ListNode;

void error(char *message) {
    fprintf(stderr, "%s\n", message);
    exit(1);
}

void insert_node(ListNode **phead, ListNode *p, ListNode *new_node) {
    if (*phead == NULL) { // 공백 리스트인 경우
        new_node->link = NULL;
        *phead = new_node;
    }
    else if (p = NULL) {    // p가 NULL이면 첫 번째 노드로 삽입
        new_node->link = *phead;
        *phead = new_node;
    }
}

void remove_node(ListNode **phead, ListNode *p, ListNode *removed) {
    if (p == NULL) {
        *phead = (*phead)->link;
    }
    else {
        p->link = removed->link;
    }
    free(removed);
}

ListNode *search(ListNode *head, int x) {
    ListNode *p;
    p = head;
    while (p != NULL) {
        if (p->data == x) return p;         // 탐색 성공
        p = p->link;
    }
    return p;
}

ListNode *concat(ListNode *head1, ListNode *head2) {
    ListNode *p;
    if (head1 == NULL) return head2;
    else if (head2 == NULL) return head1;
    else {
        p = head1;
        while (p->link != NULL) {
            p = p->link;
            p->link = head2;
            return head1;
        }
    }
}

ListNode *reverse(ListNode *head) {
    // 순회 포인터로 p, q, r을 사용
    ListNode *p, *q, *r;
    p = head;               // p는 아직 처리되지 않은 노드
    q = NULL;               // q는 역순으로 만들 노드
    while (p != NULL) {
        r = q;
        q = p;
        p = p->link;
        q->link = r;;       // q의 링크 방향을 바꾼다.
    }
    return q;               // q는 역순으로 된 리스트의 헤드 포인터
}

ListNode *create_node(element data, ListNode *link) {
    ListNode *new_node;
    new_node = (ListNode *)malloc(sizeof(ListNode));
    if (new_node == NULL) error("메모리 할당 에러");
    new_node->data = data;
    new_node->link = link;
    return new_node;
}

void display(ListNode *head) {
    ListNode *p = head;
    while (p != NULL) {
        printf("%d->", p->data);
        p = p->link;
    }
    printf("\b\b \n");      // 마지막에 -> 출력을 없애기 위함.
}

void display_recur(ListNode *head) {
    ListNode *p = head;
    if (p != NULL) {
        printf("%d->", p->data);
        display_recur(p->link);
    }
    else {
        printf("\b\b \n");  // 반복문 모습과 동일하게 출력하기 위함
    }
}

void free_list(ListNode **phead) {
    ListNode *removed, *p = *phead;
    while (p != NULL) {
        removed = p;
        p = p->link;
        *phead = p;
        free(removed);
    }
}

void main() {
    ListNode *list1 = NULL, *list2 = NULL;
    ListNode *p;

    insert_node(&list1, NULL, create_node(10, NULL));
    insert_node(&list1, NULL, create_node(20, NULL));
    insert_node(&list1, search(list1, 10), create_node(30, NULL));        // search 사용하여 중간노드 찾기
    insert_node(&list1, search(list1, 30), create_node(40, NULL));        // search 사용하여 중간노드 찾기
    insert_node(&list1, search(list1, 20), create_node(50, NULL));        // search 사용하여 중간노드 찾기
    insert_node(&list1, search(list1, 30), create_node(60, NULL));        // search 사용하여 중간노드 찾기
    display_recur(list1);        // list1 = 20->50->10->30->60->40

    remove_node(&list1, NULL, list1);        // 첫 번째 노드 삭제
    display(list1);            // list1 = 50->10->30->60->40
    remove_node(&list1, search(list1, 60), search(list1, 40));        // 마지막 노드 삭제
    display(list1);            // list1 = 50->10->30->60
    remove_node(&list1, search(list1, 50), search(list1, 10));        // 중간 노드 삭제
    display(list1);            // list1 = 50->30->60

    insert_node(&list2, NULL, create_node(80, NULL));
    insert_node(&list2, NULL, create_node(70, NULL));
    insert_node(&list2, search(list2, 70), create_node(90, NULL));
    display(list2);        // list2 = 79->90->80

    // list1 = list1 + list2
    list1 = concat(list1, list2);
    display(list1);            // list1 = 50->30->60->70->90->80

    // list1을 역순으로
    list1 = reverse(list1);
    display(list1);        // list1 = 80->90->70->60->30->50

    // list1에서 20 탐색
    p = search(list1, 20);
    if (p) {
        printf("탐색 성공: %d\n", p->data);
    }
    else {
        printf("탐색 실패\n");
    }
    free_list(&list1);        // 연결리스트에 있는 동적할당 받은 모든 노드 메모리 해제
    display(list1);            // 아무것도 안 나옴.
}

}

 

내용 출처 : C언어로 쉽게 풀어쓴 자료구조 (천인국 외 지음, 생능출판사)

728x90
그리드형(광고전용)

'Computer Science > Data Structure' 카테고리의 다른 글

[C] 그래프(Graph)  (0) 2017.06.19
[C] 정렬(Sorting)  (0) 2017.06.18
[C] 우선순위 큐(Priority Queue)  (0) 2017.06.17
[C] 트리(Tree)  (0) 2017.06.01
[C] 큐(Queue)  (0) 2017.05.23
[C] 스택(Stack)  (0) 2017.05.11
[C] 이중 연결 리스트(Doubly Linked List)  (0) 2017.05.06
[C] 원형 연결 리스트(Circular Linked List)  (0) 2017.05.02
⚠️AdBlock이 감지되었습니다. 원할한 페이지 표시를 위해 AdBlock을 꺼주세요.⚠️
starrykss
starrykss
별의 공부 블로그 🧑🏻‍💻


📖 Contents 📖