1. 노드 구현하기
template<typename T>
class Node
{
public:
Node() : _next(nullptr), _prev(nullptr), _data(T())
{
}
Node(const T& value) : _next(nullptr), _prev(nullptr), _data(value)
{
}
public:
Node* _next; // 다음 노드의 주소를 담은 포인터, 노드 다음에는 노드가 있음(Node 형)
Node* _prev; // 이전 노드의 주소를 담은 포인터
T _data; // 각 노드의 값
};
2. 리스트 구현하기
template<typename T>
class List
{
public:
List() : _size(0)
{
_header = new Node<T>();
_header->_next = _header;
_header->_prev = _header;
}
~List()
{
while (_size > 0)
pop_back();
delete _header;
}
public:
Node<T>* _header;
int _size;
};
3. insert와 push_back 구현을 위한 AddNode 함수 구현하기
// [1] <-> [prevnode 2] <-> [node value] <-> [before 3] <-> [4] <-> [header] <->
Node<T>* AddNode(Node<T>* before, const T& value) // 이전(before)의 노드를 찾고 node를 추가
{
Node<T>* node = new Node<T>(value); // T 형, value 값을 가진 노드를 생성
Node<T>* prevnode = before->_prev;
prevnode->_next = node; // 이전 노드의 다음을 value 값의 노드를 가리키게 함
node->_prev = prevnode; // value 값의 노드의 prev를 이전 노드를 가리키게 함
node->_next = before; // value 값의 노드의 next를 이동 전 이전의 노드를 가리키게 함
before->_prev = node; // 이동 전 이전의 노드의 prev는 node를 가리키게 함
_size++;
return node;
}
2와 3 사이에 새로운 노드를 추가한다.
- prevnode : 리스트의 두 번째 요소, 2
- before : 리스트에서 세 번째 요소였던 것, 3
- node : 새롭게 리스트에서 세 번째 요소가 되는 것, value
- header : 더미 값을 가지고 있는 헤더
4. push_back 구현하기
void push_back(const T& value)
{
AddNode(_header, value);
}
헤더를 before로 넣어주면 헤더의 다음과 이전은 자기 자신을 가리키고 있기 때문에 적절히 잘 작동하게 된다.
[prevnode] <-> [node] <-> [header]의 구조가 완성되었다.
5. pop_back과 erase 구현을 위한 RemoveNode 구현하기
// pop_back과 erase 구현
// [1] <-> [2] <-> [node] <-> [4] <-> [header]
// [1] <-> [2] <-> [4] <-> [header]
Node<T>* RemoveNode(Node<T>* node)
{
Node<T>* prevnode = node->_prev;
Node<T>* nextnode = node->_next;
prevnode->_next = nextnode; // 노드가 사라졌으므로 다음노드와 이전노드가
nextnode->_prev = prevnode; // 서로를 가리키게 만듬
delete node;
_size--;
return nextnode;
}
6. pop_back 노드 구현
int size() {return _size};
void pop_back(const T& value)
{
RemoveNode(_header->_prev);
}
7. 반복자 구현
template<typename T>
class Iterator
{
public:
Iterator() : _node(nullptr)
{
}
Iterator(Node<T>* node) : _node(node)
{
}
public:
Node<T>* _node; // 어떤 노드를 가리키고 있는지 저장
};
(1) 증가 연산자 오버로딩
Iterator<T>& operator++ () // 전위형
{
_node = _node->_next;
return *this;
}
Iterator<T> operator++(int) // 후위형
{
Iterator<T> temp = *this; // 자신을 복사하여 임시 저장
_node = _node->_next;
return temp;
}
Iterator<T>& operator-- () // 전위형
{
_node = _node->_prev;
return *this;
}
Iterator<T> operator--(int) // 후위형
{
Iterator<T> temp = *this; // 자신을 복사하여 임시 저장
_node = _node->_prev;
return temp;
}
(2) 포인터 연산자 오버로딩
T& operator*()
{
return _node->_data;
}
(3) 비교 연산자 오버로딩
bool operator==(const Iterator& right)
{
return _node == right._node;
}
bool operator!=(const Iterator& right)
{
return _node != right._node;
}
8. begin, end, insert, erase 구현하기
이 코드들은 List 클래스 내부에서 작업한다.
public:
typedef Iterator<T> iterator;
iterator begin() { return iterator(_header->_next);}
iterator end() { return iterator(_header);}
iterator insert() (iterator it, const T& value)
{
Node<T>* node = AddNode(it._node, value);
return iterator(node);
}
iterator erase() {iterator it}
{
Node<T>* node = RemoveNode(it._node);
}
'기초 C++ 스터디 > 예제' 카테고리의 다른 글
9-9. STL 실습 (0) | 2023.06.19 |
---|---|
9-3. STL - Vector 구현하기 (실습) (0) | 2023.06.14 |
7-3. 디버깅 예제 #8 ~ 10 (0) | 2023.06.07 |
7-2. 디버깅 예제 #5 ~ 7 (0) | 2023.06.07 |
7-1. 디버깅 예제 #1 ~ 4 (0) | 2023.06.07 |