cpp
iterator insert(iterator pos,const T&x)
{
Node* newnode = new Node(x);
Node* cur = pos._node;//先存一下pos位置的指针
Node* prev = cur->_prev;//再存一下没插入之前pos前面节点的指针
cur->_prev = newnode;
newnode->_next = cur;
newnode->_prev = prev;
prev->_next = newnode;
return newnode;
}
开头
cpp
#include<iostream>
#include<assert.h>
using namespace std;
namespace Ljw
//结点,节点要要公开,用struct就好
cpp
//结点,节点要要公开,用struct就好
template<class T>
struct list_node
{
list_node<T>* _prev;
list_node<T>* _next;
T _val;
//结点的初始化构造函数
list_node(const T&val=T())//写成T(),是为了防止T不是内置类型
:_val(val)
,_prev(nullptr)
,_next(nullptr)
{}
};
迭代器指针
cpp
template<class T, class Ref, class Ptr>
struct __list_node
{
typedef list_node<T> Node;
typedef __list_node<T,Ref,Ptr> KKK;
};
指向节点的指针
cpp
Node* _node;
构造函数
cpp
__list_node(Node*node)
:_node(node)
{}
operator*
cpp
Ref& operator*()//这里是const迭代器的关键,返回的*it,就是指向的位置
{
return _node->_val;
}
这里是const迭代器的关键,返回的*it,就是指向的位置
operator++
cpp
KKK operator++()
{
_node = _node->_next;
return *this;
}
KKK operator++(int)
{
KKK tmp(*this);
_node = _node->_next;
return tmp;
}
operator--
cpp
KKK operator--()
{
_node = _node->_prev;
return *this;
}
KKK operator--(int)
{
Node tmp(*this);
_node = _node->_prev;
return tmp;
}
operator!=
cpp
bool operator!=(const KKK&it)//里面必须加const,因为返回的end()具有常性
{
return _node != it._node;
}
里面必须加const,因为返回的end()具有常性
operator->
cpp
Ptr* operator->()//这里的T*也分为const和不带const,所以加上class Ptr
{
return &_node->_val;
}
这里的T*也分为const和不带const,所以加上class Ptr
list
cpp
template<class T>
class list
{
private:
Node*_head;
size_t _size;
};
三参数的传递
(第二个const迭代器,第三个是带不带const的->的重载)
cpp
typedef list_node<T> Node;//相当于私有
public:
//迭代器
typedef __list_node<T,T&, T*> iterator;//第三个T*是为了operator->的重载
//const迭代器
//typedef const __list_node<T> const_iterator;这种写法是错误的,因为const后的对象无法
//修改,但我们需要的是it++,可以被修改,不被修改的是
//指向的内容不被修改
//正确写法
typedef __list_node<T,const T&,const T*> const_iterator;
//const迭代器
//typedef const __list_node<T> const_iterator;这种写法是错误的,因为const后的对象无法修改,但我们需要的是it++,可以被修改,不被修改的是指向的内容不被修改
构造函数
cpp
list()
{
_head = new Node;// new一个类型就相当于new一个这个类型的空间
_head->_next = _head;
_head->_prev = _head;
}
new一个类型就相当于new一个这个类型的空间
尾插
cpp
void push_back(const T&x)
{
//Node* newnode = new Node(x);//初始化为x,()是初始化[]开空间
先把尾结点和头结点连接起来
//Node* tail = _head->_prev;//一开始时,_head_>prev指向的是自己
//tail->_next = newnode;//一开始要把_head的prev和next与newnode连接起来
//newnode->_prev = tail;
//newnode->_next = _head;
//_head->_prev = newnode;
insert(end(),x);
}
iterator begin
cpp
iterator begin()
{
return _head->_next;
}
iterator end()
cpp
iterator end()
{
return _head;//左闭右开
}
const_iterator
cpp
const_iterator begin() const
{
return _head->_next;
}
const_iterator end() const
{
return _head;//左闭右开
}
pos位置前插入
cpp
iterator insert(iterator pos,const T&x)
{
Node* newnode = new Node(x);
Node* cur = pos._node;//先存一下pos位置的指针
Node* prev = cur->_prev;//再存一下没插入之前pos前面节点的指针
cur->_prev = newnode;
newnode->_next = cur;
newnode->_prev = prev;
prev->_next = newnode;
return newnode;
}
pos位置的删除
cpp
iterator erase(iterator pos)
{
assert(pos != end());//不能删除头结点
Node* cur = pos._node;//存一下pos的节点指针
Node* prev = cur->_prev;//存一下pos之前节点的指针
Node* next = cur->_next;//存一下pos下一个节点的指针
//连接pos位置前一个和后一个的节点,然后释放pos的空间
prev->_next = next;
next->_prev = prev;
delete[] cur;//加不加[]都行
return next;
}
pop_back
cpp
void pop_back()
{
erase(--end());
}
push_front
cpp
void push_front(const T& val)
{
insert(begin(), val);
}
pop_front
cpp
void pop_front()
{
erase(begin());
}
size
cpp
size_t size()
{
size_t i = 0;
auto it = begin();
while (it != end())
{
i++;
it++;
}
return i;
}
clear
clear,顺序表vector不需要释放空间,因为没法单独释放一部分空间,而链表list可以
cpp
void clear()
{
auto it = begin();
while (it != end())
{
it = erase(it);//这里会释放空间
it++;
}
_size = 0;
}
erase(it);//这里会释放空间
析构
cpp
~list()
{
clear();
delete _head;
_head = nullptr;
}
拷贝构造
必须要有一个头结点
cpp
list(const list<T>& It)
{
//必须要有一个头结点
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
auto it = It.begin();
while (it != It.end())
{
push_back(*it);
it++;
}
}
swap
cpp
void swap(list<T>&It)
{
std::swap(_head, It._head);
std::swap(_size, It._size);
}
operator=
cpp
//=的实现
list<T>& operator=(list<T>&It)
{
//现代写法用swap
swap(It);
return *this;
}
总代码加测试
cpp
//list.h
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace Ljw
{
//结点,节点要要公开,用struct就好
template<class T>
struct list_node
{
list_node<T>* _prev;
list_node<T>* _next;
T _val;
//结点的初始化构造函数
list_node(const T&val=T())//写成T(),是为了防止T不是内置类型
:_val(val)
,_prev(nullptr)
,_next(nullptr)
{}
};
//迭代器指针
template<class T, class Ref, class Ptr>
struct __list_node
{
typedef list_node<T> Node;
typedef __list_node<T,Ref,Ptr> KKK;
Node* _node;//指向节点的指针
//构造函数
__list_node(Node*node)
:_node(node)
{}
Ref& operator*()//这里是const迭代器的关键,返回的*it,就是指向的位置
{
return _node->_val;
}
KKK operator++()
{
_node = _node->_next;
return *this;
}
KKK operator--()
{
_node = _node->_prev;
return *this;
}
KKK operator--(int)
{
Node tmp(*this);
_node = _node->_prev;
return tmp;
}
KKK operator++(int)
{
KKK tmp(*this);
_node = _node->_next;
return tmp;
}
bool operator!=(const KKK&it)//里面必须加const,因为返回的end()具有常性
{
return _node != it._node;
}
Ptr* operator->()//这里的T*也分为const和不带const,所以加上class Ptr
{
return &_node->_val;
}
};
//list,带头双向链表
template<class T>
class list
{
typedef list_node<T> Node;//相当于私有
public:
//迭代器
typedef __list_node<T,T&, T*> iterator;//第三个T*是为了operator->的重载
//const迭代器
//typedef const __list_node<T> const_iterator;这种写法是错误的,因为const后的对象无法
//修改,但我们需要的是it++,可以被修改,不被修改的是
//指向的内容不被修改
//正确写法
typedef __list_node<T,const T&,const T*> const_iterator;
//构造函数
list()
{
_head = new Node;// new一个类型就相当于new一个这个类型的空间
_head->_next = _head;
_head->_prev = _head;
}
//尾插
void push_back(const T&x)
{
//Node* newnode = new Node(x);//初始化为x,()是初始化[]开空间
先把尾结点和头结点连接起来
//Node* tail = _head->_prev;//一开始时,_head_>prev指向的是自己
//tail->_next = newnode;//一开始要把_head的prev和next与newnode连接起来
//newnode->_prev = tail;
//newnode->_next = _head;
//_head->_prev = newnode;
insert(end(),x);
}
iterator begin()
{
return _head->_next;
}
iterator end()
{
return _head;//左闭右开
}
const_iterator begin() const
{
return _head->_next;
}
const_iterator end() const
{
return _head;//左闭右开
}
//pos位置前插入
iterator insert(iterator pos,const T&x)
{
Node* newnode = new Node(x);
Node* cur = pos._node;//先存一下pos位置的指针
Node* prev = cur->_prev;//再存一下没插入之前pos前面节点的指针
cur->_prev = newnode;
newnode->_next = cur;
newnode->_prev = prev;
prev->_next = newnode;
return newnode;
}
//pos位置的删除
iterator erase(iterator pos)
{
assert(pos != end());//不能删除头结点
Node* cur = pos._node;//存一下pos的节点指针
Node* prev = cur->_prev;//存一下pos之前节点的指针
Node* next = cur->_next;//存一下pos下一个节点的指针
//连接pos位置前一个和后一个的节点,然后释放pos的空间
prev->_next = next;
next->_prev = prev;
delete[] cur;//加不加[]都行
return next;
}
void pop_back()
{
erase(--end());
}
void push_front(const T& val)
{
insert(begin(), val);
}
void pop_front()
{
erase(begin());
}
size_t size()
{
size_t i = 0;
auto it = begin();
while (it != end())
{
i++;
it++;
}
return i;
}
//clear,顺序表vector不需要释放空间,因为没法单独释放一部分空间,而链表list可以
void clear()
{
auto it = begin();
while (it != end())
{
it = erase(it);//这里会释放空间
it++;
}
_size = 0;
}
//析构
~list()
{
clear();
delete _head;
_head = nullptr;
}
//拷贝构造//必须要有一个头结点
list(const list<T>& It)
{
//必须要有一个头结点
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
auto it = It.begin();
while (it != It.end())
{
push_back(*it);
it++;
}
}
void swap(list<T>&It)
{
std::swap(_head, It._head);
std::swap(_size, It._size);
}
//=的实现
list<T>& operator=(list<T>&It)
{
//现代写法用swap
swap(It);
return *this;
}
private:
Node*_head;
size_t _size;
};
void test1()
{
list<int>v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
list<int>::iterator it = v.begin();//这里是浅拷贝,不是赋值,迭代器不用写析构
while (it != v.end())
{
cout << *it << " ";
it++;
}
}
void test2()
{
list<int>v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(3);
v.insert(v.begin(), 9);
auto it = v.begin();
while(it!=v.end())
{
if (*it % 3 == 0)
{
it = v.erase(it);
}
else
{
it++;
}
}
for (auto e : v)
{
cout << e << " ";
}
cout << endl;
cout<<v.size();
}
void test3()
{
list<int>v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(3);
list<int>v1(v);
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
list<int>v2;
v2.push_back(10);
v2.push_back(20);
v2.push_back(30);
v1 = v2;
for (auto e : v1)
{
cout << e << " ";
}
cout << endl;
}
}