싱글 링크드 리스트

2015. 6. 21. 15:32엘키스공간/엘키스코딩공방

728x90
728x90

서론

아카데미 중간쯤에 정말 미친듯이 타임어택을 쳤던 그 코드!!

지금 하면 또 될지 모르겠지만 일단 구조 파악하는덴 역시.. 최강..

 

코드

#include <iostream>
#include <cstring>
using namespace std;

// 요소(데이터부)
typedef struct tagElement
{
    int        id;        // id로검색(중복체크)
    char    name[ _MAX_FNAME ];
}ELEMENT,*LPELEMENT;

// 노드
typedef struct NODE
{
    // 정적 상수인 정수 계열 데이터 멤버만 클래스 내부에서 초기화될 수 있습니다.
    static int nodeCount;
    LPELEMENT    element;    // 원소
    NODE        *next;        // 다음노드
}NODE,*LPNODE;

// 외부 초기화
int        NODE::nodeCount = 0;

// 리스트초기화
void    initList( LPNODE &head );
// 앞에 삽입
void    push_front( LPNODE &head, const LPELEMENT element );
// 뒤에 삽입
void    push_back( LPNODE &head, const LPELEMENT element );
// 앞에서 삭제
void    pop_front( LPNODE &head );
// 뒤에서 삭제
void    pop_back( LPNODE &head );

// 모두삭제
void    clear( LPNODE &head );
// 노드 검색
LPNODE    find( const LPNODE head, int findID );
// 노드 검색
LPNODE    find( const LPNODE head, const char *name );

// 편의
// 새로운 노드생성 및 초기화
LPNODE    getNewNode( const LPELEMENT element );
void deleteNode(LPNODE head);

// 출력
void    outputList( const LPNODE head );

void main( void )
{
    // 헤더선언
    LPNODE    head = NULL;

    // 초기화
    initList( head );
    // 원소삽입테스트용
    ELEMENT data;
    
    // 처음삽입
    data.id = 1;
    strcpy_s( data.name , _MAX_FNAME, "1길동");
    push_front( head, &data );
    outputList( head );

    data.id = 2;
    strcpy_s( data.name , _MAX_FNAME, "2길동");
    push_front( head, &data );
    outputList( head );

    data.id = 3;
    strcpy_s( data.name , _MAX_FNAME, "3길동");
    push_front( head, &data );
    outputList( head );

    // 마지막삽입
    data.id = 4;
    strcpy_s( data.name , _MAX_FNAME, "4길동");
    push_back( head, &data );
    outputList( head );

    data.id = 5;
    strcpy_s( data.name , _MAX_FNAME, "5길동");
    push_back( head, &data );
    outputList( head );

    data.id = 6;
    strcpy_s( data.name , _MAX_FNAME, "6;길동");
    push_back( head, &data );
    outputList( head );

    // 처음삭제
    pop_front( head );
    outputList( head );

    pop_front( head );
    outputList( head );

    // 마지막삭제
    pop_back( head );
    outputList( head );

    pop_back( head );
    outputList( head );

    // 찾기테스트
    // ID찾기
    LPNODE    findNode = find( head, 1 );

    if( NULL != findNode )
    {
        cout << findNode->element->id << endl;
        cout << findNode->element->name << endl;
    }
    findNode = find( head, "4길동" );
    // 이름찾기
    if( NULL != findNode )
    {
        cout << findNode->element->id << endl;
        cout << findNode->element->name << endl;
    }

    // 모두삭제
    clear( head );
    outputList( head );
}

// 리스트초기화
void    initList( LPNODE &head )
{
    // 헤더가 널이아니면
    if( NULL != head )
    {
        // 모두삭제
        clear( head );
    }
    // 헤더초기화
    head = NULL;
    NODE::nodeCount = 0;
}
// 앞에 삽입
void    push_front( LPNODE &head, const LPELEMENT element )
{
    // 헤더가 널이냐
    if( NULL == head )
    {
        // 함수버전
        head = getNewNode( element );
    }
    else
    {
        // 헤더갈아치우기
        LPNODE newNode = getNewNode( head->element );
        // 새로운노드삽입
        memmove_s( head->element, sizeof(ELEMENT), element, sizeof( ELEMENT));
        // 새로운노드와 연결
        newNode->next = head->next;
        // 헤더의 다음을 새노드로
        head->next = newNode;
    }
    // 노드 개수 증가
    NODE::nodeCount++;
}
// 뒤에 삽입
void    push_back( LPNODE &head, const LPELEMENT element )
{
        // 헤더가 널이냐
    if( NULL == head )
    {
        // 함수버전
        head = getNewNode( element );
    }
    else
    {
        LPNODE    tempNode = head;
        // 마지막노드찾기
        while( NULL != tempNode->next )
        {
            tempNode = tempNode->next;
        }

        // 다음노드연결
        tempNode->next = getNewNode(element);
    }
    // 노드 개수 증가
    NODE::nodeCount++;
}
// 앞에서 삭제
void    pop_front( LPNODE &head )
{
    if( NULL == head )
    {
        return;
    }

    // 헤더가 널이냐
    if( NULL == head->next )
    {
           // 헤더지우기
        deleteNode(head);
    }
    else
    {
        // 헤더의 다음백업
        LPNODE  headNext = head->next;
        deleteNode(head);
        // 헤더가 다음노드 물기
        head = headNext;
    }
    NODE::nodeCount--;
}

// 뒤에서 삭제
void    pop_back( LPNODE &head )
{
    // 헤더가 널이냐
    if( NULL == head->next )
    {
        deleteNode(head);
    }
    else
    {
        // 헤더의 다음백업
        LPNODE    delPrev = head;
        LPNODE    delNode = head->next;

        while( NULL != delNode->next )
        {
            // 다음으로
            delPrev = delPrev->next;
            delNode = delNode->next;
        }
        // delNode의 다임이 널이라는 소리다!!!
        deleteNode(delNode);
        // 이전꺼
        delPrev->next = NULL;
    }
    NODE::nodeCount--;
}

// 모두삭제
void    clear( LPNODE &head )
{
    while( NULL != head )
    {
        // 모드지우기( 널일때까지 )
        LPNODE back = head->next;

        // 지우기
        deleteNode(head);
        // 다음노드로
        head = back;
    }
    // 노드개수 0
    NODE::nodeCount = 0;
}
// 노드 검색
LPNODE    find( const LPNODE head, int findID )
{
    // 같은 ID의 노드 찾기
    if( NULL != head )
    {
        LPNODE tempNode = head;

        while( NULL != tempNode )
        {
            // 쇼트 서킷트기법에 의해
            if( NULL != tempNode->element && tempNode->element->id == findID )
            {
                return tempNode;
            }
            // 순회
            tempNode = tempNode->next;
        }
    }
    
    return NULL;
}
// 노드 검색
LPNODE    find( const LPNODE head, const char *name )
{
    // 같은 이름의 노드 찾기
    if( NULL != head )
    {
        LPNODE tempNode = head;

        while( NULL != tempNode )
        {
            // 쇼트 서킷트기법에 의해
            if( NULL != tempNode->element && 
                strcmp(tempNode->element->name , name) == 0 )
            {
                return tempNode;
            }
            // 순회
            tempNode = tempNode->next;
        }
    }
    
    return NULL;
}

// 편의
// 새로운 노드생성 및 초기화
LPNODE    getNewNode( const LPELEMENT element )
{
    // 노드 선언 및 할당
    LPNODE    newNode = new NODE;
    // 원소할당
    newNode->element = new ELEMENT;
    // 노드의 원소 복사
    memmove_s( newNode->element , sizeof( ELEMENT ), element,  sizeof( ELEMENT ) ); 
    // 새로운 노드의 다음을 널로
    newNode->next = NULL;
    // 새로운 노드 반환
    return newNode;
}

void deleteNode(LPNODE delNode)
{
        // 헤더지우기
        if( NULL != delNode->element )
        {
            delete delNode->element;
            delNode->element = NULL;
        }
        delete delNode;
        delNode = NULL;
}

// 출력
void    outputList( const LPNODE head )
{
    cout <<"==================== 리스트 출력 ===================="<<endl;
    cout <<"노드개수 : " << NODE::nodeCount << endl;
    // 헤더확인
    if( NULL != head )
    {
        // 임시물기
        LPNODE    tempNode = head;
        // 출력    
        while( NULL != tempNode )
        {
            if( NULL != tempNode->element )
            {
                cout << "ID : " << tempNode->element->id << endl;
                cout << "NAME : " << tempNode->element->name << endl;
            }
            // 다음으로 이동
            tempNode = tempNode->next;
        }
    }
    cout <<"====================================================="<<endl;
}

 

 

 

 

728x90
반응형

'엘키스공간 > 엘키스코딩공방' 카테고리의 다른 글

counted_ptr 구현  (0) 2015.07.28
비트 조작 유틸로 만들기  (0) 2015.07.13
더블 링크드 리스트  (1) 2015.06.21
큐로 메시지 큐 구현하기  (0) 2015.06.10
큐 구현하기  (0) 2015.06.10
[코딩] 스택 구현하기  (1) 2015.06.10
가위바위보 게임 만들기  (0) 2015.03.24