C/자료구조와 알고리듬
                
              Chapter 08. 연결 리스트(Linked List)
                GameStudy
                 2021. 11. 12. 20:42
              
                          
            0. 연결리스트
- 연결되지 않은 메모리를 사용함. 배열과 정반대의 장단점.
이때문에, 중간 삽입 중간 삭제가 아주 쉬움.
- 단점은 N번째 방을 바로 찾을수가 없음. 배열과 다름.
즉, Random Access가 불가능함.
1. 기본 코드
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
enum {
    FALSE = 0,
    TRUE = 1,
    INVALID_INDEX = -1
};
typedef struct node {
    int             nData;
    struct node*    pNext;
    /* struct node_t* 라고 적으면 안됨. */
} node_t;
void destroy(node_t* _pHeadNode);
void recursively_destroy(node_t* _pCurrentNode);
void insert_front(node_t** _dpHeadNode, int _nData);
void orderly_insert_front(node_t** _dpHeadNode, int _nData);
void insert_back(node_t** _dpHeadNode, int _nData);
void remove_node(node_t** _dpHeadNode, int _nData);
void print(node_t* _pHeadNode);
int main(void)
{
    node_t* my_linked_list_head = (node_t*)malloc(sizeof(node_t));
    my_linked_list_head->nData = 0;
    my_linked_list_head->pNext = NULL;
    insert_front(&my_linked_list_head, 1);
    insert_front(&my_linked_list_head, 9);
    printf("The result of insert_front(1) and insert_front(9).\n");
    print(my_linked_list_head);
    printf("\n\n");
    insert_back(&my_linked_list_head, 8);
    insert_back(&my_linked_list_head, 3);
    print(my_linked_list_head);
    printf("\n\n");
    orderly_insert_front(&my_linked_list_head, 4);
    orderly_insert_front(&my_linked_list_head, 10);
    print(my_linked_list_head);
    printf("\n\n");
    insert_back(&my_linked_list_head, 100);
    insert_back(&my_linked_list_head, 120);
    print(my_linked_list_head);
    printf("\n\n");
    remove_node(&my_linked_list_head, 4);
    print(my_linked_list_head);
    printf("\n\n");
    destroy(my_linked_list_head);
    return 0;
}
void destroy(node_t* _pHead)
{
    printf("destroy() has been called. -> ");
    recursively_destroy(_pHead);
    printf("Close to destroy.\n\n");
}
void recursively_destroy(node_t* _pCurrentNode)
{
    if (NULL == _pCurrentNode)
    {
        return;
    }
    recursively_destroy(_pCurrentNode->pNext);
    printf("[%d] has been Deleted. -> ", _pCurrentNode->nData);
    free(_pCurrentNode);
}
void insert_front(node_t** _dpHeadNode, int _nData)
{
    node_t* pNewNode = (node_t*)malloc(sizeof(node_t));
    pNewNode->nData = _nData;
    pNewNode->pNext = (*_dpHeadNode)->pNext;
    (*_dpHeadNode)->pNext = pNewNode;
}
void orderly_insert_front(node_t** _dpHeadNode, int _nData)
{
    node_t** dpCurrentNode = _dpHeadNode;
    node_t* pNewNode = (node_t*)malloc(sizeof(node_t));
    pNewNode->nData = _nData;
    while (NULL != *dpCurrentNode)
    {
        if (pNewNode->nData <= (*dpCurrentNode)->nData)
        {
            break;
        }
        dpCurrentNode = &((*dpCurrentNode)->pNext);
        /* *dpCurrentNode = ((*dpCurrentNode)->pNext); 하면 안됨. */
    }
    pNewNode->pNext = *dpCurrentNode;
    *dpCurrentNode = pNewNode;
    /* pp = &pNewNode; 하면 안됨. */
}
void insert_back(node_t** _dpHeadNode, int _nData)
{
    node_t** dpCurrentNode = _dpHeadNode;
    node_t* pNewNode = (node_t*)malloc(sizeof(node_t));
    pNewNode->nData = _nData;
    pNewNode->pNext = NULL;
    while (NULL != *dpCurrentNode)
    {
        dpCurrentNode = &((*dpCurrentNode)->pNext);
    }
    *dpCurrentNode = pNewNode;
}
void remove_node(node_t** _dpHeadNode, int _nData)
{
    node_t** dpCurrentNode = _dpHeadNode;
    while (NULL != *dpCurrentNode)
    {
        if (_nData == (*dpCurrentNode)->nData)
        {
            node_t* pTempNode = *dpCurrentNode;
            *dpCurrentNode = (*dpCurrentNode)->pNext;
            free(pTempNode);
            break;
        }
        dpCurrentNode = &(*dpCurrentNode)->pNext;
    }
}
void print(node_t* _pHead)
{
    node_t* pCurrentNode = _pHead;
    while(NULL != pCurrentNode)
    {
        printf("[%d:%p]->", pCurrentNode->nData, (void*)pCurrentNode->pNext);
        pCurrentNode = pCurrentNode->pNext;
    }
    printf("[NULL]\n");
}