list使用

目录

list介绍

list使用

list创建

list迭代器

容量操作

元素访问

修改元素

其他操作


list介绍

● list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代

● list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素

● list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高 效。

● 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率 更好。

● 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间 开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这 可能是一个重要的因素)

list使用

list创建

cpp 复制代码
list<int> lt1;		 // 无参构造
list<int> lt2(3, 2); // 3个2构造
vector<int> v(10, 2);
list<int> lt3(v.begin(), v.end()); // 迭代器区间构造
list<int> lt4(lt3);				   // 拷贝构造

list迭代器

正向普通迭代器

cpp 复制代码
#include <iostream>
#include <list>
int main()
{
	list<int> lt(5, 2); 
	list<int>::iterator it = lt.begin();
	while(it != lt.end())
	{
		cout << *it << " "; //2 2 2 2 2 
		it++;
	}
	cout << endl;
	return 0;
}

正向const迭代器

cpp 复制代码
#include <iostream>
#include <list>
int main()
{
	const list<int> lt(5, 2); 
	list<int>::const_iterator it = lt.begin();
	while(it != lt.end())
	{
		cout << *it << " "; //2 2 2 2 2 
		it++;
	}
	cout << endl;
	return 0;
}

反向普通迭代器

cpp 复制代码
#include <iostream>
#include <list>
int main()
{
	list<int> lt(5, 2); 
	list<int>::reverse_iterator it = lt.rbegin();
	while(it != lt.rend())
	{
		cout << *it << " "; //2 2 2 2 2 
		it++;
	}
	cout << endl;
	return 0;
}

反向const迭代器

cpp 复制代码
#include <iostream>
#include <list>
int main()
{
	const list<int> lt(5, 2); 
	list<int>::const_reverse_iterator it = lt.rbegin();
	while(it != lt.rend())
	{
		cout << *it << " "; //2 2 2 2 2 
		it++;
	}
	cout << endl;
	return 0;
}

容量操作

cpp 复制代码
#include <iostream>
#include <list>
int main()
{
	const list<int> lt(5, 2); 
	cout << lt.empty() << endl; //0
	cout << lt.size() << endl; //5
	return 0;
}

元素访问

cpp 复制代码
#include <iostream>
#include <list>
int main()
{
	const list<int> lt(5, 2); 
	cout << lt.front() << endl; //2
	cout << lt.back() << endl; //2
	return 0;
}

修改元素

cpp 复制代码
#include <iostream>
#include <list>
void print(list<int>& lt)
{
	for(auto& x : lt)
	{
		cout << x << " ";
	}
	cout << endl;
}
int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	list<int> lt(v.begin(), v.end());
	lt.push_front(0); 
	print(lt); //0 1 2 3 4
	lt.push_back(5);
	print(lt); //0 1 2 3 4 5
	lt.pop_front();
	print(lt); //1 2 3 4 5
	lt.pop_back();
	print(lt); //1 2 3 4
	lt.insert(++lt.begin(), 10);
	print(lt); //1 10 2 3 4
	lt.erase(--lt.end()); 
	print(lt); //1 10 2 3
	list<int> lt2;
	lt2.assign(lt.begin(), lt.end());
	print(lt2); //1 10 2 3
	lt.clear();
	cout << lt.size() << endl; // 0
	return 0; 
}

其他操作

逆置链表

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	print(lt); //1 2 3 4
	lt.reverse(); // 逆置链表
	print(lt); //4 3 2 1
}

排序链表

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(1);
	print(lt); //2 3 4 1
	lt.sort(); //默认是升序
	print(lt); //1 2 3 4
}

● 算法库algorithm中也提供了sort函数,但是我们无法直接使用sort函数去排序链表,因为sort函数要求传递的迭代器是随机访问迭代器,而list不支持随机访问迭代器,只有双向迭代器

● list中的sort函数提供了两个重载接口,无参的sort默认是升序,因此不传递任何参数排序的结果就是升序

● 而我们也可以传参,去调用有参的sort,就可以控制升序还是降序了,comp是类模版参数,可以传递类对象,比如less/greater,使用仿函数实现升序/降序

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(1);
	print(lt); //2 3 4 1
	less<int> ls;
	lt.sort(ls);
	print(lt); //1 2 3 4

	greater<int> gt;
	lt.sort(gt);
	print(lt); //4 3 2 1
}

unique

● unique接口可以将链表相邻重复元素去重,如果搭配sort使用,就可以实现将链表所有元素去重

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(4);
	lt.push_back(1);
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(5);
	lt.push_back(5);
	lt.push_back(1);
	lt.push_back(3);
	lt.sort();
	print(lt); //1 1 1 2 3 4 5 5
	lt.unique(); // 把相邻的重复去掉, 配合sort可以达到去重的功能
	print(lt); //1 2 3 4 5
	return 0;
}

remove

● remove接口可以将指定的某个元素从链表中全部删除

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(4);
	lt.push_back(1);
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(5);
	lt.push_back(5);
	lt.push_back(1);
	lt.push_back(3);
	print(lt); //4 1 1 2 5 5 1 3 
	lt.remove(1);
	print(lt); //4 2 5 5 3
	return 0;
}

remove if
remove if接口可以将满足条件的所有元素从链表中删除,因此remove if 的参数是类对象,可以传递函数对象,也可以传递仿函数对象

cpp 复制代码
bool cmp(const int& val)
{
	return val == 1;
}

class Cmp
{
public:
	bool operator()(const int& val)
	{
		return val == 5;
	}
};

int main()
{
	list<int> lt;
	lt.push_back(4);
	lt.push_back(1);
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(5);
	lt.push_back(5);
	lt.push_back(1);
	lt.push_back(3);
	print(lt); //4 1 1 2 5 5 1 3 
	lt.remove_if(cmp);
	print(lt); //4 2 5 5 3
	lt.remove_if(Cmp());
	print(lt); //4 2 3
	return 0;
}

merge

● lt1.merge(lt2),该操作会移除掉lt2的所有元素尾插到lt1链表的后面,完成两个链表的合并

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);
	list<int> lt2;
	lt1.push_back(8);
	lt1.push_back(7);
	lt1.push_back(6);
	lt1.push_back(5);
	lt1.merge(lt2);
	print(lt1); //1 2 3 4 8 7 6 5
	print(lt2); //空
	return 0;
}

splice

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);

	list<int> lt2;
	lt2.push_back(10);
	lt2.push_back(20);
	lt2.push_back(30);
	lt2.push_back(40);

	list<int>::iterator it = lt1.begin();
	++it;
	lt1.splice(it, lt2); // 将lt2嫁接到lt1第2个位置之后, lt2就为空了!

	print(lt1); //1 10 20 30 40 2 3 4
	print(lt2); //空
}
cpp 复制代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);
	list<int> lt2;
	lt2.push_back(10);
	lt2.push_back(20);
	lt2.push_back(30);
	lt2.push_back(40);
	lt1.splice(lt1.begin(), lt2, lt2.begin()); // 将lt2的第一个节点接到lt1开始位置
	print(lt1); // 10 1 2 3 4
	print(lt2);	// 20 30 40
}
cpp 复制代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);
	list<int> lt2;
	lt2.push_back(10);
	lt2.push_back(20);
	lt2.push_back(30);
	lt2.push_back(40);
	lt1.splice(lt1.begin(), lt2, lt2.begin(), lt2.end()); // 将lt2的全部接到lt1开始
	print(lt1); //10 20 30 40 1 2 3 4
	print(lt2); //空
}
相关推荐
7yewh1 小时前
LeetCode 力扣 热题 100道(二十一)接雨水(C++)
开发语言·数据结构·c++·算法·leetcode·安卓
界面开发小八哥1 小时前
QtitanChart组件——高效、灵活的Qt数据可视化解决方案
c++·qt·ui·信息可视化·界面控件
c++初学者ABC2 小时前
统计字符的个数C++
开发语言·数据结构·c++
醉颜凉2 小时前
【一本通】两个数的最小公倍数
c语言·数据结构·c++·算法
Quz2 小时前
QScreen在Qt5.15与Qt6.8版本下的区别
c++·qt·ui
就叫飞六吧2 小时前
Electron和C/C++开发桌面应用对比
c语言·开发语言·c++·visual studio
7yewh3 小时前
LeetCode 力扣 热题 100道(二十)三数之和(C++)
c语言·数据结构·c++·算法·leetcode
程序员涵哥4 小时前
wxWidgets使用wxStyledTextCtrl(Scintilla编辑器)的正确姿势
c++·编辑器·wxwidgets·scintilla·cutemysql
sweetheart7-74 小时前
LeetCode5. 最长回文子串(2024冬季每日一题 35)
c++·算法·leetcode·动态规划·力扣