【C++】 STL库list容器


  1. 头文件:#include

  2. Lists将元素按顺序储存在链表中。与 向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢。

  3. list的特点:

    (1)不使用连续的内存空间这样可以随意地进行动态操作;
    (2)可以在内部任何位置快速地插入或删除,当然也可以在两端进行push和pop。
    (3)不能进行内部的随机访问,即不支持[ ] 操作符和vector.at()
    (4)相对于verctor占用更多的内存。

1、 list中的构造函数

  1. list() 声明一个空列表;
  2. list(n) 声明一个有n个元素的列表,每个元素都是由其默认构造函数T()构造出来的,元素默认值为:0,即n个0
  3. list(n,val) 声明一个由n个val元素的列表;
  4. list(first,last) 声明一个列表,其元素的初始值来源于由区间所指定的序列中的元素;
  5. list (const list &);拷贝构造函数,要求类型一致;
  1. list data4(data3.begin(),data3.end()); √
    list data4(data3.begin(),data3.begin()+3); ×
    报错:没有“+”运算符重载
  2. for (; itor4 != data4.end()-8; ++itor4) { // 报错:没有“-”运算符重载
    cout << *itor4 << " ";
    }

for (; itor4 != data4.end(); ++itor4) {
cout << *itor4 << " "; // k k k k k k
}

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

int main() {
	//------------------ 1. list() 声明一个空列表
	list<int> data1;
	cout << data1.size() << endl; // 0


	 //------------------ 2.   list(n) 声明一个有n个元素的列表.值为0
	list<int> data(10);

	list<int>::iterator itor = data.begin();   // 遍历
	for (; itor != data.end(); ++itor) {
		cout << *itor << " ";	// 0 0 0 0 0 0 0 0 0 0  
	}

	//------------------3. list(n, val) 
	list<int> data2(5, 10);

	list<int>::iterator itor2 = data2.begin();   // 遍历
	for (; itor2 != data2.end(); ++itor2) {
		cout << *itor2 << " ";	// 10 10 10 10 10 
	}


	//------------------4. list(first, last) 声明一个列表,其元素的初始值来源于由区间所指定的序列中的元素
	list<char> data3(6,'k');
	list<char> data4(data3.begin(),data3.end());

	list<char>::iterator itor4 = data4.begin();   // 遍历
	for (; itor4 != data4.end(); ++itor4) {
		cout << *itor4 << " ";	// k k k k k k 
	}


	//------------------5. list(const list &); 拷贝构造函数
	list<char> data5(6, 'g');
	list<char> data6(data5);

	list<char>::iterator itor6 = data6.begin();   // 遍历
	for (; itor6 != data6.end(); ++itor6) {
		cout << *itor6 << " ";	// g g g g g g
	}

	return 0;
}

2、 begin()和end()——list 容器的iterator

  1. 通过调用list容器的成员函数begin()得到一个指向容器起始位置的iterator
  2. 可以调用list容器的end()函数来得到list末端下一位置,相当于:int a[n]中的第n+1个位置a[n],实际上是不存在的,不能访问,经常作为循环结束判断结束条件使用。

3、 增

3.1 push_back() 末端插入

3.2 push_front() 头部插入

3.3 insert() 在指定位置插入n个元素

  1. l1.insert(l1.begin(),100); // 在l1的开始位置插入100。
  2. l1.insert(l1.begin(),2,200); // 在l1的开始位置插入2个100。
  3. l1.insert(l1.begin(),l2.begin(),l2.end()); // 在l1的开始位置插入l2的从开始到结束的所有位置的元素。

代码演示

int main() {
	//------------------ insert() 在指定位置插入n个元素
	list<int> data1;
	data1.push_back(1);
	data1.push_back(1);
	data1.push_back(1);

	data1.push_front(2);
	data1.push_front(2);
	data1.push_front(2);

	list<int>::iterator itor1 = data1.begin();   // 遍历
	for (; itor1 != data1.end(); ++itor1) {
		cout << *itor1 << " ";	// 2 2 2 1 1 1
	}

	//******** 1.在某个位置插入1个x
	data1.insert(data1.begin(), 9);
	data1.insert(data1.begin(), 10);
	list<int>::iterator itor2 = data1.begin();   // 遍历
	for (; itor2 != data1.end(); ++itor2) {
		cout << *itor2 << " ";	// 10 9 2 2 2 1 1 1
	}

	//******** 2.在某个位置插入n个x
	list<int> data2;
	data2.push_back(1);
	data2.push_back(1);
	data2.push_back(1);

	data2.insert(data2.begin(), 5, 4); // 头插
	data2.insert(data2.begin(), 2, 7);

	data2.insert(data2.end(), 5, 4);  // 尾插
	data2.insert(data2.end(), 2, 7);
	
	for (list<int>::iterator itor3 = data2.begin(); itor3 != data2.end(); ++itor3) {   // 遍历
		cout << *itor3 << " ";	//  7 7 4 4 4 4 4 1 1 1 4 4 4 4 4 7 7
	}


	//******** 3.在某个位置插入[begin,end)元素
	list<int> data3;
	data3.push_back(1);
	data3.push_back(1);
	data3.push_back(1);

	list<int> data4;
	data4.push_back(2);
	data4.push_back(2);
	data4.push_back(2);
	cout << endl;

	data3.insert(data3.begin(), data4.begin(),data4.end()); // 头插
	for (auto itor3 = data3.begin(); itor3 != data3.end(); ++itor3) {   // 遍历
		cout << *itor3 << " ";	// 2 2 2 1 1 1
	}

	return 0;
}

4、删

  1. 通过pop_back()删除最后一个元素,通过pop_front()删除第一个元素;
  2. 序列必须不为空,如果当list为空的时候调用pop_back()和pop_front()会使程序崩掉。

4.1 pop_back() 删尾

4.2 pop_front() 删头

4.3 erase() 删除n个元素

  1. l1.erase(l1.begin()); 将l1的第一个元素删除。
  2. l1.erase(l1.begin(),l1.end()); 将l1的从begin()到end()之间的元素删除。

【注意】:
data2.end() 表示指向4后面的位置,该位置不存在元素,因此:
auto itor2 = data2.erase(–data2.end()); ✔ 删除的是4,剩下为 2 3
auto itor2 = data2.erase(data2.end()); ❌ 删除的元素不存在,报错

4.4 clear() 清空

代码演示

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

int main() {
	//------------------  pop_back 删尾和 pop_front() 删头
	list<int> data1;
	data1.push_back(1);
	data1.push_back(2);
	data1.push_back(3);

	data1.pop_back(); // 删尾
	for (auto it = data1.begin(); it != data1.end(); ++it) {
		cout << *it << " "; // 1 2
	}

	data1.pop_front(); // 删头
	for (auto it = data1.begin(); it != data1.end(); ++it) {
		cout << *it << " "; // 2
	}
	

	//------------------ erase() 删除n个元素

	// ******* 1. erase(iterator it)
	list<int> data2;
	data2.push_back(1);
	data2.push_back(2);
	data2.push_back(3);
	data2.push_back(4);
	
	//==== 1.1 erase(data2.begin())
	auto itor1= data2.erase(data2.begin());
	cout <<"删除后的下一个元素为:"<< *itor1 << endl; // 2
	
	for (auto it = data2.begin(); it != data2.end(); ++it) {
		cout << *it << "  "; // 2  3  4
	}
	

	//==== 1.2 erase(--data2.end())
	
	/*原列表元素:2 3 4;
	data2.end() 表示指向4后面的位置,该位置不存在元素,因此:
	auto itor2 = data2.erase(--data2.end());  ✔删除的是4,剩下为 2  3 
	auto itor2 = data2.erase(data2.end()); ❌ 删除的元素不存在,报错 */
	
	auto itor2 = data2.erase(--data2.end());
	for (auto it = data2.begin(); it != data2.end(); ++it) {
		cout << *it << "  "; // 2  3 
	}
	


	// ******* 2. erase(iterator first,iterator last);删除当前列表[first,last)之间的元素
	list<int> data3;
	data3.push_back(1);
	data3.push_back(2);
	data3.push_back(3);
	data3.push_back(4);

	auto it3 = data3.erase(++data3.begin(), --data3.end());
	for (auto it = data3.begin(); it != data3.end(); ++it) {
		cout << *it << "  "; // 1  4 
	}


	//------------------ clear()  清空
	list<int> data4;
	data4.push_back(1);
	data4.push_back(2);
	data4.push_back(3);
	data4.push_back(4);

	data4.clear();
	for (auto it = data4.begin(); it != data4.end(); ++it) {
		cout << "data4="<< *it << "  "; //   (空)
	}


	return 0;
}

5、改

5.1 assign() 替换/赋值

  1. l1.assign(n,val); // 将当前列表中所有元素替换为n个T类型的val
  2. l1.assign(l2.begin(),l2.end()); // 将12列表中的从l2.begin()到l2.end()之间的数值赋值给当前列表l1

5.2 swap() 交换

交换两个链表(两个重载)语法:(都可能完成连个链表的交换)
(1) l1.swap(l2);
(2)swap(l1,l2);

5.3 reverse() 逆置

5.4 merge() 合并

合并两个链表并使之默认升序(也可改):
l1.merge(l2,greater());

  1. 调用结束后l2变为空,l1中元素包含原来l1 和 l2中的元素,并且排好序,升序。
  2. 其实默认是升序,greater()可以省略。
  3. 另外greater()是可以变的,也可以不按升序排列,例如:less()是降序排列。

代码演示

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

int main() {
	//------------------ 1. assign() 赋值/替换 
	// ***** 1.1 assign(n,val) 将列表中所有元素替换为n个T类型的val
	list<int> data1;
	data1.push_back(1);
	data1.push_back(2);
	data1.push_back(3);

	data1.assign(2, 9);
	for (auto it = data1.begin(); it != data1.end(); ++it) {
		cout << "data1="<< *it << " "; // data1=9 data1=9
	}
	
	// ***** 1.2 l1.assign(l2.begin(), l2.end());  将12列表中的从l2.begin()到l2.end()之间的数值赋值给当前列表l1
	list<int> data1_2;
	data1_2.push_back(1);
	data1_2.push_back(1);
	data1_2.push_back(1);

	list<int> data1_3;
	data1_3.push_back(2);
	data1_3.push_back(2);
	data1_3.push_back(2);

	data1_2.assign(++data1_3.begin(), data1_3.end());
	for (auto it = data1_2.begin(); it != data1_2.end(); ++it) {
		cout << "data1_2 = " << *it << " "; // data1_2 = 2 data1_2 = 2
	}


	//------------------ 2. swap() 交换
	// ***** 2.1  l1.swap(l2); 
	list<int> data2_1;
	data2_1.push_back(1);
	data2_1.push_back(1);
	data2_1.push_back(1);

	list<int> data2_2;
	data2_2.push_back(2);
	data2_2.push_back(2);
	data2_2.push_back(2);

	data2_1.swap(data2_2); // 交换

	for (auto it = data2_1.begin(); it != data2_1.end(); ++it) {
		cout << "data2_1 = " << *it << " "; // ata2_1 = 2 data2_1 = 2 data2_1 = 2
	}

	for (auto it = data2_2.begin(); it != data2_2.end(); ++it) {
		cout << "data2_2 = " << *it << " "; // data2_2 = 1 data2_2 = 1 data2_2 = 1
	}
	cout << endl;

	//***** 2.2  swap(l1,l2);
	swap(data2_1, data2_2);
	for (auto it = data2_1.begin(); it != data2_1.end(); ++it) {
		cout << "data2_1 = " << *it << " "; // data2_1 = 1 data2_1 = 1 data2_1 = 1
	}
	cout << endl;
	for (auto it = data2_2.begin(); it != data2_2.end(); ++it) {
		cout << "data2_2 = " << *it << " "; // data2_2 = 2 data2_2 = 2 data2_2 = 2
	}


	//------------------ 3. reverse() 逆置
	list<int> data3;
	data3.push_back(1);
	data3.push_back(2);
	data3.push_back(3);

	data3.reverse();
	for (auto it = data3.begin(); it != data3.end(); ++it) {
		cout <<  *it << " "; // 3 2 1
	}


	//------------------ 4. merge() 合并

	//**** 合并后降序排列

	//**** 合并后升序排列



	return 0;
}

6、查

6.1 front() 获取头部元素

  1. 通过front()可以获得list容器中的头部元素,通过back()可以获得list容器的最后一个元素。
  2. 但是有一点要注意,就是list中元素是空的时候,这时候调用front()和back()会发生什么呢?实际上会发生不能正常读取数据的情况,但是这并不报错,那我们编程序时就要注意了,个人觉得在使用之前最好先调用empty()函数判断list是否为空。

6.2 back() 获取尾部元素

6.3 遍历(不支持 [] 和“<<”)

int main() {
	//------------------1. front() 获取头部元素 和 back() 获取尾部元素
	list<char> data1 = {'a','b','c'};
	cout << data1.front()<<endl; // a
	cout<< data1.back() << endl; // c

	// -----------------2. 遍历
	//******* 法1:
	list<char>::iterator itor;
	for (itor = data1.begin(); itor != data1.end(); ++itor) {
		cout << *itor << " "; // a b c
	}

	//******* 法2:
	for (list<char>::iterator itor = data1.begin(); itor != data1.end(); ++itor) {
		cout << *itor << " "; // a b c
	}

	//******* 法3:
	for (auto it = data1.begin(); it != data1.end(); ++it) {
		cout << *it << " ";
	}

	return 0;
}

7、empty() 判空

8、resize() 修改list容器容量

  1. resize(n)将list的长度改为n;

(1)超出的元素将被删除;
(2)不足部分:

① 类型 默认补‘空格’
② 类型 默认补0

  1. resize(n,val),将list的长度改为n;
    (1)超出的元素将被删除;
    (2)不足部分:补val
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值