[C언어 소스] 원형 연결리스트 (단일 연결리스트, 순차 보관)

안녕하세요. 언제나 휴일이예요.

이번에는 원형 연결리스트 소스 코드예요. 노드에 링크가 한 개인 단일 연결리스트 형태이며 순차 보관하는 예제입니다.

소스 코드에서는 노드 정의, 연결리스트 초기화, 데이터 추가, 데이터 삭제, 데이터 검색, 전체 데이터 출력, 연결리스트 해제화로 구성합니다.

원형 연결리스트 실행 화면
원형 연결리스트 실행 화면

소스 코드

/*https://ehpub.co.kr
언제나 C언어 예제 Center
원형 연결리스트 - 단일 연결리스트, 순차 보관
노드 정의, 초기화, 보관, 삭제, 검색, 전체 출력, 해제
*/

#include 
#include 

typedef struct Node
{
    int data;
    struct Node *next;
}Node;

void InitList(Node **phead, Node **ptail);
void AddData(Node **phead, Node **ptail, int data);
void Remove(Node **phead, Node **ptail, Node *now);
Node *Find(Node *seek, int data);
void ViewAll(Node *head, Node *tail);
void Clear(Node **phead, Node **ptail);
int main()
{
    Node *head, *tail;
    InitList(&head, &tail);
    AddData(&head, &tail, 3); //3
    AddData(&head, &tail, 4); //3 4 
    AddData(&head, &tail, 6); //3 4 6
    AddData(&head, &tail, 9); //3 4 6 9
    ViewAll(head, tail);//3 4 6 9
    Node *seek = Find(head, 3);
    Remove(&head, &tail, seek);
    seek = Find(head, 4);
    if (seek)
    {
        printf("4를 보관한 노드를 찾았음\n");
        Remove(&head, &tail, seek);//3 6 9
        printf("4를 보관한 노드를 제거했음\n");
        ViewAll(head, tail);//3 6 9
    }
    Clear(head, tail);
    printf("전체 제거\n");
    ViewAll(head, tail);
    return 0;
}

void InitList(Node **phead, Node **ptail)
{
    *phead = NULL;
    *ptail = NULL;
}
void AddData(Node **phead, Node **ptail, int data)
{
    Node *now = (Node *)malloc(sizeof(Node));//새로운 노드 생성
    now->data = data; //생성한 노드에 data 설정

    if (*phead == NULL)//빈 상태일 때
    {
        *phead = *ptail = now;
        return;
    }

    (*ptail)->next = now;//맨 뒤 노드의 next를 now로 설정
    now->next = (*phead); //now의 next를 맨 앞 노드로 설정
    *ptail = now; //맨 뒤 노드를 now로 설정

}

void Remove(Node **phead, Node **ptail, Node *now)
{
    Node *prev = NULL;
    Node *seek = *phead;
    while (seek != *ptail) //seek가 맨 마지막 노드가 아니면
    {
        if (seek == now)//seek가 now와 같을 때
        {
            break;
        }
        prev = seek;//seek를 변경하기 전에 prev에 기억
        seek = seek->next;//seek를 다음으로 이동
    }
    
    if (seek == *ptail && seek != now)//now를 발견하지 못함 - 예외 발생
    {
        return;
    }

    if (seek == *phead)//seek가 맨 앞 노드
    {
        *phead = seek->next;
    }
    if (seek == *ptail)//seek가 맨 마지막 노드
    {
        *ptail = prev;
    }
    if (prev)//이전 노드가 있을 때
    {
        prev->next = seek->next;
    }
    free(seek);
}

Node *Find(Node *seek, int data)
{
    Node *at = seek;
    if (seek == NULL)
    {
        return NULL;
    }
    do
    {
        if (seek->data == data)//찾았을 때
        {
            return seek;
        }
        seek = seek->next;//seek를 다음으로 이동
    } while (seek != at); //seek가 참이면(NULL 이 아니면)
    return NULL;//못 찾았을 때
}
void ViewAll(Node *head, Node *tail)
{
    Node *seek = head;
    int i = 0;
    if (head == NULL)
    {
        printf("비어 있습니다.\n");
        return;
    }
    while (seek != tail) //seek가 tail이 아니면
    {
        i++;
        printf("[%2d]:%-05d ", i, seek->data);

        if (i % 5 == 0)//5의 배수일 때
        {
            printf("\n");//개행
        }
        seek = seek->next;//seek를 다음으로 이동
    }
    i++;
    printf("[%2d]:%-05d ", i, seek->data);
    printf("\n");
}

void Clear(Node **phead, Node **ptail)
{
    Node *prev = NULL;
    Node *seek = *phead;
    while (seek != *ptail) //seek가 마지막 노드가 아니면
    {
        prev = seek;//seek를 변경하기 전에 prev에 기억
        seek = seek->next;//seek를 다음으로 이동
        free(prev);//이전 노드 메모리 해제
    }
    //현재 seek는 *ptail 임
    free(seek);//마지막 노드 메모리 해제
    *phead = *ptail = NULL;//이제 맨 앞 노드가 없음
}