IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> STL--list容器(链表) -> 正文阅读

[数据结构与算法]STL--list容器(链表)

一、list基本概念

1. 功能:将数据进行链式存储

2. 链表

链表:

????????????????是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的

链表的组成:

????????链表是由一系列结点组成

结点的组成:

????????一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

3. 结构

STL中的链表是一个双向循环链表

由于链表的存储方式不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

?4. list优缺点:

list的优点:

  • 可以对任意位置进行快速插入或者删除
  • 采用动态存储分配,不会造成内存浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要大量移动数据

list的缺点:

  • 容器遍历速度没有数组快,占用空间比数组大
  • 链表灵活,但是空间(指针域)和时间(遍历)额外耗费比较大

5. 特别:

list容器的插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。

二、list构造函数

  • list<T>? lst;???????????????????????????? // list采用模板类实现,对象的默认构造方式
  • list(beg,? end);??????????????????????? // 构造函数讲(beg,end)区间内的元素拷贝给本身
  • list(n,? elem);????????????????????????? // 构造函数将n个elem拷贝给本身
  • list(const? list? &? lst);??????????? // 拷贝构造函数
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
//遍历
void print_List(list<int> &l)
{
	for(list<int>::iterator it = l.begin();it!=l.end();it++)
	{
		cout<<*it<<" ";
	}
	cout<<endl;
}
int main()
{
	list<int> l; // 默认构造

	// 添加数据
	l.push_back(10);
	l.push_back(20);
	l.push_back(30);
    l.push_back(40);
		l.push_back(50);
		// 遍历容器
	print_List(l);

	// 区间构造
	list<int>  L2(l.begin(),l.end());
	print_List(L2);

	// 拷贝构造
	list<int> L3(L2);
	print_List(L3);

	// n 个 elem 的方式
	list<int> L4(10,100);
	print_List(L4);
	return 0;
}

?三、list赋值和交换

  • assign(beg,? end);??????????????????????????? ? ? ? // 将(beg,end)区间内的数据拷贝赋值给本身
  • assign(n,? elem);?????????????????????????????????????? // 将n个elem拷贝赋值给本身
  • list? operator=(const? list? &? lst);??????????? // 重载等号操作符
  • swap(lst);???????????????????????????????????????????????? // 将lst与本身的元素互换
#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
//遍历
void print_List(list<int> &l)
{
	for(list<int>::iterator it = l.begin();it!=l.end();it++)
	{
		cout<<*it<<" ";
	}
	cout<<endl;
}
int main()
{
	list<int> L1;
	for(int i=0;i<10;i++)
	{
		L1.push_back(i);
	}
	print_List(L1);

	// 赋值
	list<int> L2;
	L2 = L1;  // operator= 进行赋值
	print_List(L2);

	// assign 区间赋值
	list<int> L3;
	L3.assign(L2.begin(),L2.end());
	print_List(L3);

    // assign n 个 elem 的方式
	list<int> L4;
	L4.assign(10,100);
	print_List(L4);


	// 交换
	cout<<"交换前L3 和 L4:"<<endl;
    print_List(L3);
	print_List(L4);
	cout<<"交换后L3 和 L4:"<<endl;
	L3.swap(L4);
	print_List(L3);
	print_List(L4);
	return 0;

}

?四、list大小操作

  • size();????????????????????????????????? // 返回容器中元素的个数
  • empty();???????????????????????????? // 判断容器是否为空
  • resize(num);?????????????????????? // 重新指定容器的长度为num,若容器变长,则以默认值0填充新的位置

????????????????????????????????????????? // 如果容器变短,则末尾超出容器长度的元素被删除

  • resize(num,? elem);??// 重新指定容器的长度为num,若容器变长,则以elem值填充新的位置

???????????????????????????????????????? // 如果容器变短,则末尾超出容器长度的元素被删除

	#include<iostream>
	#include<list>
	#include<algorithm>
	using namespace std;
	//遍历
	void print_List(list<int> &l)
	{
		for(list<int>::iterator it = l.begin();it!=l.end();it++)
		{
			cout<<*it<<" ";
		}
		cout<<endl;
	}
	int main()
	{
		list<int> L1;
		for(int i=0;i<10;i++)
		{
			L1.push_back(i);
		}
		print_List(L1);
	
		// 判断容器是否为空
		if(L1.empty())
		cout<<"L1 为空"<<endl;
		else
		cout<<"L1 不为空"<<endl;
	
	
		// 元素个数
		cout<<"L1 中元素的个数:"<<L1.size()<<endl;
	
		// 重新指定大小
		L1.resize(11); // 如果超出原本的大小,多出的部分默认由0 填充
		print_List(L1);
		L1.resize(15,99); // 重载版本,指定填充内容
		print_List(L1);
		L1.resize(6);
		print_List(L1); // 如果比原本的大小小,那么多出的部分被删除
		return 0;
	}

?五、list插入和删除

  • push_back(elem);???????????? // 在容器尾部加入一个元素
  • push_front(elem);??????????? // 在容器开头插入一个元素
  • pop_back();?????????????????????? // 删除容器中最后一个元素
  • pop_front();????????????????????? // 删除容器第一个元素

  • insert(pos,? elem);?????????????????? // 在pos位置插入elem元素的拷贝,返回新数据的位置
  • insert(pos,? n,? elem);????????????? // 在pos位置插入n个elem数据,无返回值
  • insert(pos,? beg,? end);??????????? // 在pos位置插入(beg,end)区间内的数据,无返回值

  • erase(beg,? end);????????????????????? // 删除(beg,end)区间内的数据,返回下一个数据的位置
  • erase(pos);?????????????????????????????? // 删除pos位置的数据,返回下一个数据的位置

  • remove(elem);??????????????????????? // 删除容器中所有与elem值匹配的元素

  • clear();?????????????????????????????????? // 移除容器中所有的数据
	#include<iostream>
	#include<list>
	#include<algorithm>
	using namespace std;
	//遍历
	void print_List(list<int> &l)
	{
		for(list<int>::iterator it = l.begin();it!=l.end();it++)
		{
			cout<<*it<<" ";
		}
		cout<<endl;
	}
	int main()
	{
		list<int> L1;
		for(int i=0;i<10;i++)
		{
			L1.push_back(i);
		}
		print_List(L1);
	
		// 头插
		L1.push_front(100);
		// 尾插
		L1.push_back(200);
		print_List(L1);
		/*
		头删
		L1.pop_front();
		尾删
		L1.pop_back();
		*/
	
		//insert 插入
		L1.insert(++L1.begin(),1000);  // 第一个参数是迭代器(位置),第二个参数是插入的内容
		print_List(L1); // 迭代器可以偏移
	
		// 删除
		L1.erase(L1.begin());  // 迭代器可以偏移
	    list<int>::iterator it = L1.begin(); // 设置it为迭代器
	    L1.erase(it);
		print_List(L1);
	
		// 移除
		L1.push_back(10000);
		print_List(L1);
		L1.remove(10000); // 移除list中所有的指定内容
		print_List(L1);
	
	    // 清空
	    L1.clear();
	    print_List(L1); // 清空所有的内容
		return 0;
	}

?六、list数据存取

list本质是链表,不是连续线性空间存储数据,迭代器也不支持随机访问

list不支持[]和at()访问

  • front();????????? // 返回第一个元素
  • back();?????????????? // 返回最后一个元素
	#include<iostream>
	#include<list>
	#include<algorithm>
	using namespace std;
	//遍历
	void print_List(list<int> &l)
	{
		for(list<int>::iterator it = l.begin();it!=l.end();it++)
		{
			cout<<*it<<" ";
		}
		cout<<endl;
	}
	int main()
	{
		list<int> L1;
		for(int i=0;i<10;i++)
		{
			L1.push_back(i);
		}
		print_List(L1);
	
	    // 访问第一个和最后一个元素
	    cout<<"第一个元素为:"<<L1.front()<<endl;
	    cout<<"最后一个元素为:"<<L1.back()<<endl;
	
		// 验证迭代器不能随机访问
		list<int>::iterator it = L1.begin();
		it++; // 只能++或者--不能+1
		return 0;
	}

?七、list反转和排序

  • reverse();??????????? // 反转链表
  • sort();?????????????????????? // 链表排序

	#include<iostream>
	using namespace std;
	#include<list>
	#include<algorithm>
	
	//遍历
	void print_List(list<int> &L)
	{
		for(list<int>::iterator it = L.begin();it!=L.end();it++)
		{
			cout<<*it<<" ";
		}
		cout<<endl;
	}
	
	// list容器的反转和排序
	void test01()
	{
		list<int> L1;
		for(int i=0;i<10;i++)
		{
			L1.push_back(i);
		}
		cout<<"反转前:"<<endl;
		print_List(L1);
	
		// 反转
		L1.reverse();
		cout<<"反转后:"<<endl;
		print_List(L1);
	}
	
	// 伪函数
	bool my_compare(int v1,int v2)
	{
		// 降序  --> 就让第一个数大于第二个数
		return v1 > v2;
	}
	
	void test02()
	{
		// 排序
		list<int> L2;
		L2.push_back(5);
		L2.push_back(78);
		L2.push_back(2);
		L2.push_back(98);
		L2.push_back(65);
		cout<<"排序前:"<<endl;
		print_List(L2);
		// sort(L2.begin(),L2.end()); // 所有不支持随机访问迭代器的容器,都不可以用标准算法
		// 不支持随机访问的迭代器的容器,内部会对应提供一些算法
		L2.sort(); // 默认升序
		cout<<"升序排序后:"<<endl;
		print_List(L2);
	
		L2.sort(my_compare); // 降序的操作
		cout<<"降序排列后:"<<endl;
	 	print_List(L2);
	}
	int main()
	{
		test01();
		test02();
		return 0;
	} 

八、附加一个排序案例

	#include<iostream>
	using namespace std;
	#include<list>
	#include<algorithm>
	
	class person
	{
	public:
		person(string name,int age,int height)
		{
			this->name=name;
			this->age=age;
			this->height=height;
		}
		string name;
		int age;
		int height;
	};
	
	void print_list(list<person>&L)
	{
		for(list<person>::iterator it=L.begin();it!=L.end();it++)
		{
			cout<<"姓名:"<<it->name<<"\t年龄:"<<it->age<<"\t身高:"<<it->height<<endl;
		}
	}
	
	bool compare_person(person &p1,person &p2)
	{
		// 按照身高降序
		if(p1.age==p2.age)
		return p1.height>p2.height;
		// 按年龄升序
		return p1.age<p2.age;
	}
	
	void test01()
	{
		list<person> L;
		person p1("刘备",35,175);
		person p2("曹操",45,180);
		person p3("孙权",40,170);
		person p4("赵云",25,190);
		person p5("张飞",35,189);
		person p6("关羽",35,200);
	
		L.push_back(p1);
		L.push_back(p2);
		L.push_back(p3);
		L.push_back(p4);
		L.push_back(p5);
		L.push_back(p6);
	
		// 排序前
		print_list(L);
	
		// 排序后
		cout<<"按年龄排序后:"<<endl;
		// 操作自定义类型的数据排序要指定排序的规则
		L.sort(compare_person);
		print_list(L);
	
		// 重新定义排序,在年龄相同的情况下,按照身高进行降序排列
		cout<<"多重条件后的排序:"<<endl;
		L.sort(compare_person);
		print_list(L);
	}
	int main()
	{
		test01();
		return 0;
	}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:48:39  更:2022-07-17 16:51:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:39:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码