list就是我们数据结构中的链表,我们先看一下它的用法
# 基本用法
首先是swap,它可以直接将两个链表中的所有数据交换
下一个是resize,我们在之前也见过,如果resize的值小于链表长度,链表就会直接缩短;如果大于的话,链表后面的值就补0
下一个是clear,就是直接让链表变成空链表
下一个是splice,它的意思是拼接,粘接。顾名思义就是把一个链表(或者一部分)拼接到另一个链表上的任意位置,有这些重载形式
下一个是remove,就是删除链表中某个给定的值,这个好说,下一个是remove_if,这是函数参数是一个bool值,如果传'真'就删除这段代码就是去除所有小于10的值
unique就是去重,但前提是链表有序才可以有效去重,所以我们在前边先用一个sort来对数据进行排序
下一个是merge,也就是归并,就是将两个链表按照一定规律进行归并成一个
下一个就更简单了,reverse就是逆置
# 模拟实现
我们要模拟出一个链表,STL的list的底层就是一个带头双向循环链表。要写一个节点的类,再写一个链表的类。与C语言不同的是,因为C++要实现迭代器,而链表的底层又不是连续的,所以这里的迭代器并不能像之前的只用typedef,而是将迭代器也写成一个类,在这个类中实现迭代器要实现的内容。比较关键的就是迭代器有const版本和非const版本,两者的不同之处就是在于类型,而模板就是管类型的,所以可以给模板多传几个类型来区分。
cpp
#pragma once
#include<assert.h>
namespace jxh {
template<class T>
struct list_node {
T _data;
list_node<T>* _next;
list_node<T>* _prev;
list_node(const T& x = T())
:_data(x)
,_next(nullptr)
,_prev(nullptr)
{}
};
template<class T,class Ref,class Ptr>
struct __list_iterator {
typedef list_node<T>Node;
typedef __list_iterator<T, Ref, Ptr>self;
Node* _node;
__list_iterator(Node*node)
:_node(node){}
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& s) {
return _node != s._node;
}
bool operator==(const self& s) {
return _node == s._node;
}
};
template<class T>
class list {
typedef list_node<T>Node;
public:
typedef __list_iterator<T, T&, T*> iterator;
typedef __list_iterator<T,const T&,const T*> const_iterator;
iterator begin() {
return _head->_next;
}
iterator end() {
return _head;
}
const_iterator begin()const {
return const_iterator(_head->_next);
}
const_iterator end()const {
return const_iterator(_head);
}
void empty_init() {
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
_size = 0;
}
list() {
empty_init();
}
list(const list<T>& tmp) {
empty_init();
for (auto e : tmp) {
push_back(e);
}
}
void swap(list<T>& lt) {
std::swap(_head, lt._head);
std::swap(_size, lt._size());
}
list<int>& operator=(list<int>lt) {
swap(lt);
return *this;
}
~list() {
clear();
delete _head;
_head = nullptr;
}
void clear() {
iterator it = begin();
while (it != end()) {
it = erase(it);
}
}
void push_back(const T& x) {
insert(end(), x);
}
void push_front(const T& x) {
insert(begin(), x);
}
void pop_front() {
erase(begin());
}
void pop_back() {
erase(--end());
}
iterator insert(iterator pos, const T& x) {
Node* cur = pos._node;
Node* newnode = new Node(x);
Node* prev = cur->_prev;
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
++_size;
return newnode;
}
iterator erase(iterator pos) {
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
delete cur;
prev->_next = next;
next->_prev = prev;
--_size;
return next;
}
size_t size() {
return _size;
}
private:
Node* _head;
size_t _size;
};
}