STL(五)list 双向链表
来源:互联网 发布:数据库的设计原则答案 编辑:程序博客网 时间:2024/05/17 06:33
参考:
list
底层数据结构
list同样是一个模板类,它底层数据结构为双向循环链表。因此,它支持任意位置常数时间的插入/删除操作,不支持快速随机访问。
迭代器类型
list的迭代器具备前移、后移的能力,所以list提供的是Bidirectional iterator(双向迭代器)。由于采用的是双向迭代器,自然也很方便在指定元素之前插入新节点,所以list很正常地提供了insert()操作与push_back()/pop_back()操作。在C++11中,list新增了三个接口,以支持在指定位置构造对象后插入容器中:
内存分配策略
list的空间配置策略,自然是像我们普通双向链表那样,有多少元素申请多少内存。它不像vector那样需要预留空间供新元素的分配,也不会因找不到连续的空间而引起整个容器的内存迁移。
迭代器失效问题
list 有一个重要性质:插入操作(insert)与接合操作(splice)都不会造成原有的list迭代器失效。这在vector是不成立的,因为vactor的插入可能引起空间的重新配置,导致原来的迭代器全部失效。list的迭代器失效,只会出现在删除的时候,指向删除元素的那个迭代器在删除后失效。
通常来说,forward_list在使用灵活度上比不上list,因为它只能单向迭代元素,且提供的接口没有list多。然而,在内存的使用上,它是比list占优势的。当对内存的要求占首要位置时,应该选择forward_list。
list使用优劣
优点:
(1) 不使用连续内存完成动态操作。
(2) 在内部方便的进行插入和删除操作
(3) 可在两端进行push、pop
缺点:
(1) 不能进行内部的随机访问,即不支持[ ]操作符和vector.at()
(2) 相对于verctor占用内存多
<list>
class T,
class Allocator = std::allocator<T>
template <class T>
using list = std::list<T, std::pmr::polymorphic_allocator<T>>;
1、
成员函数
list
(公开成员函数)explicit list( const Allocator& alloc );(C++14 起) (2) explicit list( size_type count,
const T& value = T(),
const T& value,
(C++14 前)
list( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );(8)(C++11 起)
从各种数据源构造新容器,可选地使用用户提供的分配器 alloc
。
count
个有值 value
的元素的容器。count
默认插入的 T
实例的容器。不进行复制。[first, last)
内容的容器。若 InputIt
是整数类型,则此构造函数拥有的效果同 list(static_cast<size_type>(first), static_cast<value_type>(last), a) 。(C++11 前)此重载仅若InputIt
满足 输入迭代器 (InputIterator
) 才参与重载决议,以避免和重载 (2) 的歧义。(C++11 起)other
内容的容器。若不提供 alloc
,则如同通过调用 std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.get_allocator()) 获得分配器。other
内容的容器。分配器通过属于 other
的分配器移动构造获得。alloc
用作新容器的分配器,从 other
移动内容;若 alloc != other.get_allocator() ,则它导致逐元素移动。init
内容的容器。参数
alloc-用于此容器所有内存分配的分配器count-容器的大小value-以之初始化容器元素的值first, last-复制元素的来源范围other-用作初始化容器元素来源的另一容器init-用作初始化元素来源的 initializer_list复杂度
count
成线性first
和 last
的距离成线性other
的大小成线性init
的大小成线性。异常
到 Allocator::allocate
的调用可能抛出。
注意
在容器移动构造(重载 (6) )后,指向 other
的引用及迭代器(除了尾迭代器)保持合法,但指代现于 *this 中的元素。
list
(公开成员函数)(C++17 前)
替换容器内容。
other
的副本替换内容。若 std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value 为 true ,则以源分配器的副本替换目标分配器。若源分配器与目标分配器不比较相等,则用目标( *this )分配器销毁内存,然后在复制元素前用 other
的分配器分配。 (C++11 起).、other
的内容替换内容(即从 other
移动 other
中的数据到此容器)。之后 other
在合法但未指定的状态。若 std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value 为 true ,则用源分配器的副本替换目标分配器。若它为 false 且源与目标分配器不比较相等,则目标不能取走源内存的所有权,而必须单独移动赋值逐个元素,用自己的分配器按需分配额外的内存。任何情况下,原先在 *this 中的元素要么被销毁,要么以逐元素移动赋值替换。ilist
所标识者替换内容。参数
other-用作数据源的另一容器ilist-用作数据源的 initializer_list返回值
*this
复杂度
*this
和 other
的大小成线性。*this
的大小成线性,除非分配器不比较相等且不传播,该情况下与 *this
和 other
的大小成线性。*this
和 ilist
的大小成线性。异常
注意
容器移动赋值(重载 (2) )后,除非不兼容的分配器强制逐元素赋值,否则指向 other
的引用、指针和迭代器(除了尾迭代器)都保持合法,不过指代的元素现在在 *this 中。
void assign( InputIt first, InputIt last );(2)
替换容器的内容。
count
份 value
的副本替换内容。[first, last)
中元素的副本替换内容若 InputIt
为整数类型,则此重载与 (1) 拥有相同效果。(C++11 前)此重载仅若 InputIt
满足输入迭代器 (InputIterator
) 才参与重载决议。(C++11 起)ilist
的元素替换内容。所有指向容器元素的迭代器、指针及引用均被非法化。
参数
count-容器的新大小value-用以初始化容器元素的值first, last-复制来源元素的范围ilist-复制值来源的 initializer_list复杂度
count
成线性first
和 last
间的距离成线性返回与容器关联的分配器。
参数
(无)
返回值
关联的分配器。
复杂度
常数。
#include<iostream>#include<string>#include<list>using namespace std;//队列重载<<template<typename T>ostream& operator<<(ostream& s, const list<T>& v){s.put('[');char comma[3] = { '\0', ' ', '\0' };for (const auto& e : v) {s << comma << e;comma[0] = ',';}return s << ']';}int main(){list<int>lst;lst.push_back(1);lst.push_back(2);lst.push_back(3);cout << "lst:" << lst << endl;list<int>lst1(lst.begin(), lst.end());cout << "lst1:" << lst1 << endl;//复制构造list<int>lst2(lst);cout << "lst2:" << lst2 << endl;list<string>lst3(5, "AB");cout << "lst3:" << lst3 << endl;list<int>num1{ 1, 2, 3, 4, 5, 6 };list<int>num2;list<int>num3;cout << "num1:" << num1 << endl;// 复制赋值会从 nums1 复制数据到 nums2num2 = num1;cout << "num2:" << num2 << endl;// 移动赋值会从 nums1 移动数据到 nums3 num3 = move(num2);cout << "num3:" << num3 << endl;list<char>ch;ch.assign(6, '*');cout << "ch:" << ch << endl;//重新初始化对象num1.assign(2, 6);cout << "num1:" << num1 << endl;//list<char>ch1;ch1.assign(ch.begin(), ch.end());cout << "ch1:" << ch1 << endl;list<int> mylst;int * p;unsigned int i;//分配数组5个元素的空间用于deque分配器p = mylst.get_allocator().allocate(5);// 空间中赋值for (i = 0; i<5; i++)mylst.get_allocator().construct(&p[i], i);cout << "The allocated array contains:";for (i = 0; i<5; i++) cout << ' ' << p[i];cout << '\n';// 销毁空间for (i = 0; i<5; i++)mylst.get_allocator().destroy(&p[i]);lst.get_allocator().deallocate(p, 5);system("pause");return 0;}
2、
元素访问
返回到容器首元素的引用。
在空容器上对 front
的调用是未定义的。
参数
(无)
返回值
到首元素的引用
复杂度
常数
注意
对于容器 c
,表达式 c.front() 等价于 *c.begin() 。
返回到容器中最后一个元素的引用。
在空容器上对 back
的调用是未定义的。
参数
(无)
返回值
到最后元素的引用。
复杂度
常数。
注意
对于容器 c
,表达式 return c.back(); 等价于 { auto tmp = c.end(); --tmp; return *tmp; }
示例
示例省略,注意元素访问无operater[ ]和at。
3、
迭代器
cbegin
返回指向容器首元素的迭代器。
若容器为空,则返回的迭代将等于 end() 。
参数
(无)
返回值
指向首元素的迭代器
复杂度
常数
cend
返回指向后随容器最后元素的元素的迭代器。
此元素表现为占位符;试图访问它导致未定义行为。
参数
(无)
返回值
指向后随最后元素的迭代器。
复杂度
常数。
crbegin
返回值指向逆向容器的首元素。它对应非逆向容器的最末元素。
参数
(无)
返回值
指向首元素的逆向迭代器。
复杂度
常数
crend
返回逆向容器末元素的后一元素。它对应非逆向容器首元素的前一元素。此元素表现为占位符,试图访问它导致未定义行为。
参数
(无)
返回值
指向末元素后一元素的逆向迭代器。
复杂度
常数。
#include<iostream>#include<string>#include<list>using namespace std;int main(){list<string>str;str.assign(2, "abac");str.push_back("aaa");str.push_back("bbb");str.push_back("ccc");//迭代器list<string>::iterator iter = str.begin();for (; iter != str.end();){cout << *iter++ << ' ';}cout << endl;//常迭代器list<string>::const_iterator iter1 = str.begin();for (; iter1 != str.end();){cout << *iter1++ << ' ';}cout << endl;//常反迭代器list<string>::const_reverse_iterator iter2 = str.rbegin();for (; iter2 != str.rend();){cout << *iter2++ << ' ';}cout << endl;system("pause");return 0;}
4、
容量
(C++20 前)
检查容器是否无元素,即是否 begin() == end() 。
参数
(无)
返回值
若容器为空则为 true ,否则为 false
复杂度
常数。
返回容器中的元素数,即 std::distance(begin(), end()) 。
参数
(无)
返回值
容器中的元素数量。
复杂度
常数。
返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。
参数
(无)
返回值
元素数量的最大值。
复杂度
常数。
注意
此值典型地反映容器大小上的理论极限。运行时,容器的大小可能被可用 RAM 总量限制到小于 max_size()
的值。
注意:无shrink_to_fit()函数
#include<iostream>#include<string>#include<list>#include<ctime>using namespace std;int main(){srand(time(0));list<char> ch;for (int i = 0; i < 10; i++)ch.push_back((char)rand() % 10);cout << "ch size:" << ch.size() << endl;if (ch.empty() == 0)cout << "ch is null" << endl;ch.resize(20);//容器可保有的元素最大数量cout << "ch max_size:" << ch.max_size() << endl;system("pause");return 0;}
5、
修改器
从容器移除所有元素。
非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器保持合法。
参数
(无)
返回值
(无)
复杂度
与容器大小,即元素数成线性。
void insert( iterator pos, InputIt first, InputIt last);(C++11 前)template< class InputIt >
iterator insert( const_iterator pos, InputIt first, InputIt last );(C++11 起)
插入元素到容器中的指定位置。
pos
前插入 value
。pos
前插入 value
的 count
个副本。pos
前插入来自范围 [first, last)
的元素。若 InputIt
为整数类型,则此重载与重载 (3) 拥有相同效果。(C++11 前)此重载仅若 InputIt
足以为输入迭代器 (InputIterator
) 才参与重载决议,以避免与重载 (3) 有歧义。(C++11 起)若 first
和 last
是指向 *this 中的迭代器,则行为未定义。pos
前插入来自 initializer_list ilist
的元素。没有引用和迭代器被非法化。
参数
pos-将内容插入到其前的迭代器。pos
可为 end() 迭代器value-要插入的元素值first, last-要插入的元素范围,不能是指向调用 insert 所用的容器中的迭代器ilist-要插入的值来源的 initializer_list类型要求- 为使用重载 (1) , T
必须满足 CopyInsertable
的要求。- 为使用重载 (2) , T
必须满足 MoveInsertable
的要求。- 为使用重载 (3) , T
必须满足 CopyAssignable
和 CopyInsertable
的要求。- 为使用重载 (4,5) , T
必须满足 EmplaceConstructible
的要求。返回值
value
的迭代器。pos
。pos
。ilist
为空则为 pos
。复杂度
异常
若抛出异常,则无效果(强异常保证)。
template< class... Args >
iterator emplace( const_iterator pos, Args&&... args ); (C++11 起)
直接于 pos
前插入元素到容器中。通过 std::allocator_traits::construct 构造元素,它典型地用布置 new 在容器所提供的位置原位构造元素。将参数 args...
作为 std::forward<Args>(args)... 转发给构造函数。
没有引用和迭代器被非法化。
参数
pos-将构造新元素到其前的迭代器args-转发给元素构造函数的参数类型要求-T (容器元素类型)
必须满足 EmplaceConstructible
的要求。返回值
指向被安置的元素的迭代器。
复杂度
常数。
异常
若抛异常(例如由构造函数),则保留容器不修改,如同未曾调用过此函数(强异常保证)。
从容器移除指定的元素。
pos
的元素。[first; last)
中的元素。指向被擦除元素的迭代器和引用被非法化。其他引用和迭代器不受影响。
迭代器 pos
必须合法且可解引用。从而不能以 end() 迭代器(合法,但不可解引用)为 pos
的值。
若 first==last
则迭代器 first
不必可解引用:擦除空范围是无操作。
参数
pos-指向要移除的元素的迭代器first, last-要移除的元素范围返回值
后随最后被移除元素的迭代器。若迭代器 pos
指代最后元素,则返回 end() 迭代器。
异常
(无)
复杂度
first
和 last
间的距离成线性。后附给定元素 value
到容器尾。
value
的副本。value
进新元素。没有引用和迭代器被非法化。
参数
value-要后附的元素值类型要求- 为使用重载 (1) ,T
必须满足 CopyInsertable
的要求。- 为使用重载 (2) , T
必须满足 MoveInsertable
的要求。返回值
(无)
复杂度
常数。
异常
若抛出异常(可能因为 Allocator::allocate()
或元素复制/移动构造函数/赋值),则此函数无效果(强异常保证)。
template< class... Args >
void emplace_back( Args&&... args ); (C++11 起)
(C++17 前)template< class... Args >
reference emplace_back( Args&&... args ); (C++17 起)
添加新元素到容器尾。元素通过 std::allocator_traits::construct 构造,它典型地用布置 new 于容器所提供的位置原位构造元素。参数 args...
以 std::forward<Args>(args)... 转发到构造函数。
没有引用和迭代器被非法化。
参数
args-转发到元素构造函数的参数类型要求-T (容器元素类型)
必须满足 EmplaceConstructible
的要求。返回值
(无)(C++17 前)到被插入元素的引用。(C++17 起)复杂度
常数。
异常
若抛出异常,则此函数无效果(强异常保证)。
移除容器的最末元素。
在空容器上调用 pop_back
是未定义的。
指向被擦除元素的迭代器和引用被非法化。
参数
(无)
返回值
(无)
复杂度
常数。
异常
(无)
前附给定元素 value
到容器起始。
没有引用和迭代器被非法化。
参数
value-要前附的元素值返回值
(无)
复杂度
常数。
异常
若抛出异常,则此函数无效果(强异常保证)。
template< class... Args >
void emplace_front( Args&&... args ); (C++11 起)
(C++17 前)template< class... Args >
reference emplace_front( Args&&... args ); (C++17 起)
插入新元素到容器起始。通过 std::allocator_traits::construct 构造元素,它典型地用布置 new 在容器所提供的位置原位构造元素。将参数 args...
作为 std::forward<Args>(args)... 转发给构造函数。
没有引用和迭代器被非法化。
参数
args-转发给元素构造函数的参数类型要求-T (容器元素类型)
必须满足 EmplaceConstructible
的要求。返回值
(无)(C++17 前)到被插入元素的引用。(C++17 起)复杂度
常数。
异常
若抛异常,则此函数无效果(强异常保证)。
移除容器首元素。若容器中无元素,则行为未定义。
指向被擦除元素的迭代器和引用被非法化。
参数
(无)
返回值
(无)
复杂度
常数。
异常
不抛出。
重设容器大小以容纳 count
个元素。
若当前大小大于 count
,则减小容器为其首 count
个元素。
若当前大小小于 count
,则后附额外元素,并以 value
的副本初始化。
若当前大小小于 count
,
value
的副本参数
count-容器的大小value-用以初始化新元素的值类型要求- 为使用重载 (1) ,T
必须满足 DefaultInsertable
的要求。- 为使用重载 (2) , T
必须满足 CopyInsertable
的要求。返回值
(无)
复杂度
与当前大小和 count
间的差成线性。。
将内容与 other
的交换。不在单个元素上调用任何移动、复制或交换操作。
所有迭代器和引用保持合法。在操作后,保有此容器中尾后值的迭代器指代此容器或另一容器是未指定的。
swap
的非限定调用交换分配器。否则,不交换它们(且若 get_allocator() != other.get_allocator() ,则行为未定义)。(C++11 起)参数
other-要与之交换内容的容器返回值
(无)
异常
(无)
(C++17 前)复杂度
常数。
#include<iostream>#include<string>#include<list>#include<ctime>#include<vector>using namespace std;int main(){list<string> str;str.push_back("Hello");str.push_back("World");cout << "str: " << str.front() << " size:" << str.size() << endl;str.clear();if (!str.empty())cout << "str: " << str.front() << endl;else cout<< "size:" << str.size() << endl;list<int> mylist;//插入// set some initial values:for (int i = 1; i<6; i++)mylist.push_back(i); // 1 2 3 4 5list<int>::iterator it = mylist.begin();++it;it = mylist.insert(it, 10); // 1 10 2 3 4 5// "it" now points to the newly inserted 10mylist.insert(it, 2, 20); // 1 20 20 10 2 3 4 5// "it" no longer valid!it = mylist.begin();vector<int> myvector(2, 30);mylist.insert(it, myvector.begin(), myvector.end());// 1 20 30 30 20 10 2 3 4 5cout << "mylist contains:";for (it = mylist.begin(); it != mylist.end(); ++it)cout << ' ' << *it;cout << '\n';list<int> mylist1 = { 10, 20, 30 };auto it1 = mylist1.emplace(mylist1.begin(), 100);mylist1.emplace(it1, 200);mylist1.emplace(mylist1.end(), 300);cout << "mylist1 contains:";for (auto& x : mylist1)cout << ' ' << x;cout << '\n';mylist1.emplace_back(100);mylist1.emplace_back(200);cout << "emplace_back:" << endl;cout << "mylist1 contains:";for (auto& x : mylist1)cout << ' ' << x;cout << '\n';list<string> str1;str1.push_back("Hello");str1.push_back("world");cout << "str1: " << str1.front() << " size:" << str1.size() << endl;str1.erase(str1.begin());if (!str1.empty())cout << "str1: " << str1.front() << " size:" << str1.size() << endl;elsecout << "size:" << str1.size() << endl;list<int> arr{ 1, 2, 3, 4, 5, 6 };for (list<int>::iterator it = arr.begin(); it != arr.end(); it++)cout << *it << ' ';cout << endl;//移除末元素 arr.pop_back();cout << "pop_back:" << endl;for (list<int>::iterator it = arr.begin(); it != arr.end(); it++)cout << *it << ' ';cout << endl;//移除首元素 arr.pop_front();cout << "pop_front:" << endl;for (list<int>::iterator it = arr.begin(); it != arr.end(); it++)cout << *it << ' ';cout << endl;//首元素插入arr.push_front(6);arr.push_front(6);arr.push_front(6);cout << "push_front:" << endl;for (list<int>::iterator it = arr.begin(); it != arr.end(); it++)cout << *it << ' ';cout << endl;//交换list<int>arr1(5, 9);cout << "arr1 size:" << arr1.size() << endl;arr1.swap(arr);cout << "arr1 size:" << arr1.size() << endl;for (list<int>::iterator it = arr.begin(); it != arr.end(); it++)cout << *it << ' ';cout << endl;//首元素插入arr.emplace_front(66);arr.emplace_front(66);arr.emplace_front(66);cout << "emplace_front:" << endl;for (list<int>::iterator it = arr.begin(); it != arr.end(); it++)cout << *it << ' ';cout << endl;system("pause");return 0;}
6、
操作
void merge( list& other, Compare comp );(2) template <class Compare>
void merge( list&& other, Compare comp );(2)(C++11 起)
归并二个已排序链表为一个。链表应以升序排序。
不复制元素。操作后容器 other
变为空。若 this == &other 则函数不做任何事。若 get_allocator() != other.get_allocator() ,则行为未定义。没有引用和迭代器变得非法,除了被移动元素的迭代器现在指代到 *this 中,而非到 other
中,第一版本用 operator< 比较元素,第二版本用给定的比较函数 comp
。
此操作是稳定的:对于二个链表中的等价元素,来自 *this
的元素始终前驱来自 other
的元素,而且 *this
和 other
的等价元素顺序不更改。
参数
other-要交换的另一容器comp-比较函数对象(即满足比较 (Compare
) 概念的对象),若第一参数小于(即先序于)第二参数则返回 true 。比较函数的签名应等价于如下者:
bool cmp(const Type1 &a, const Type2 &b);
签名不必拥有 const & ,但函数对象必须不修改传递给它的对象。
类型 Type1 与 Type2 必须使得 list<T,Allocator>::const_iterator 类型的对象能在解引用后隐式转换到这两个类型。
返回值
(无)
异常
若抛出异常,则此函数无效果(强异常保证),除非异常来自比较函数。
复杂度
至多 std::distance(begin(), end()) + std::distance(other.begin(), other.end()) - 1 次比较。
list
中移动元素 (公开成员函数)const_iterator first, const_iterator last);(3) void splice( const_iterator pos, list&& other,
const_iterator first, const_iterator last );(3)(C++11 起)
从一个 list 转移元素给另一个。
不复制或移动元素,仅重指向链表结点的内部指针。若 get_allocator() != other.get_allocator() 则行为未定义。没有迭代器或引用被非法化,指向被移动元素的迭代器保持合法,但现在指代到 *this 中,而非到 other
中。
other
转移所有元素到 *this 中。元素被插入到 pos
所指向的元素之前。操作后容器 other
变为空。若 this == &other 则行为未定义。other
转移 it
所指向的元素到 *this 。元素被插入到 pos
所指向的元素之前。other
转移范围 [first, last)
中的元素到 *this 。元素被插入到 pos
所指向的元素之前。若 pos
是范围 [first,last)
中的迭代器则行为未定义。参数
pos-将插入内容到其前的元素other-要自之转移内容的另一容器it-要从other
转移到 *this 的元素first, last-要从 other
转移到 *this 的元素范围返回值
(无)
复杂度
1-2) 常数。
3) 若 this == &other 则为常数,否则与 std::distance(first, last) 成线性。
remove_if
void remove_if( UnaryPredicate p );
移除所有满足特定标准的元素。第一版本移除所有等于 value
的元素,第二版本移除所有谓词 p
对它返回 true 的元素。
参数
value-要移除的元素的值p-是否应移除该元素则返回 true 的一元谓词。谓词函数签名应等价于如下者:
bool pred(const Type &a);
签名不必拥有 const & ,但函数必须不修改传递给它的对象。
类型 Type 必须使得 list<T,Allocator>::const_iterator 类型对象能在解引用后隐式转换到 Type 。
返回值
(无)
复杂度
与容器大小成线性
逆转容器中的元素顺序。不非法化任何引用或迭代器。
参数
(无)
返回值
(无)
参数
与容器大小成线性
void unique( BinaryPredicate p );(2)
从容器移除所有相继的重复元素。只留下相等元素组中的第一个元素。第一版本用 operator==
比较元素,第二版本用二元谓词 p
比较元素
参数
p-若元素应被当做相等则返回 true 的二元谓词。谓词函数的签名应等价于如下者:
bool pred(const Type1 &a, const Type2 &b);
签名不必拥有 const & ,但函数必须不修改传递给它的对象。
类型 Type1 与 Type2 必须使得 list<T,Allocator>::const_iterator 类型的对象能在解引用后隐式转换到这两个类型。
返回值
(无)
复杂度
与容器大小成线性
void sort( Compare comp );(2)
以升序排序元素。保持相等元素的顺序。第一版本用 operator< 比较元素,第二版本用给定的比较函数 comp
。
若抛出异常,则 *this 中元素顺序未指定。
参数
comp-比较函数对象(即满足比较 (Compare
) 概念的对象),若第一参数小于(即先序于)第二参数则返回 true 。比较函数的签名应等价于如下者:
bool cmp(const Type1 &a, const Type2 &b);
签名不必拥有 const & ,但函数对象必须不修改传递给它的对象。
类型 Type1 与 Type2 必须使得 list<T,Allocator>::const_iterator 类型的对象能在解引用后隐式转换到这两个类型。
返回值
(无)
复杂度
大约 N log N 次比较,其中 N 是表中的元素数。
注意
std::sort 要求随机访问迭代器且不能用于 list
。此函数与 std::sort 的区别在于,它不要求 list
的元素类型可交换,保留所有迭代器的值,并进行稳定排序。
#include<iostream>#include<list>using namespace std;template<typename T>ostream&operator<<(ostream&s, const list<T>&list){for (auto &i : list){s << " " << i;}return s;}int main(){list<int>list1{ 1, 6, 3, 6, 2, 8 };list<int>list2{ 7, 4, 2, 8, 6, 4, 9 };//列表元素排序list1.sort();list2.sort();cout << "list1:" << list1 << endl;cout << "list2:" << list2 << endl;list1.merge(list2);cout << "list1 merge:" << list1 << endl;advance(list1.begin(), 0);cout << "list1 advace:" << list1 << endl;//从一个 list 转移元素给另一个。//不复制或移动元素,仅重指向链表结点的内部指针。list1.splice(list1.begin(), list2);//将list2所有元素放置到list1中cout << "list1:" << list1 << endl;cout << "list2:" << list2 <<" size:"<<list2.size()<< endl;////将list1所有元素放置到list2中list2.splice(list2.begin(), list1, list1.begin(), list1.end());cout << "list1:" << list1 << endl;cout << "list2:" << list2 << endl;list2.remove(6);// 移除所有等于 6的元素cout << "list2:" << list2 << endl;list2.remove_if([](int n){ return n > 6; }); // 移除全部大于 6 的元素cout << "list2:" << list2 << endl;//列表反转list2.reverse();cout << "list2:" << list2 << endl;//从容器移除所有相继的重复元素。list2.unique();cout << "list2:" << list2 << endl;system("pause");return 0;}
7、
非成员函数
operator!=
operator<
operator<=
operator>
operator>=
template< class T, class Alloc >
bool operator==( const list<T,Alloc>& lhs,
bool operator!=( const list<T,Alloc>& lhs,
bool operator<( const list<T,Alloc>& lhs,
bool operator<=( const list<T,Alloc>& lhs,
bool operator>( const list<T,Alloc>& lhs,
bool operator>=( const list<T,Alloc>& lhs,
比较二个容器的内容。
lhs
与 rhs
的内容是否相等,即是否 lhs.size() == rhs.size() 且每个 lhs
中的元素与 rhs
的同位置元素比较相等。lhs
与 rhs
的内容。按照等价于 std::lexicographical_compare 的函数进行比较。参数
lhs, rhs-要比较内容的容器- 为使用重载 (1-2) ,T
必须满足 EqualityComparable
的要求。- 为使用重载 (3-6) , T
必须满足 LessThanComparable
的要求。顺序关系必须建立全序。返回值
lhs
的内容按字典序小于 rhs
的内容则为 true ,否则为 falselhs
的内容按字典序小于或等于 rhs
的内容则为 true ,否则为 falselhs
的内容按字典序大于 rhs
的内容则为 true ,否则为 falselhs
的内容按字典序大于或等于 rhs
的内容则为 true ,否则为 false复杂度
与容器大小成线性
template< class T, class Alloc >
void swap( list<T,Alloc>& lhs,
void swap( list<T,Alloc>& lhs,
为 std::list 特化 std::swap 算法。交换 lhs
与 rhs
的内容。调用 lhs.swap(rhs) 。
参数
lhs, rhs-要交换内容的容器返回值
(无)
复杂度
常数。
异常
#include <iostream>#include <list>using namespace std;int main(){list<int> a = { 10, 20, 30 };list<int> b = { 10, 20, 30 };list<int> c = { 30, 20, 10 };if (a == b) cout << "a and b are equal\n";if (b != c) cout << "b and c are not equal\n";if (b<c) cout << "b is less than c\n";if (c>b) cout << "c is greater than b\n";if (a <= b) cout << "a is less than or equal to b\n";if (a >= b) cout << "a is greater than or equal to b\n";system("pause");return 0;}swap:
//swap (deque overload)#include <iostream>#include <list>using namespace std;int main(){unsigned int i;list<int> foo(3, 100); // three ints with a value of 100list<int> bar(5, 200); // five ints with a value of 200swap(foo, bar);cout << "foo contains:";for (list<int>::iterator it = foo.begin(); it != foo.end(); ++it)cout << ' ' << *it;cout << '\n';cout << "bar contains:";for (list<int>::iterator it = bar.begin(); it != bar.end(); ++it)cout << ' ' << *it;cout << '\n';system("pause");return 0;}
自定义类测试:
#include<iostream>#include<list>using namespace std;class Myclass{public :Myclass(int a, int b_) :b(b_){this->a = a;}void fun(){cout << "My fun" << endl;}int b;private:int a;};int main(){list<Myclass*>lst;Myclass *p = new Myclass(5,6);lst.push_back(p);lst.front()->fun();cout << lst.front()->b << endl;system("pause");return 0;}
待续。。。。。。。
- STL(五)list 双向链表
- STL - list(双向链表)
- STL-list(双向链表)
- STL双向链表之删除重复元素(list)
- 双向循环链表(为STL LIST 做准备)
- STL序列式容器之list(双向链表)
- STL(八)list双向链表容器
- c++stl的list(双向链表)
- STL list为双向循环链表
- STL 之 list 双向链表
- STL系列(3):List 双向链表
- STL list双向链表容器
- stl,vector, list,双向链表,map
- 【C++ STL】细数C++ STL 的那些事---List(双向链表)
- 【C++ STL】细数C++ STL 的那些事---List(双向链表)
- C++ STL学习笔记四 list双向链表容器
- C++ STL 容器技术 之 list双向链表容器
- C++ STL 容器技术 之 list双向链表容器
- git 命令
- OOALV单个container放置多个ALV grid
- 小东吖 之 java的基础知识以及break 和 continue 关键字的使用
- 关于SSH的经典知识
- JAVA 与 MyCat(2) 单例模式
- STL(五)list 双向链表
- ToolBar的封装、动态改变状态栏颜色
- 20171130_tensorflow_tf.Variable
- CentOS7 下安装docker和docker-compose
- 面向对象(上)
- 获取python未知异常信息的方法
- 基于最小均方差(维纳)滤波的图像去模糊
- java.lang.NoSuchMethodError: redis.clients.jedis.JedisShardInfo.setTimeout(I)V
- 九九乘法表