构造函数( (constructor)) | 接口说明 |
---|---|
list (size_type n, const value_type& val = value_type()) | 构造的list中包含n个值为val的元素 |
list() | 构造空的list |
list (const list& x) | 拷贝构造函数 |
list (InputIterator first, InputIterator last) | 用[first, last)区间中的元素构造list |
void TestList1()
{
std::list<int> l1; // 构造空的l1
std::list<int> l2(4, 100); // l2中放4个值为100的元素
std::list<int> l3(l2.begin(), l2.end()); // 用l2的[begin(), end())左闭右开的区间构造l3
std::list<int> l4(l3); // 用l3拷贝构造l4
// 以数组为迭代器区间构造l5
int array[] = { 16,2,77,29 };
std::list<int> l5(array, array + sizeof(array) / sizeof(int));
std::list<int>::iterator it = l5.begin();
//auto it = lt.begin();
while (it != l5.end())
{
std::cout << *it << " ";
it++;
}
}
void TestList2()
{
std::list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_front(10);
lt.push_front(20);
//list的迭代器
std::list<int>::iterator it = lt.begin();
//auto it = lt.begin();
while (it != lt.end())
{
std::cout << *it << " ";
it++;
}
std::cout << std::endl;
//范围for
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//在第5个位置插入数据
it = lt.begin();
for (size_t i = 0; i < 5; i++)
{
++it;
}
lt.insert(it, 6);
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//查找某个数据是否存在lt中
it = find(lt.begin(), lt.end(), 3);
if (it != lt.end())
{
lt.insert(it, 30);
//insert后,it不失效
*it *= 100;
}
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//删除lt中的某个数据
it = find(lt.begin(), lt.end(), 2);
if (it != lt.end())
{
lt.erase(it);
//erase后,it失效
//error:*it *= 100;
}
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//删除lt中的所有偶数
it = lt.begin();
while (it != lt.end())
{
if (*it % 2 == 0)
{
it = lt.erase(it);
//返回值是一个迭代器,指向函数调用删除的元素后面的元素。如果操作删除的是序列中的最后一个元素,则为容器结束。
}
else
{
++it;
}
}
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
}
void TestList3()
{
std::list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_front(10);
lt.push_front(20);
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//逆置lt的数据
lt.reverse();
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//对lt中的数据进行排序,我们一般不用,因为链表的排序效率实在是太低了,底层使用的是归并
//优点是方便,可以将list的数据拷贝到vector,再将vector中的数据进行排序(底层使用的是快排),再将vector中的数据重新拷贝到list中
lt.sort();
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//合并两个list对象,前提是两个对象必须有序
std::list<int> lt2;
lt2.push_back(8);
lt2.push_back(7);
lt2.push_back(9);
lt2.push_back(10);
lt2.sort();
for (auto e : lt2)
{
std::cout << e << " ";
}
std::cout << std::endl;
lt.merge(lt2);
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//去掉lt中的重复数据
lt.unique();
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//remove删除lt中的数据,相当于 find+erase,没有找到这个值不会报错。
lt.remove(20);
for (auto e : lt)
{
std::cout << e << " ";
}
std::cout << std::endl;
//将一个list中的数据"转移"到另外一个list中
std::list<int> mylist1;
std::list<int>mylist2;
std::list<int>::iterator it;
for (int i = 1; i <= 4; ++i)
{
mylist1.push_back(i);
}
for (auto e : mylist1)
{
std::cout << e << " ";
}
std::cout << std::endl;
for (int i = 1; i <= 3; ++i)
{
mylist2.push_back(i * 10);
}
for (auto e : mylist2)
{
std::cout << e << " ";
}
std::cout << std::endl;
it = mylist1.begin();
++it;
//全部转移
//mylist1.splice(it, mylist2);
//转移一个数据
//mylist1.splice(it, mylist2, mylist2.begin());
//转移一部分数据
/*std::list::iterator it2 = mylist2.begin();
for (size_t i = 0; i < 1; i++)
{
++it2;
}*/
mylist1.splice(it, mylist2, ++mylist2.begin(), mylist2.end());
for (auto e : mylist1)
{
std::cout << e << " ";
}
std::cout << std::endl;
}
前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
#pragma once
#include
#include
namespace flash
{
template<class T>
struct list_node
{
list_node<T>* _next;
list_node<T>* _prev;
T _val;
list_node(const T& val = T())
:_next(nullptr)
,_prev(nullptr)
,_val(val)
{}
};
//typedef _list_iterator iterator
//typedef _list_const_iterator const_iterator
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)
{}
Ref operator*()
{
return _node->_val;
}
Ptr operator->()
{
return &_node->_val;
}
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)
{
return _node != it._node;
}
bool operator==(const self& it)
{
return _node == it._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;
//这样设计const迭代器是不行的,因为const迭代器期望的是指向的内容不能被修改
// 这样设计是迭代器本身不能被修改
//typedef const _list_iterator const_iterator;
iterator begin()
{
return _head->_next;
}
iterator end()
{
return _head;
}
const_iterator begin() const
{
return _head->_next;
}
const_iterator end() const
{
return _head;
}
list()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
_size = 0;
}
list(const list<T>& lt)
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
_size = 0;
for (auto& e : lt)
{
push_back(e);
}
}
void swap(list<T>& lt)
{
std::swap(_head, lt._head);
std::swap(_size, lt._size);
}
list<T>& operator=(list<T> lt)
{
swap(lt);
return *this;
}
~list()
{
clear();
delete _head;
_head = nullptr;
}
void clear()
{
iterator it = begin();
while (it != end())
{
it = erase(it);
}
_size = 0;
}
void push_back(const T& x)
{
insert(end(), x);
}
void push_front(const T& x)
{
insert(begin(), x);
}
void pop_back()
{
erase(--end());
}
void pop_front()
{
erase(begin());
}
size_t size()
{
return _size;
}
//在pos位置之前插入
void insert(iterator pos, const T& x)
{
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* newnode = new Node(x);
prev->_next = newnode;
cur->_prev = newnode;
newnode->_next = cur;
newnode->_prev = prev;
++_size;
}
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 next;
--_size;
}
private:
Node* _head;
size_t _size;
};
}
vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及应用场景不同,其主要不同如下:
本篇博客到此结束。。。。。。