list模拟实现
由于list的底层是双向链表结构,因此在进行list模式实现时需要先定义一个结构体(节点),成员定义为三个:
_data:用来保存数据
_prev:用来指向上一个节点的指针
_next:用来指向下一个节点的指针
template <class T>
struct ListNode
{
T _data;
ListNode<T>* _next;
ListNode<T>* _prev;
ListNode(const T& val = T())
:_data(val)
, _next(nullptr)
, _prev(nullptr)
{}
};
之前实现vector迭代器时定义的begin函数直接返回start指针(该指针直接指向数据本身)。但由于在实现list迭代器时,list的指针指向的是节点类型。节点由包括data、prev、next。因此在进行解引用时,不会得到数据本身,同时进行++操作时也不会得到下一个节点的位置。
因此还需要定义一个迭代器结构体,其成员定义为:
_node:指向节点类型的指针。
同时也要重载一些运算符函数星号和++操作等,即实现以下逻辑(举例):
*it:_node->data;
++it:_node->next;
template <class T, class Ref, class Ptr>
struct ListIterator
{
typedef ListIterator<T, Ref, Ptr> Self;
ListIterator(ListNode<T>* node)
:_node(node)
{}
//*iterator:获取数据本身
Ref operator*()
{
return _node->_data;
}
//it->_a:内置类型可以通过解引用*来获得数据,当想引用自定义类型中的成员时,需要返回T*类型指针,再根据指针指向来获取自定义类型成员
//如:A* ptr = new A(1,2,3) 自定义类型A中有三个成员_a,_b,_c分别赋值1,2,3. 获取时cout << ptr->a << ptr->b << ptr->c << endl;
//那么在使用List迭代器进行获取的时候就需要重载->
//因此在获得迭代器后 List<A>::iterator it = lst.begin();
//全写:cout << it.operator->()->_a << it.operator->()->_b << it.operator->()->_c << endl;
//简写:cout << it->_a << it->_b << it->_c << endl;
Ptr operator->()
{
return &_node->_data;
}
//++iterator:
Self& operator++()
{
_node = _node->_next;
return *this;
}
//后置++:
Self operator++(int)
{
ListIterator<T> tmp(*this);
_node = _node->_next;
return tmp;
}
bool ooerator != (const Self& it)
{
//判断成员指针_node是否指向同一个节点
return _node != it._node;
}
//it->_a:当定义一个自定义类型时
T* operator->()
{
return &_node->_data;
}
bool operator==(const Self& it)
{
return !(*this != it);
}
//封装节点
ListNode<T>* _node;
};
之后再开始实现list类,成员定义为一个:
_header:指向先前定义的节点结构体类型的指针
该list中析构函数的实现与先前stirng和vector不同在于需要循环释放每个节点的资源。
template <class T>
class List
{
public:
typedef ListNode<T> Node;
typedef Node* pNode;
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
iterator begin()
{
return iterator(_header->_next);
}
const_iterator begin() const
{
return const_iterator(_header->_next);
}
iterator end()
{
return iterator(_header);
}
const_iterator end() const
{
return const_iterator(_header);
}
List()
:_header(new Node())
{
//循环结构
_header->_next = _header->_prev = _header;
}
List(size_t n, const T& val = T())
:_header(new Node())
{
_header->_next = _header->_prev = _header;
for (size_t i = 0; i < n; ++i)
{
pushBack(val);
}
}
template <class inputIterator>
List(inputIterator first, inputIterator last)
:_header(new Node())
{
_header->_next = _header->_prev = _header;
while (first != last)
{
pushBack(*first);
++first;
}
}
void pushBack(const T& val)
{
pNode prev = _header->_prev;
Node newNode = List(val);
prev->_next = newNode;
newNode->_prev = prev;
newNode->_next = _header;
_header->_prev = newNode;
}
void insert(iterator pos, const T& val)
{
pNode cur = pos._node;
pNode prev = cur->_prev;
pNode newNode = new Node(val);
prev->_next = newNode;
newNode->_prev = prev;
newNode->_next = cur;
cur->_prev = newNode;
}
iterator erase(iterator pos)
{
//判断是否为end迭代器
if (pos != end())
{
pNode cur = pos._node;
pNode prev = cur->_prev;
pNode next = cur->_next;
delete cur;
prev->_next = next;
next->_prev = prev;
//pos迭代器失效
//更新迭代器:指向下一个元素
return iterator(next);
}
return pos;
}
void popFront()
{
erase(begin());
}
void popBack()
{
erase(--end());
}
//传统写法:
//List<T>& operator=(List<T>& lst)
//{
// if (this != &lst)
// {
// //释放原有的节点
// Node* cur = _header->_next;
// while (cur != _header)
// {
// Node* next = cur->_next;
// delete cur;
// cur = next;
// }
// _header->_next = _header->_prev = _header;
// //拷贝
// for (auto& e : lst)
// pushBack(e);
// }
// return *this;
//}
//现代写法:
List<T>& operator=(List<T> lst)
{
swap(_header, lst._header);
return *this;
}
//深拷贝
List(const List<T>& lst)
:_header(new Node())
{
//循环结构
_header->_next = _header->_prev = _header;
//元素拷贝
//Node* cur = lst._header->_next;
//while (cur != lst._header)
//{
// pushBack(cur->_data);
//}
//写法2:
for (auto& e : lst)
pushBack(e);
}
~List()
{
if (_header)
{
Node* node = _header->_next;
while (node != _header)
{
Node* next = node->_next;
delete node;
node = next;
}
delete _header;
_header = nullptr;
}
}
private:
ListNode<T>* _header;
};
void test()
{
List<int> lst;
lst.pushBack(1);
lst.pushBack(2);
List<int> lst2((size_t)10, 5);
string str = "12345";
List<char> lst3(str.begin(), str.end());
}