5.1 list 구현

이제 STL의 list를 모델로 정의한 list를 구현합시다. 설명은 주석으로 해 놓았어요.

#pragma once
namespace ehlib
{ 
    template<typename Data>
    class list
    {
        //리스트 내부에 노드를 정의합시다. 
        //여기에서는 링크가 두 개 있는 노드를 정의할게요.
        struct node
        {
            Data data;
            node *prev;
            node *next;
            node(Data data=0)
            {
                this->data = data;
                prev = next = 0;
            }
        };
        //리스트에는 맨 앞 노드와 맨 뒤 노드를 기억하는
        //head와 tail 멤버를 선언하세요. 
        node *head;
        node *tail;
        //보관한 데이터 개수를 기억하는 멤버도 선언하세요.
        int count;
    public:
        class iterator
        {
            //반복자는 보관한 자료의 위치를 기억하고 있어야 합니다. 
            //리스트에는 자료를 노드에 보관하므로 노드의 위치를 멤버로 선언하세요.
            node *now;
        public:
            //생성자는 기본 생성이 가능하게 디폴트 인자를 사용하세요. 
            iterator(node *now=0)
            {         
                this->now = now;
            }
            //간접 연산으로 보관한 자료를 반환하게 구현하세요.
            Data operator *()const
            {
                 return now->data;
            }

            //리스트 내부에서는 반복자 내부 
            //노드의 위치 정보를 알 수 있어야 합니다. 
            //여기에서는 묵시적 형 변환 연산을 정의할게요.
            operator node *()
            {
                return now;
            }
            //증가 연산자에서는 now를 다음 위치로 이동하세요.
            iterator &operator++()
            {
                now = now->next;
                return (*this);
            }
            //나머지 증가 연산자도 now를 다음 위치로 이동하세요.
            const iterator operator++(int)
            {
                iterator re(*this);
                now = now->next;
                return re;
            }
            bool operator !=(const iterator &iter)const
            {   
                return now != iter.now;
            }
            bool operator ==(const iterator &iter)const
            {
                return now == iter.now;
            }
        };
        typedef iterator const_iterator;

        //생성자를 정의합시다.
        list()
        {
            //생성자에서는 head와 tail에 더미 노드를 생성하고 링크를 조절하세요. 
            //여기에서 작성하는 이중 연결리스트는 3.2.2에서 작성했던 
            //더미있는 이중 연결리스트입니다.
            head = new node();
            tail = new node();
            head->next = tail;
            tail->prev = head;
            //보관한 자료의 개수를 0으로 설정하세요.
            count = 0;
        }

        //소멸자를 정의합시다.
        ~list()
        {
            //맨 앞의 노드부터 순차적으로 소멸하세요. 
            node *prev=0;
            //head가 존재하면 반복하세요.
            while(head !=0)
            {
                //head를 이동하기 전에 prev에 기억하세요.
                prev = head;
                head = head->next;
                //기억해 두었던 prev의 노드를 소멸하세요.
                delete prev;
            }
        }

        //순차적으로 보관하는 push_back 메서드를 구현합시다.
        void push_back(Data data)
        {
            //순차 보관하는 push_back에서는 
            //insert 메서드를 이용하여 맨 끝에 보관합니다.
            insert(end(),data);
        }

        //특정 위치 앞에 보관하는 insert 메서드를 구현합시다.
        void insert(iterator at, Data data)
        {
            //자료를 보관할 노드를 생성하세요.
            node *now = new node(data);
            //반복자 형식에는 node * 형식으로 묵시적 형 변환을 정의하였습니다. node * 형식으로 얻어오세요.
            node *pos = at;
            //now 노드를 pos 앞에 매달기 위해 링크를 조절하세요. 
            //자세한 내용은 3.2.2를 참고하세요.
            now->next = pos;
            now->prev = pos->prev;
            pos->prev->next = now;
            pos->prev = now;
            //보관한 자료 개수를 1 증가하세요.
            count++;
        }

        //특정 위치의 자료를 제거하는 erase 메서드를 구현합시다.
        void erase(iterator at)
        {
            node *now = at;
            //삭제할 노드의 링크를 끊어야겠죠.
            now->prev->next = now->next;
            now->next->prev = now->prev;
            //자료를 보관한 노드를 소멸하고 보관한 자료 개수를 1 감소하세요.
            delete now;
            count--;
        }

        iterator begin()
        {
            //head는 더미 노드를 가리키므로 
            //head의 next가 자료를 보관하고 있는 첫 번째 노드입니다.
            iterator iter(head->next);
            return iter;
        }
        iterator end()
        {
            //end는 맨 마지막 자료를 보관한 다음 위치를 의미하죠. 
            //tail이 가리키는 노드는 맨 마지막 자료를 보관한 다음 위치입니다.
            iterator iter(tail);
            return iter;
        }
        const_iterator begin()const
        {
            iterator iter(head->next);
            return iter;
        }
        const_iterator end()const
        {            
            iterator iter(tail);
            return iter;
        }
        size_t size()
        {
            //보관한 자료 개수를 반환하세요.
            return count;
        }        
    };
}