주의사항
- vector와 차이점
push_front가 가능하다
[] 연산자로 임의접근이 불가능하다
- insert(a, data)
a의 위치를 나타내는 iterator 앞에 data를 연결한다
즉, a 앞에 삽입한다는 것이다
- insert 반환타입
insert는 반환을 하지 않는 push_back과 달리 iterator를 반환한다
- list 중간삽입/삭제의 진실
list 중간삽입/삭제는 O(1)이지만,
그 위치를 모른다면 탐색을 해야 하니 O(N)이 걸린다
연결리스트 구현을 위한 Node 구현
template<typename T>
class Node
{
public:
Node() : _prev(nullptr), _next(nullptr), _data(T())
{
}
Node(const T& value) : _prev(nullptr), _next(nullptr), _data(value)
{
}
public:
Node* _prev;
Node* _next;
T _data;
};
연결리스트 구현을 위한 Iterator 구현
template<typename T>
class Iterator
{
public:
Iterator() : _node(nullptr)
{
}
Iterator(Node<T>* node) : _node(node)
{
}
// ++it
Iterator& operator++()
{
_node = _node->_next;
return *this;
}
// it++
Iterator operator++(int)
{
Iterator<T> temp = *this;
_node = _node->_next;
return temp;
}
// --it
Iterator& operator--()
{
_node = _node->_prev;
return *this;
}
// it--
Iterator operator--(int)
{
Iterator<T> temp = *this;
_node = _node->_prev;
return temp;
}
// *it
T& operator*()
{
return _node->_data;
}
bool operator==(const Iterator& other)
{
return _node == other._node;
}
bool operator!=(const Iterator& other)
{
return _node != other._node;
}
public:
Node<T>* _node;
};
연결리스트 구현
template<typename T>
class MyList
{
public:
MyList() : _size(0)
{
// [head] <-> ... <-> [tail]
_head = new Node<T>();
_tail = new Node<T>();
_head->_next = _tail;
_tail->_prev = _head;
}
~MyList()
{
while (_size > 0)
pop_back();
delete _head;
delete _tail;
}
void push_back(const T& value)
{
AddNode(_tail, value);
}
void pop_back()
{
RemoveNode(_tail->_prev);
}
private:
// [head] <-> [1] <-> [prevNode] <-> [before] <-> [tail]
// [head] <-> [1] <-> [prevNode] <-> [newNode] <-> [before] <-> [tail]
Node<T>* AddNode(Node<T>* before, const T& value)
{
Node<T>* newNode = new Node<T>(value);
Node<T>* prevNode = before->_prev;
prevNode->_next = newNode;
newNode->_prev = prevNode;
newNode->_next = before;
before->_prev = newNode;
_size++;
return newNode;
}
// [head] <-> [prevNode] <-> [node] <-> [nextNode] <-> [tail]
// [head] <-> [prevNode] <-> [nextNode] <-> [tail]
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;
}
int size() { return _size; }
public:
using iterator = Iterator<T>;
iterator begin() { return iterator(_head->_next); }
iterator end() { return iterator(_tail); }
iterator insert(iterator it, const T& value)// it '앞에' 추가
{
Node<T>* node = AddNode(it._node, value);
return iterator(node);
}
iterator erase(iterator it)
{
Node<T>* node = RemoveNode(it._node);
return iterator(node);
}
private:
Node<T>* _head;
Node<T>* _tail;
int _size;
};
#include <iostream>
#include <list>
#include "MyList.h"
using namespace std;
int main()
{
//list<int> li;
MyList<int> li;
MyList<int>::iterator eraseIt;
for (int i = 0; i < 10; i++)
{
if (i == 5)
{
eraseIt = li.insert(li.end(), i);
}
else
{
li.push_back(i);
}
}
li.pop_back();
li.erase(eraseIt);
for (MyList<int>::iterator it = li.begin(); it != li.end(); it++)
{
cout << (*it) << endl;
}
}
'자료구조 & 알고리즘 > [루키스] C++ 자료구조 & 알고리즘' 카테고리의 다른 글
[C++ 자/알 Note] 큐 구현 (0) | 2025.01.08 |
---|---|
[C++ 자/알 Note] 스택 구현 (0) | 2025.01.08 |
[C++ 자/알 Note] 동적배열 구현 (0) | 2025.01.07 |
[C++ 자/알 Note] 배열, 동적배열, 연결리스트 (0) | 2025.01.04 |
[C++ 자/알 Note] 오른손 법칙 (미로 탐색) (0) | 2025.01.04 |