文章目录
- 目录
-
- [1. list的使用](#1. list的使用)
-
- [1.1 排序 + 去重](#1.1 排序 + 去重)
- [1.2 转移](#1.2 转移)
- [2. list的模拟实现](#2. list的模拟实现)
-
- [2.1 构造 + 尾插](#2.1 构造 + 尾插)
- [2.2 遍历](#2.2 遍历)
- [2.3 插入 + 删除](#2.3 插入 + 删除)
- [2.4 析构](#2.4 析构)
- [2.5 拷贝构造](#2.5 拷贝构造)
- [2.6 赋值运算符重载](#2.6 赋值运算符重载)
- [2.7 initializer_list 的构造](#2.7 initializer_list 的构造)
- [2.8 完整代码](#2.8 完整代码)
- [3. list与vector的对比](#3. list与vector的对比)
目录
- list的使用
- list的模拟实现
1. list的使用
我们先统一看一下它的一些常见重要接口:
- list的构造
- list iterator的使用
- list capacity
- list element access
- list modifiers
接着,我们写几个函数的具体使用方法:
1.1 排序 + 去重
cpp
#include <iostream>
using namespace std;
#include <list>
#include <algorithm>
void test_list1()
{
list<int> lt1 = { 10, 2, 3, 3, 4, 3, 5, 6 };
list<int>::iterator it = lt1.begin();
while (it != lt1.end())
{
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : lt1)
{
cout << e << " ";
}
cout << endl;
//链表不支持使用算法库里面的排序,因为它需要随机迭代器
//链表的迭代器是双向迭代器,只允许++和--,不允许+和-,因为效率太低了
//string和vector的迭代器都是随机迭代器,支持++ -- + -
//sort(lt1.begin(), lt1.end());//err
lt1.sort();
for (auto e : lt1)
{
cout << e << " ";
}
cout << endl;
lt1.sort(greater<int>());
for (auto e : lt1)
{
cout << e << " ";
}
cout << endl;
//必须要先排好序再用去重
lt1.unique();
for (auto e : lt1)
{
cout << e << " ";
}
cout << endl;
}
但如果数据很多,list的排序效率是很低的,下面是和vector的比较:
cpp
void test_op1()
{
srand(time(0));
const int N = 10000000;
list<int> lt1;
list<int> lt2;
vector<int> v;
for (int i = 0; i < N; ++i)
{
auto e = rand() + i;
lt1.push_back(e);
v.push_back(e);
}
int begin1 = clock();
// 排序
sort(v.begin(), v.end());
int end1 = clock();
int begin2 = clock();
lt1.sort();
int end2 = clock();
printf("vector sort:%d\n", end1 - begin1);
printf("list sort:%d\n", end2 - begin2);
}
void test_op2()
{
srand(time(0));
const int N = 10000000;
list<int> lt1;
list<int> lt2;
for (int i = 0; i < N; ++i)
{
auto e = rand() + i;
lt1.push_back(e);
lt2.push_back(e);
}
int begin1 = clock();
// 拷贝vector
vector<int> v(lt2.begin(), lt2.end());
// 排序
sort(v.begin(), v.end());
// 拷贝回lt2
lt2.assign(v.begin(), v.end());
int end1 = clock();
int begin2 = clock();
lt1.sort();
int end2 = clock();
printf("list copy vector sort copy list sort:%d\n", end1 - begin1);
printf("list sort:%d\n", end2 - begin2);
}
1.2 转移
cpp
#include <iostream>
#include <list>
using namespace std;
int main()
{
std::list<int> mylist1, mylist2;
std::list<int>::iterator it;
// set some initial values:
for (int i = 1; i <= 4; ++i)
mylist1.push_back(i); // mylist1: 1 2 3 4
for (int i = 1; i <= 3; ++i)
mylist2.push_back(i * 10); // mylist2: 10 20 30
it = mylist1.begin();
++it; // points to 2
mylist1.splice(it, mylist2); // mylist1: 1 10 20 30 2 3 4
// mylist2 (empty)
// "it" still points to 2 (the 5th element)
return 0;
}
cpp
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
std::list<int> mylist1;
for (int i = 1; i <= 4; ++i)
mylist1.push_back(i); // mylist1: 1 2 3 4
//算法库中的find
auto it = find(mylist1.begin(), mylist1.end(), 3);
mylist1.splice(mylist1.begin(), mylist1, it);
return 0;
}
2. list的模拟实现
2.1 构造 + 尾插

cpp
namespace bit
{
template <class T>
struct ListNode
{
ListNode<T>* _next;
ListNode<T>* _prev;
T _data;
ListNode(const T& data = T())
:_next(nullptr)
,_prev(nullptr)
,_data(data)
{}
};
template <class T>
class list
{
typedef ListNode<T> Node;
public:
list()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
void push_back(const T& x)
{
Node* newnode = new Node(x);
Node* tail = _head->_prev;
tail->_next = newnode;
newnode->_prev = tail;
newnode->_next = _head;
_head->_prev = newnode;
}
private:
Node* _head;
};
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);
}
}
2.2 遍历
- 普通迭代器
cpp
//不符合迭代器的行为,无法遍历
//typedef Node* iterator;
cpp
#include <iostream>
using namespace std;
template <class T>
class ListIterator
{
typedef ListNode<T> Node;
typedef ListIterator<T> Self;
Node* _node;
public:
ListIterator(Node* node)
:_node(node)
{}
//++it
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
Self operator--(int)
{
Self tmp(*this);
_node = _node->_prev;
return tmp;
}
T& operator*()
{
return _node->_data;
}
T* operator->()
{
return &_node->_data;
}
bool operator!=(const Self& it)
{
return _node != it._node;
}
bool operator==(const Self& it)
{
return _node == it._node;
}
};
template <class T>
class list
{
typedef ListNode<T> Node;
public:
//不符合迭代器的行为,无法遍历
//typedef Node* iterator;
typedef ListIterator<T> iterator;
iterator begin()
{
//iterator it(_head->_next);
//return it;
return iterator(_head->_next);
}
iterator end()
{
return iterator(_head);
}
private:
Node* _head;
};
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);
list<int>::iterator it = lt1.begin();
while (it != lt1.end())
{
*it += 10;
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : lt1)
{
cout << e << " ";
}
cout << endl;
}
struct Pos
{
int _row;
int _col;
Pos(int row = 0, int col = 0)
:_row(row)
,_col(col)
{}
};
void test_list2()
{
list<Pos> lt1;
lt1.push_back(Pos(100, 100));
lt1.push_back(Pos(200, 200));
lt1.push_back(Pos(300, 300));
//begin返回值是拷贝构造出的临时对象
//匿名构造出的也是临时对象
//这些临时对象具有常性,但是和直接用const修饰的对象有一些不同
//它不能直接引用,但是可以调用非const成员函数
//比如这个begin直接调用operator++是可以的
list<Pos>::iterator it = lt1.begin();
while (it != lt1.end())
{
//cout << (*it)._row << ":" << (*it)._col << endl;
//为了可读性,省略了一个->
cout << it->_row << ":" << it->_col << endl;
//cout << it->->_row << ":" << it->->_col << endl;//err
cout << it.operator->()->_row << ":" << it.operator->()->_col << endl;
++it;
}
cout << endl;
}
- const迭代器
cpp
template <class T>
class ListConstIterator
{
typedef ListNode<T> Node;
typedef ListConstIterator<T> Self;
Node* _node;
public:
ListConstIterator(Node* node)
:_node(node)
{}
//++it
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
Self operator--(int)
{
Self tmp(*this);
_node = _node->_prev;
return tmp;
}
//*it
const T& operator*()
{
return _node->_data;
}
const T* operator->()
{
return &_node->_data;
}
bool operator!=(const Self& it)
{
return _node != it._node;
}
bool operator==(const Self& it)
{
return _node == it._node;
}
};
template <class T>
class list
{
typedef ListNode<T> Node;
public:
typedef ListConstIterator<T> const_iterator;
const_iterator begin() const
{
return const_iterator(_head->_next);
}
const_iterator end() const
{
return const_iterator(_head);
}
private:
Node* _head;
};
void Func(const list<int>& lt)
{
//const迭代器不能是普通迭代器前面加const修饰
//const迭代器目标是本身可以修改,指向的内容不能修改 类似const T* p
list<int>::const_iterator it = lt.begin();
while (it != lt.end())
{
//指向的内容不能修改
//*it += 10;
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);
Func(lt1);
}
从普通迭代器和const迭代器的代码中我们可以发现,只有 operator* 和 operator-> 的代码有区别,其他代码都是相同的,那么我们写两份就有点浪费了,应该如何解决呢?
可能有人会这样写:typedef ListIterator<const T> const_iterator; ,这样做虽然解决了 operator* 和 operator-> 返回类型的问题,但是会产生其他问题:假设 T 是 int ,ListIterator构造时需要的参数就变为 ListNode<const int>* ,而调用begin函数时传的参数是 ListNode<int>* ,导致形参和实参的类型不匹配,所以这样写是有问题的。
简单来说,问题就在于模板参数T的影响范围太大了,它不仅仅影响 operator* 和 operator-> 的返回类型,还影响了节点的类型,所以会出现问题。因此我们可以增加模板参数,使这个模板参数只影响 operator* 和 operator-> 的返回类型,不要影响节点的类型就可以了。

cpp
template <class T, class Ref, class Ptr>
class ListIterator
{
typedef ListNode<T> Node;
typedef ListIterator<T, Ref, Ptr> Self;
Node* _node;
public:
ListIterator(Node* node)
:_node(node)
{}
//++it
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
Self operator--(int)
{
Self tmp(*this);
_node = _node->_prev;
return tmp;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& it)
{
return _node != it._node;
}
bool operator==(const Self& it)
{
return _node == it._node;
}
};
template <class T>
class list
{
typedef ListNode<T> Node;
public:
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
iterator begin()
{
return iterator(_head->_next);
}
const_iterator begin() const
{
return const_iterator(_head->_next);
}
iterator end()
{
return iterator(_head);
}
const_iterator end() const
{
return const_iterator(_head);
}
private:
Node* _head;
};
2.3 插入 + 删除

cpp
void push_back(const T& x)
{
insert(end(), x);
}
void pop_back()
{
erase(--end());
}
void push_front(const T& x)
{
insert(begin(), x);
}
void pop_front()
{
erase(begin());
}
//没有iterator失效
iterator insert(iterator pos, const T& x)
{
Node* cur = pos._node;
Node* newnode = new Node(x);
Node* prev = cur->_prev;
//prev newnode cur
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
return iterator(newnode);
}
//erase 后 pos失效了,pos指向节点被释放了
iterator erase(iterator pos)
{
assert(pos != end());
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
prev->_next = next;
next->_prev = prev;
delete cur;
return iterator(next);
}
void Func(const list<int>& lt)
{
list<int>::const_iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
void test_list3()
{
list<int> lt1;
lt1.push_back(1);
lt1.push_back(2);
lt1.push_back(3);
lt1.push_back(4);
lt1.push_back(5);
Func(lt1);
lt1.push_front(10);
lt1.push_front(20);
lt1.push_front(30);
Func(lt1);
lt1.pop_front();
lt1.pop_front();
Func(lt1);
lt1.pop_back();
lt1.pop_back();
Func(lt1);
lt1.pop_back();
lt1.pop_back();
lt1.pop_back();
lt1.pop_back();
//lt1.pop_back();
Func(lt1);
}
注: 这里要把迭代器的成员变量改成公有的,不然 pos._node 是访问不到的
2.4 析构
cpp
~list()
{
clear();
delete _head;
_head = nullptr;
}
void clear()
{
auto it = begin();
while (it != end())
{
it = erase(it);
}
}
2.5 拷贝构造
cpp
void empty_init()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
list()
{
empty_init();
}
//lt2(lt1)
list(const list<T>& lt)
{
empty_init();
for (const auto& e : lt)
{
push_back(e);
}
}
void Func(const list<int>& lt)
{
list<int>::const_iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
void test_list4()
{
list<int> lt1;
lt1.push_back(1);
lt1.push_back(2);
lt1.push_back(3);
lt1.push_back(4);
lt1.push_back(5);
Func(lt1);
list<int> lt2(lt1);
lt1.push_back(6);
Func(lt1);
Func(lt2);
}
2.6 赋值运算符重载
cpp
//lt1 = lt3
list<T>& operator=(list<T> lt)
{
swap(_head, lt._head);
return *this;
}
void Func(const list<int>& lt)
{
list<int>::const_iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
void test_list4()
{
list<int> lt1;
lt1.push_back(1);
lt1.push_back(2);
lt1.push_back(3);
lt1.push_back(4);
lt1.push_back(5);
Func(lt1);
list<int> lt3;
lt3.push_back(10);
lt3.push_back(20);
lt3.push_back(30);
lt1 = lt3;
Func(lt1);
Func(lt3);
}
2.7 initializer_list 的构造
cpp
list(initializer_list<T> il)
{
empty_init();
for (const auto& e : il)
{
push_back(e);
}
}
void Func(const list<int>& lt)
{
list<int>::const_iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
void test_list5()
{
list<int> lt1 = { 1, 2, 3, 4, 5, 6 };
Func(lt1);
}
2.8 完整代码
cpp
//List.h
#include <iostream>
using namespace std;
#include <assert.h>
namespace bit
{
template <class T>
struct ListNode
{
ListNode<T>* _next;
ListNode<T>* _prev;
T _data;
ListNode(const T& data = T())
:_next(nullptr)
,_prev(nullptr)
,_data(data)
{}
};
template <class T, class Ref, class Ptr>
struct ListIterator
{
typedef ListNode<T> Node;
typedef ListIterator<T, Ref, Ptr> Self;
Node* _node;
ListIterator(Node* node)
:_node(node)
{}
//++it
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
Self operator--(int)
{
Self tmp(*this);
_node = _node->_prev;
return tmp;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& it)
{
return _node != it._node;
}
bool operator==(const Self& it)
{
return _node == it._node;
}
};
//template <class T>
//class ListConstIterator
//{
// typedef ListNode<T> Node;
// typedef ListConstIterator<T> Self;
// Node* _node;
//public:
// ListConstIterator(Node* node)
// :_node(node)
// {}
// //++it
// Self& operator++()
// {
// _node = _node->_next;
// return *this;
// }
// Self& operator--()
// {
// _node = _node->_prev;
// return *this;
// }
// Self operator++(int)
// {
// Self tmp(*this);
// _node = _node->_next;
// return tmp;
// }
// Self operator--(int)
// {
// Self tmp(*this);
// _node = _node->_prev;
// return tmp;
// }
// //*it
// const T& operator*()
// {
// return _node->_data;
// }
// const T* operator->()
// {
// return &_node->_data;
// }
// bool operator!=(const Self& it)
// {
// return _node != it._node;
// }
// bool operator==(const Self& it)
// {
// return _node == it._node;
// }
//};
template <class T>
class list
{
typedef ListNode<T> Node;
public:
//不符合迭代器的行为,无法遍历
//typedef Node* iterator;
//typedef ListIterator<T> iterator;
//typedef ListConstIterator<T> const_iterator;
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
iterator begin()
{
//iterator it(_head->_next);
//return it;
return iterator(_head->_next);
}
const_iterator begin() const
{
return const_iterator(_head->_next);
}
iterator end()
{
return iterator(_head);
}
const_iterator end() const
{
return const_iterator(_head);
}
void empty_init()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
list()
{
empty_init();
}
list(initializer_list<T> il)
{
empty_init();
for (const auto& e : il)
{
push_back(e);
}
}
//lt2(lt1)
list(const list<T>& lt)
{
empty_init();
for (const auto& e : lt)
{
push_back(e);
}
}
//lt1 = lt3
list<T>& operator=(list<T> lt)
{
swap(_head, lt._head);
return *this;
}
~list()
{
clear();
delete _head;
_head = nullptr;
}
void clear()
{
auto it = begin();
while (it != end())
{
it = erase(it);
}
}
void push_back(const T& x)
{
/*Node* newnode = new Node(x);
Node* tail = _head->_prev;
tail->_next = newnode;
newnode->_prev = tail;
newnode->_next = _head;
_head->_prev = newnode;*/
insert(end(), x);
}
void pop_back()
{
erase(--end());
}
void push_front(const T& x)
{
insert(begin(), x);
}
void pop_front()
{
erase(begin());
}
//没有iterator失效
iterator insert(iterator pos, const T& x)
{
Node* cur = pos._node;
Node* newnode = new Node(x);
Node* prev = cur->_prev;
//prev newnode cur
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
return iterator(newnode);
}
//erase 后 pos失效了,pos指向节点被释放了
iterator erase(iterator pos)
{
assert(pos != end());
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
prev->_next = next;
next->_prev = prev;
delete cur;
return iterator(next);
}
private:
Node* _head;
};
void Func(const list<int>& lt)
{
//const迭代器不能是普通迭代器前面加const修饰
//const迭代器目标是本身可以修改,指向的内容不能修改 类似const T* p
list<int>::const_iterator it = lt.begin();
while (it != lt.end())
{
//指向的内容不能修改
//*it += 10;
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);
Func(lt1);
list<int>::iterator it = lt1.begin();
while (it != lt1.end())
{
*it += 10;
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : lt1)
{
cout << e << " ";
}
cout << endl;
}
struct Pos
{
int _row;
int _col;
Pos(int row = 0, int col = 0)
:_row(row)
,_col(col)
{}
};
void test_list2()
{
list<Pos> lt1;
lt1.push_back(Pos(100, 100));
lt1.push_back(Pos(200, 200));
lt1.push_back(Pos(300, 300));
//begin返回值是拷贝构造出的临时对象
//匿名构造出的也是临时对象
//这些临时对象具有常性,但是和直接用const修饰的对象有一些不同
//它不能直接引用,但是可以调用非const成员函数
//比如这个begin直接调用operator++是可以的
list<Pos>::iterator it = lt1.begin();
while (it != lt1.end())
{
//cout << (*it)._row << ":" << (*it)._col << endl;
//为了可读性,省略了一个->
cout << it->_row << ":" << it->_col << endl;
//cout << it->->_row << ":" << it->->_col << endl;//err
cout << it.operator->()->_row << ":" << it.operator->()->_col << endl;
++it;
}
cout << endl;
}
void test_list3()
{
list<int> lt1;
lt1.push_back(1);
lt1.push_back(2);
lt1.push_back(3);
lt1.push_back(4);
lt1.push_back(5);
Func(lt1);
lt1.push_front(10);
lt1.push_front(20);
lt1.push_front(30);
Func(lt1);
lt1.pop_front();
lt1.pop_front();
Func(lt1);
lt1.pop_back();
lt1.pop_back();
Func(lt1);
lt1.pop_back();
lt1.pop_back();
lt1.pop_back();
lt1.pop_back();
//lt1.pop_back();
Func(lt1);
}
void test_list4()
{
list<int> lt1;
lt1.push_back(1);
lt1.push_back(2);
lt1.push_back(3);
lt1.push_back(4);
lt1.push_back(5);
Func(lt1);
list<int> lt2(lt1);
lt1.push_back(6);
Func(lt1);
Func(lt2);
list<int> lt3;
lt3.push_back(10);
lt3.push_back(20);
lt3.push_back(30);
lt1 = lt3;
Func(lt1);
Func(lt3);
}
void test_list5()
{
list<int> lt1 = { 1, 2, 3, 4, 5, 6 };
Func(lt1);
}
}
cpp
//Test.cpp
#include "List.h"
int main()
{
bit::test_list5();
return 0;
}
3. list与vector的对比
vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及应用场景不同,其主要不同如下: