目录
一、初始准备
二、迭代器
三、构造函数与析构函数
四、插入与删除数据
五、全部代码
一、初始准备
为了防止与库里的命名发生冲突,所以首先得定义一个命名空间
list是通过一个个节点连接而成的,所以得先定义一个自定义变量,采用模板的方式
这里实现的是带头双向循环链表,所以有前后指针成员,以及数据成员,共三个成员
同时定义构造函数,将其初始化
定义一个list类,同样采用模板,同时将其将要使用的正反迭代器,节点名称用typedef定义一个新名称,将其简化
成员就一个头节点指针
二、迭代器
正向迭代器
迭代器实现,同样采用了模板,但采用了三个模板参数,便于const版本和普通版本的实现,减少代码量,不至于代码冗余
由于list是一个个节点连接而成,空间不连续,无法像vector一样,所以需要通过运算符重载来实现与vector一样的遍历方式,如++、--等等
成员也只有一个节点指针
重载解引用(*)运算符,返回的是节点存储的数据
重载解引用(->)运算符,返回的是节点存储的数据的地址,由于存储的数据是自定义类型时,会有两个->->,为了增加可读性,编译器优化掉了一个箭头
重载前置++,前置--,只需让节点指针指向下一个或上一个节点即可
重载后置++,后置--,需要先拷贝一个迭代器对象(浅拷贝),再让原对象的节点指针指向下一个或上一个节点,然后返回拷贝的对象即可
重载== 、!=运算符,判断节点指针是否相等即可
头节点和尾节点
反向迭代器
这里头尾节点采用与正向迭代器相对称的方式(也可以不这样做)
由于正向迭代器已经实现,复用其中的一些功能即可
只是正向迭代器的++,变成了--,--变成了++,相反而已
三、构造函数与析构函数
默认构造函数,先给头节点开辟一块空间,再将其成员指针都指向头节点即可
其它构造函数
先将其初始化,即创立头节点
再往后尾插数据即可
拷贝构造(深拷贝)
这里需要实现一个迭代器(构造函数)来插入数据,实现一个链表
先将其初始化,即创立头节点
再创建一个临时对象,调用它的构造函数(迭代器)
然后将头节点指针交换即可
赋值运算符重载,这里采用的是值传递,也是为了实现一次拷贝构造,再交换头节点指针
清空链表(头节点除外),调用随机位置节点的删除函数
调用清空数据的函数,然后将头节点空间释放,再置空
四、插入与删除数据
尾插
随机位置节点的插入
随机位置节点的删除
头节点不能删,所以需断言一下
五、全部代码
//List.h
#include<iostream>
#include<assert.h>
using namespace std;
#include"reverse_iterator.h"
namespace Henry
{
template<class T>
struct ListNode
{
ListNode<T>* _prev;
ListNode<T>* _next;
T _data;
ListNode(const T& data = T()):_prev(nullptr),_next(nullptr),_data(data)
{}
};
template<class T,class Ref,class Ptr>
struct __list_iterator
{
typedef __list_iterator<T, Ref, Ptr> self;
typedef struct ListNode<T> Node;
Node* _node;
__list_iterator(Node* x):_node(x)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
self& operator++()
{
_node = _node->_next;
return *this;
}
self operator++(int)
{
self tmp(*this);
_node = _node->_next;
return tmp;
}
self& operator--()
{
_node = _node->_prev;
return *this;
}
self operator--(int)
{
self tmp(*this);
_node = _node->_prev;
return tmp;
}
bool operator!=(const self& it) const
{
return _node != it._node;
}
bool operator==(const self& it) const
{
return _node != it._node;
}
};
template<class T>
class list
{
public:
typedef struct ListNode<T> Node;
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T, const T&, const T*> const_iterator;
typedef __list_reverse_iterator<T, T&, T*> reverse_iterator;
typedef __list_reverse_iterator<T, const T& ,const T*> const_reverse_iterator;
list()
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
}
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
iterator begin()
{
return iterator(_head->_next);
}
iterator end()
{
return iterator(_head);
}
const_iterator begin() const
{
return const_iterator(_head->_next);
}
const_iterator end() const
{
return const_iterator(_head);
}
template<class InputIterator>
list(InputIterator first, InputIterator last)
{
_head = new Node();
_head->_prev = _head;
_head->_next = _head;
while (first != last)
{
push_back(*first);
++first;
}
}
list(size_t n , const T& val = T())
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
for (size_t i = 0; i < n; i++)
{
push_back(val);
}
}
list(int n, const T& val = T())
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
for (int i = 0; i < n; i++)
{
push_back(val);
}
}
list(const list<T>& lt)
{
_head = new Node();
_head->_prev = _head;
_head->_next = _head;
list<T> tmp(lt.begin(), lt.end());
std::swap(_head, tmp._head);
}
list<T>& operator=(list<T> lt)
{
std::swap(lt._head, _head);
return *this;
}
void push_back(const T& val)
{
Node* newnode = new Node(val);
Node* tail = _head->_prev;
newnode->_next = _head;
newnode->_prev = tail;
_head->_prev = newnode;
tail->_next = newnode;
}
void pop_back()
{
/*Node* tail = _head->_prev;
Node* prevtail = tail->_prev;
delete tail;
_head->_prev = prevtail;
prevtail->_next = _head;*/
erase(--end());
}
iterator insert(iterator pos, const T& val)
{
Node* posprev = pos._node->_prev;
Node* newnode = new Node(val);
posprev->_next = newnode;
pos._node->_prev = newnode;
newnode->_prev = posprev;
newnode->_next = pos._node;
return iterator(newnode);
}
void clear()
{
iterator it = begin();
while (it != end())
{
erase(it++);
}
}
~list()
{
clear();
delete _head;
_head = nullptr;
}
iterator erase(iterator pos)
{
assert(pos != end());
Node* posprev = pos._node->_prev;
Node* posnext = pos._node->_next;
delete pos._node;
posprev->_next = posnext;
posnext->_prev = posprev;
return iterator(posnext);
}
void pop_front()
{
erase(begin());
}
void push_front(const T& x)
{
insert(begin(),x);
}
private:
Node* _head;
};
void print_list(const list<int>& lt)
{
list<int>::const_iterator it = lt.begin();
list<int>::const_iterator tail = lt.end();
while (it != tail)
{
cout << *it << " ";
++it;
}
cout << endl;
}
void test_list1()
{
list<int> lt1;
lt1.push_back(1);
lt1.push_back(2);
lt1.push_back(3);
lt1.push_back(4);
lt1.push_back(5);
lt1.pop_back();
lt1.pop_back();
lt1.pop_back();
print_list(lt1);
}
void test_list2()
{
list<int> lt1;
lt1.push_back(1);
lt1.push_back(2);
lt1.push_back(3);
list<int> lt2(lt1);
}
void test_list3()
{
list<int> lt1;
//lt1.push_back(1);
//lt1.push_back(2);
lt1.insert(lt1.begin(), 1);
lt1.insert(lt1.begin(), 2);
lt1.insert(lt1.begin(), 3);
lt1.insert(lt1.begin(), 4);
lt1.erase(lt1.begin());
lt1.erase(lt1.begin());
print_list(lt1);
}
}
//reverse_iterator
namespace Henry
{
template<class iterator,class Ref,class Ptr>
class __list_reverse_iterator
{
public:
typedef __list_reverse_iterator<iterator, Ref, Ptr> self;
__list_reverse_iterator(iterator x):_it(x)
{}
Ref operator*()
{
iterator prev = _it;
return *--prev;
}
Ptr operator->()
{
return &operator*();
}
self& operator++()
{
--_it;
return *this;
}
self& operator--()
{
++_it;
return *this;
}
bool operator!=(const iterator& rit) const
{
return rit._it != _it;
}
private:
iterator _it;
};
}