【C++序列式容器】list

目录

list

1. Member functions

1.1 constructor、destructor、operator=

1.1.1 constructor

1.1.2 destructor

1.1.3 operator=

1.2 Iterators

1.3 Capacity

1.3.1 empty

1.3.2 size

1.3.3 max_size

1.4 Element access

1.4.1 front

1.4.2 back

1.5 Modifiers

1.5.1 assign

1.5.2 emplace_front

1.5.3 push_front

1.5.4 pop_front

1.5.5 emplace_back

1.5.6 push_back

1.5.7 pop_back

1.5.8 emplace

1.5.9 insert

1.5.10 erase

1.5.11 swap

1.5.12 resize

1.5.13 clear

1.6 Operations

1.6.1 splice

1.6.2 remove

1.6.3 remove_if

1.6.4 unique

1.6.5 merge

1.6.6 sort

1.6.7 reverse

1.7 Observers

1.7.1 get_allocator

2. Non-member function overloads

2.1 relational operators

2.2 swap

3. list对象的遍历方法

3.1 迭代器

3.2 范围for


list

template < class T, class Alloc = allocator<T> > class list;

list是序列式容器,允许在序列内的任何地方进行恒定时间的插入和删除操作,以及双向的迭代。

list容器被实现为双向链表;双向链表可以将它们包含的每个元素存储在不同的、不相关的存储位置。顺序是通过每个元素与前面的元素和后面的元素的链接在内部保持的。

它们与forward_list非常相似:主要的区别是forward_list对象是单向链表,因此它们只能向前迭代,以换取更小和更高的效率。

与其他基本的标准序列式容器(array、vector和deque)相比,list在插入、提取和移动容器内任何已经获得迭代器的位置上的元素时通常表现得更好,因此在密集使用这些元素的算法中也是如此,比如排序算法。

与其他序列式容器相比,list和forward_list的主要缺点是它们缺乏对元素位置的直接访问;例如,要访问列表中的第六个元素,必须从一个已知的位置(如开头或结尾)迭代到该位置,这需要在这些距离中花费线性时间。它们也会消耗一些额外的内存来保持与每个元素相关的链接信息(这对于小尺寸元素的大列表来说可能是一个重要因素)。

list定义在头文件list和命名空间std中。

1. Member functions

1.1 constructor、destructor、operator=

1.1.1 constructor

// default (1)
explicit list(const allocator_type& alloc = allocator_type());
// fill(2)
explicit list(size_type n);
list(size_type n, const value_type& val, const allocator_type& alloc = allocator_type());
// range(3)
template <class InputIterator> list(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());
// copy(4)
list(const list& x);
list(const list& x, const allocator_type& alloc);
// move(5)
list(list&& x);
list(list&& x, const allocator_type& alloc);
// initializer list(6)
list(initializer_list<value_type> il, const allocator_type& alloc = allocator_type());
#include <list>
#include <string>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt1; // default
	printLt(lt1);  // 空

	list<int> lt2(5); // fill
	printLt(lt2);     // 0 0 0 0 0

	list<int> lt3(10, 1); // fill
	printLt(lt3);         // 1 1 1 1 1 1 1 1 1 1

	string s("hello world");
	list<char> lt4(s.begin() + 3, --s.end()); // range
	printLt(lt4);                             // l o   w o r l

	list<char> lt5(lt4); // copy
	// 等价于list<char> lt5 = lt4;
	printLt(lt5);        // l o   w o r l

	list<char> lt6(std::move(lt5));   // move
	cout << "lt5: ";    printLt(lt5); // lt5: 
	cout << "lt6: ";    printLt(lt6); // lt6: l o   w o r l

	list<string> lt7{ "happy","new","year" }; // initializer list
	// 等价于list<string> lt7 = { "happy","new","year" };
	printLt(lt7);                             // happy new year

	return 0;
}

1.1.2 destructor

~list();

1.1.3 operator=

// copy (1)
list& operator=(const list& x);
// move (2)
list& operator=(list&& x);
// initializer list (3)
list& operator=(initializer_list<value_type> il);
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt(5, 2);
	printLt(lt); // 2 2 2 2 2

	list<int> lt1;
	lt1 = lt;     // copy
	printLt(lt1); // 2 2 2 2 2

	list<int> lt2;
	lt2 = std::move(lt1);             // move
	cout << "lt1: ";    printLt(lt1); // lt1: 
	cout << "lt2: ";    printLt(lt2); // lt2: 2 2 2 2 2

	list<int> lt3;
	lt3 = { 1,2,3,4,5,6 }; // initializer list
	printLt(lt3);          // 1 2 3 4 5 6

	return 0;
}

1.2 Iterators

// begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
// end
iterator end() noexcept;
const_iterator end() const noexcept;
// rbegin
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
// rend
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
// cbegin
const_iterator cbegin() const noexcept;
// cend
const_iterator cend() const noexcept;
// crbegin
const_reverse_iterator crbegin() const noexcept;
// crend
const_reverse_iterator crend() const noexcept;
函数功能

begin

&

end

begin返回一个迭代器,指向list中第一个元素

end返回一个迭代器,指向list中最后一个元素的下一个位置

rbegin

&

rend

rbegin返回一个反向迭代器,指向list中最后一个元素

rend返回一个反向迭代器,指向list中第一个元素的上一个位置

cbegin

&

cend

cbegin返回一个const迭代器,指向list中第一个元素

cend返回一个const迭代器,指向list中最后一个元素的下一个位置

crbegin

&

crend

crbegin返回一个const反向迭代器,指向list中最后一个元素

crend返回一个const反向迭代器,指向list中第一个元素的上一个位置

begin&end和rbegin&rend返回的迭代器指向:

​​

const_iterator是一个指向const内容的迭代器。迭代器本身可以修改,但是它不能被用来修改它所指向的内容。

begin&end/rbegin&rend和cbegin&cend/crbegin&crend的不同:

  • begin&end/rbegin&rend的返回类型由对象是否是常量来决定。如果不是常量,返回iterator;如果是常量,返回const_iterator。
  • cbegin&cend/crbegin&crend的返回类型是const_iterator,不管对象本身是否是常量。

list迭代器的特点:不支持算数运算(+、-、+=、-=、-、>、>=、<、<=)。

#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt{ 4,5,6,7 };

	list<int>::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	// 4 5 6 7

	auto rit = lt.rbegin();
	// list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
	// 7 6 5 4

	return 0;
}

1.3 Capacity

1.3.1 empty

bool empty() const noexcept;
// 检测list是否为空,是返回true,否则返回false

1.3.2 size

size_type size() const noexcept;
// 返回list中元素的个数

1.3.3 max_size

size_type max_size() const noexcept;
// 返回list能够容纳的最大元素个数

Capacity系列函数使用示例:

#include <list>
#include <iostream>
using namespace std;

int main()
{
	list<int> lt{ 4,5,6,7 };

	if (lt.empty())
		cout << "list为空" << endl;
	else
		cout << "list不为空" << endl;
	// list不为空

	cout << lt.size() << endl; // 4

	cout << lt.max_size() << endl; // 357913941

	return 0;
}

1.4 Element access

1.4.1 front

reference front();
const_reference front() const;
// 返回list中第一个元素的引用

1.4.2 back

reference back();
const_reference back() const;
// 返回list中最后一个元素的引用

Element access系列函数使用示例:

#include <list>
#include <iostream>
using namespace std;

int main()
{
	list<int> lt{ 4,5,6,7 };

	cout << lt.front() << endl; // 4
	cout << lt.back() << endl;  // 7

	return 0;
}

1.5 Modifiers

1.5.1 assign

// range(1)
template <class InputIterator> void assign(InputIterator first, InputIterator last);
// fill(2)
void assign(size_type n, const value_type& val);
// initializer list(3)
void assign(initializer_list<value_type> il);

// 给list赋值,替换其当前内容
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt1{ 1,2,3,4 };
	list<int> lt2{ 5,6,7,8,9 };

	lt1.assign(++lt2.begin(), --lt2.end()); // range
	printLt(lt1);                           // 6 7 8

	lt1.assign(10, 1); // fill
	printLt(lt1);      // 1 1 1 1 1 1 1 1 1 1

	lt1.assign({ 77,88 }); // initializer list
	printLt(lt1);          // 77 88

	return 0;
}

1.5.2 emplace_front

template <class... Args> void emplace_front(Args&&... args);
// 对应push_front,区别是:
// 当调用push_front时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
// 当调用emplace_front时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素

1.5.3 push_front

void push_front(const value_type& val);
void push_front(value_type&& val);
// 头插
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt{ 2,3,4 };
	int val = 1;

	lt.push_front(val);
	printLt(lt); // 1 2 3 4

	lt.push_front(0);
	printLt(lt); // 0 1 2 3 4

	return 0;
}

1.5.4 pop_front

void pop_front();
// 头删
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt{ 2,3,4 };

	lt.pop_front();
	printLt(lt); // 3 4

	lt.pop_front();
	printLt(lt); // 4

	return 0;
}

1.5.5 emplace_back

template <class... Args> void emplace_back(Args&&... args);
// 对应push_back,区别是:
// 当调用push_back时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
// 当调用emplace_back时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素

1.5.6 push_back

void push_back(const value_type& val);
void push_back(value_type&& val);
// 尾插
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt{ 1,2,3 };
	int val = 4;

	lt.push_back(val);
	printLt(lt); // 1 2 3 4

	lt.push_back(5);
	printLt(lt); // 1 2 3 4 5

	return 0;
}

1.5.7 pop_back

void pop_back();
// 尾删
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt{ 1,2,3 };

	lt.pop_back();
	printLt(lt); // 1 2

	lt.pop_back();
	printLt(lt); // 1

	return 0;
}

1.5.8 emplace

template <class... Args> iterator emplace(const_iterator position, Args&&... args);
// 对应insert,区别是:
// 当调用insert时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中
// 当调用emplace时,则是将参数传递给元素类型的构造函数,然后使用这些参数在容器管理的内存空间中直接构造元素

1.5.9 insert

// single element(1)
iterator insert(const_iterator position, const value_type& val);
// fill(2)
iterator insert(const_iterator position, size_type n, const value_type& val);
// range(3)
template <class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last);
// move(4)
iterator insert(const_iterator position, value_type&& val);
// initializer list(5)
iterator insert(const_iterator position, initializer_list<value_type> il);

// 在position位置插入
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt{ 1,2,3 };
	int val = 4;
	int arr[] = { 11,22 };

	lt.insert(lt.end(), val); // single element
	printLt(lt);              // 1 2 3 4

	lt.insert(lt.end(), 2, 5); // fill
	printLt(lt);               // 1 2 3 4 5 5

	lt.insert(lt.begin(), arr, arr + 2); // range
	printLt(lt);                         // 11 22 1 2 3 4 5 5

	lt.insert(lt.begin(), 0); // move
	printLt(lt);              // 0 11 22 1 2 3 4 5 5

	lt.insert(--lt.end(), { 99,88 }); // initializer list
	printLt(lt);                      // 0 11 22 1 2 3 4 5 99 88 5

	return 0;
}

1.5.10 erase

iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
// 删除
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt{ 1,2,3,4 };
	
	lt.erase(++lt.begin());
	printLt(lt); // 1 3 4

	lt.erase(lt.begin(), --lt.end());
	printLt(lt); // 4

	return 0;
}

1.5.11 swap

void swap(list& x);
// 交换
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt1{ 1,2,3,4 };
	list<int> lt2{ 9,8,7 };

	lt1.swap(lt2);
	printLt(lt1); // 9 8 7
	printLt(lt2); // 1 2 3 4

	return 0;
}

1.5.12 resize

void resize(size_type n);
void resize(size_type n, const value_type& val);
// 调整list的大小为n
// 如果n<当前的大小,多余的元素会被截掉
// 如果n>当前的大小,则:
// 1)如果没有指定填充元素,则使用默认构造函数
// 2)如果指定了填充元素val,则多出的空间用val填充
#include <list>
#include <iostream>
using namespace std;

template<typename T>
void printLt(list<T>& lt)
{
	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

int main()
{
	list<int> lt{ 1,2,3 };

	lt.resize(6, 4);
	printLt(lt); // 1 2 3 4 4 4

	lt.resize(2);
	printLt(lt); // 1 2

	return 0;
}

1.5.13 clear

void clear() noexcept;
// 清空
#include <list>
#include <iostream>
using namespace std;

int main()
{
	list<int> lt{ 1,2,3 };

	lt.clear();
	if (lt.empty())
		cout << "lt被清空" << endl;
	else
		cout << "lt没被清空" << endl;
	// lt被清空

	return 0;
}

1.6 Operations

1.6.1 splice

// entire list (1)
void splice(const_iterator position, list& x);
void splice(const_iterator position, list&& x);
// single element (2)
void splice(const_iterator position, list& x, const_iterator i);
void splice(const_iterator position, list&& x, const_iterator i);
// element range (3) 注意区间是[first, last),与forward_list不同
void splice(const_iterator position, list& x, const_iterator first, const_iterator last);
void splice(const_iterator position, list&& x, const_iterator first, const_iterator last);

// 从另一个list转移元素
// 将元素从x转移到容器中,将它们插入到position位置,注意是转移,不是拷贝

1.6.2 remove

void remove(const value_type& val);
// 移除具有特定值的元素

1.6.3 remove_if

template <class Predicate> void remove_if(Predicate pred);
// 移除满足条件的元素

1.6.4 unique

// (1)
void unique();
// (2)
template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);

// 去重

1.6.5 merge

// (1)
void merge(list& x);
void merge(list&& x);
// (2)
template <class Compare> void merge(list& x, Compare comp);
template <class Compare> void merge(list&& x, Compare comp);

// 合并有序链表
// 将参数x合并到调用merge的链表中

1.6.6 sort

// (1)
void sort();
// (2)
template <class Compare> void sort(Compare comp);

// 排序链表

1.6.7 reverse

void reverse() noexcept;
// 反转链表

1.7 Observers

1.7.1 get_allocator

allocator_type get_allocator() const noexcept;
// 返回空间配置器

2. Non-member function overloads

2.1 relational operators

// (1)
template <class T, class Alloc> bool operator==(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (2)
template <class T, class Alloc> bool operator!=(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (3)
template <class T, class Alloc> bool operator<(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (4)
template <class T, class Alloc> bool operator<=(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (5)
template <class T, class Alloc> bool operator>(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);
// (6)
template <class T, class Alloc> bool operator>=(const list<T,Alloc>& lhs, const list<T,Alloc>& rhs);

2.2 swap

template <class T, class Alloc> void swap(list<T, Alloc>& x, list<T, Alloc>& y);

3. list对象的遍历方法

3.1 迭代器

#include <list>
#include <iostream>
using namespace std;

int main()
{
	list<int> lt{ 1,2,3,4 };

	list<int>::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	// 1 2 3 4

	auto rit = lt.rbegin();
	// list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
	// 4 3 2 1

	return 0;
}

3.2 范围for

#include <list>
#include <iostream>
using namespace std;

int main()
{
	list<int> lt{ 1,2,3,4 };

	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
	// 1 2 3 4

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值