C++ list【常用接口、模拟实现等】

news2024/11/25 16:38:18

1. list的介绍及使用

1.1 list的介绍

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

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

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

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

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

 

1.2 list的使用

1.2.1 list的构造

析构函数(constructor)

接口说明

list (size_type n, const value_type& val = value_type())构造的list中包含n个值为val的元素
list()构造空的list
list (const list& x)拷贝构造函数
list (InputIterator first, InputIterator last)用[first, last)区间中的元素构造list

(若为手机阅读,表格可左右移动)

1.2.2 list iterato的使用

此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。

函数声明

接口说明

begin+end返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器
rbegin+rend返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的reverse_iterator,即beign位置

 (若为手机阅读,表格可左右移动)

 【注意】

1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动

2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

1.2.3 list capacity

函数声明

接口说明

empty检测list是否为空,是返回true,否则返回false
size返回list中有效节点的个数

 (若为手机阅读,表格可左右移动)

1.2.4 list element access

函数声明

接口说明

front返回list的第一个节点中值的引用
back返回list的最后一个节点中值的引用

 (若为手机阅读,表格可左右移动)

1.2.5 list modifiers

函数声明

接口说明

push_front在list首元素前插入值为val的元素
pop_front删除list中的第一个元素
push_back在list尾部插入值为val的元素
pop_back删除list中最后一个元素
insert在list position位置中插入值为val的元素
erase删除list position位置的元素
swap交换两个list中的元素
clear清空list中的有效元素

(若为手机阅读,表格可左右移动)

1.2.6 list的迭代器失效

 前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

错误:

改正:

2. list的模拟实现

实现节点类

template<class T>
struct ListNode
{
	ListNode<T>* _next;
	ListNode<T>* _prev;
	T _data;


	ListNode(const T& data = T())
		:_next(nullptr)
		, _prev(nullptr)
		, _data(data)
	{


	}
};

实现正向迭代器 

迭代器不用实现析构函数和深拷贝。因为迭代器本身就是为了访问链表的节点,节点属于链表,不属于迭代器,如果需要析构和深拷贝,应该在控制链表的类中实现。

	template<class T, class Ref, class Ptr>
	struct ListIterator
	{
		typedef ListNode<T> Node;
		typedef ListIterator<T, Ref, Ptr> self;
		Node* _node;


		ListIterator(Node* node)
			:_node(node)
		{


		}


		self& operator++()
		{
			_node = _node->_next;


			return *this;
		}


		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;


			return tmp;
		}


		self& operator--()
		{
			_node = _node->_prev;


			return *this;
		}


		self operator--(int)
		{
			self tmp(*this);
			_node = _node->_prev;


			return tmp;
		}


		Ref operator*()
		{
			return _node->_data;
		}


		bool operator!=(const self& it)
		{
			return _node != it._node;
		}


		bool operator==(const self& it)
		{
			return _node == it._node;
		}


		Ptr operator->()
		{
			return &_node->_data;
		}
	};

 实现反向迭代器

template<class T, class Ref, class Ptr>
struct RListIterator
{
	typedef ListNode<T> Node;
	typedef RListIterator<T, Ref, Ptr> self;
	Node* _node;


	RListIterator(Node* node)
		:_node(node)
	{


	}


	self& operator++()
	{

		_node = _node->_prev;


		return *this;
	}


	self operator++(int)
	{
		self tmp(*this);
		_node = _node->_prev;


		return tmp;
	}


	self& operator--()
	{
		_node = _node->_next;


		return *this;
	}


	self operator--(int)
	{

		self tmp(*this);
		_node = _node->_next;


		return tmp;
	}


	Ref operator*()
	{
		return _node->_data;
	}


	bool operator!=(const self& it)
	{
		return _node != it._node;
	}


	bool operator==(const self& it)
	{
		return _node == it._node;
	}


	Ptr operator->()
	{
		return &_node->_data;
	}
};

实现控制list的类

template<class T>
class list
{
	typedef ListNode<T> Node;


public:
	typedef ListIterator<T, T&, T*> iterator;
	typedef RListIterator<T, T&, T*> reverse_iterator;
	typedef ListIterator<T, const T&, const T*> const_iterator;


	void empty_init()
	{
		_head = new Node();
		_head->_next = _head;
		_head->_prev = _head;
	}




	list()
	{
		empty_init();
	}



	list(const list<T>& it)
	{
		empty_init();
		for (const auto& e : it) 
		//在范围for上加上引用,如果it内的元素体积很大的话可以减小代价,引用并不会导致浅拷贝
		//eg:int a=1;int& a1=a;int b=a1;变量b只是和a的值一样并没有指向同一块空间(int b=a;)
		{
			push_back(e);
		}
	}


	list(initializer_list<T> il)
	{
		empty_init();
		for (const auto& e : il)
		{
			push_back(e);
		}
	}


	~list()
	{
		clear();
		delete _head;
		_head = nullptr;
	}


	void clear()
	{
		auto it = begin();
		while (it != end())
		{
			it = erase(it);
		}
	}


	list<T>& operator=(list<T> it)
	{
		std::swap(_head, it._head);


		return *this;
	}


	iterator begin()
	{
		return iterator(_head->_next);
	}


	const_iterator begin() const
	{
		return const_iterator(_head->_next);
	}


	iterator end()
	{
		return iterator(_head);
	}


	const_iterator end() const
	{
		return const_iterator(_head);
	}

	reverse_iterator rbegin()
	{
		return reverse_iterator(_head->_prev);
	}

	reverse_iterator rend()
	{
		return reverse_iterator(_head);
	}

	void push_back(const T& x)
	{
		//Node* newnode = new Node(x);
		//Node* tail = _head->_prev;


		//tail->_next = newnode;
		//newnode->_prev = tail;
		//newnode->_next = _head;
		//_head->_prev = newnode;
		insert(end(), x);


	}


	void pop_back()
	{
		erase(--end());
	}


	void push_front(const T& x)
	{
		insert(begin(), x);
	}


	void pop_front()
	{
		erase(begin());
	}


	iterator insert(iterator pos, const T& x)
	{
		Node* cur = pos._node;
		Node* newnode = new Node(x);
		Node* prev = cur->_prev;


		prev->_next = newnode;
		newnode->_prev = prev;
		newnode->_next = cur;
		cur->_prev = newnode;


		return iterator(newnode);
	}


	iterator erase(iterator pos)
	{
		assert(pos != end());


		Node* cur = pos._node;
		Node* prev = cur->_prev;
		Node* next = cur->_next;


		prev->_next = next;
		next->_prev = prev;


		delete cur;


		return iterator(next);
	}


private:
	Node* _head;
};

 完整list.h

#pragma once
#include <assert.h>
namespace wmm
{
	template<class T>
	struct ListNode
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;
		T _data;


		ListNode(const T& data = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _data(data)
		{


		}
	};

	template<class T, class Ref, class Ptr>
	struct RListIterator
	{
		typedef ListNode<T> Node;
		typedef RListIterator<T, Ref, Ptr> self;
		Node* _node;


		RListIterator(Node* node)
			:_node(node)
		{


		}


		self& operator++()
		{

			_node = _node->_prev;


			return *this;
		}


		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_prev;


			return tmp;
		}


		self& operator--()
		{
			_node = _node->_next;


			return *this;
		}


		self operator--(int)
		{

			self tmp(*this);
			_node = _node->_next;


			return tmp;
		}


		Ref operator*()
		{
			return _node->_data;
		}


		bool operator!=(const self& it)
		{
			return _node != it._node;
		}


		bool operator==(const self& it)
		{
			return _node == it._node;
		}


		Ptr operator->()
		{
			return &_node->_data;
		}
	};

	template<class T, class Ref, class Ptr>
	struct ListIterator
	{
		typedef ListNode<T> Node;
		typedef ListIterator<T, Ref, Ptr> self;
		Node* _node;


		ListIterator(Node* node)
			:_node(node)
		{


		}


		self& operator++()
		{
			_node = _node->_next;


			return *this;
		}


		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;


			return tmp;
		}


		self& operator--()
		{
			_node = _node->_prev;


			return *this;
		}


		self operator--(int)
		{
			self tmp(*this);
			_node = _node->_prev;


			return tmp;
		}


		Ref operator*()
		{
			return _node->_data;
		}


		bool operator!=(const self& it)
		{
			return _node != it._node;
		}


		bool operator==(const self& it)
		{
			return _node == it._node;
		}


		Ptr operator->()
		{
			return &_node->_data;
		}
	};


	template<class T>
	class list
	{
		typedef ListNode<T> Node;


	public:
		typedef ListIterator<T, T&, T*> iterator;
		typedef RListIterator<T, T&, T*> reverse_iterator;
		typedef ListIterator<T, const T&, const T*> const_iterator;


		void empty_init()
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
		}




		list()
		{
			empty_init();
		}



		list(const list<T>& it)
		{
			empty_init();
			for (const auto& e : it) 
			//在范围for上加上引用,如果it内的元素体积很大的话可以减小代价,引用并不会导致浅拷贝
			//eg:int a=1;int& a1=a;int b=a1;变量b只是和a的值一样并没有指向同一块空间(int b=a;)
			{
				push_back(e);
			}
		}


		list(initializer_list<T> il)
		{
			empty_init();
			for (const auto& e : il)
			{
				push_back(e);
			}
		}


		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}


		void clear()
		{
			auto it = begin();
			while (it != end())
			{
				it = erase(it);
			}
		}


		list<T>& operator=(list<T> it)
		{
			std::swap(_head, it._head);


			return *this;
		}


		iterator begin()
		{
			return iterator(_head->_next);
		}


		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}


		iterator end()
		{
			return iterator(_head);
		}


		const_iterator end() const
		{
			return const_iterator(_head);
		}

		reverse_iterator rbegin()
		{
			return reverse_iterator(_head->_prev);
		}

		reverse_iterator rend()
		{
			return reverse_iterator(_head);
		}

		void push_back(const T& x)
		{
			//Node* newnode = new Node(x);
			//Node* tail = _head->_prev;


			//tail->_next = newnode;
			//newnode->_prev = tail;
			//newnode->_next = _head;
			//_head->_prev = newnode;
			insert(end(), x);


		}


		void pop_back()
		{
			erase(--end());
		}


		void push_front(const T& x)
		{
			insert(begin(), x);
		}


		void pop_front()
		{
			erase(begin());
		}


		iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(x);
			Node* prev = cur->_prev;


			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;


			return iterator(newnode);
		}


		iterator erase(iterator pos)
		{
			assert(pos != end());


			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;


			prev->_next = next;
			next->_prev = prev;


			delete cur;


			return iterator(next);
		}


	private:
		Node* _head;
	};


	//遍历测试
	void test()
	{
		list<int> l;
		l.push_back(1);
		l.push_back(2);
		l.push_back(3);
		l.push_back(4);


		list<int>::iterator it = l.begin();
		while (it != l.end())
		{
			cout << *it << endl;
			++it;
		}
	}


	//结构体数据,重载符号->测试
	struct pos
	{
		int _x;
		int _y;


		pos(int x = 0, int y = 0)
			:_x(x)
			, _y(y)
		{


		}
	};


	void test2()
	{
		list<pos> l;
		struct pos* a = (struct pos*)malloc(sizeof(struct pos));
		a->_x = 200;
		a->_y = 200;


		struct pos b;
		b._x = 300;
		b._y = 300;


		l.push_back(pos(100, 100));
		l.push_back(*a);
		l.push_back(b);


		list<pos>::iterator it = l.begin();
		while (it != l.end())
		{
			cout << (*it)._x << endl;
			cout << (*it)._y << endl;


			cout << it._node->_data._x << endl;
			cout << it._node->_data._y << endl;


			cout << it->_x << endl;
			cout << it->_y << endl;
			//想让迭代器it像结构体指针一样访问数据,重载了一个->符号


			++it;
		}
	}


	//erase insert 测试
	void test3()
	{
		list<int> l;
		l.push_back(1);
		l.push_back(2);
		l.push_back(3);
		l.push_back(4);


		list<int>::iterator it = l.begin();
		it=l.erase(it);//注意迭代器失效问题
		for (auto e : l)
		{
			cout << e << endl;
		}
		cout << endl;


		//it=l.begin();


		l.insert(it, 1);
		for (auto& e : l)
		{
			cout << e << endl;
			e = 3;
		}

	}


	//拷贝构造测试
	void test4()
	{
		list<int> l;
		l.push_back(1);
		l.push_back(2);
		l.push_back(3);
		l.push_back(4);


		for (auto e : l)
		{
			cout << e << endl;
		}
		cout << endl;


		list<int> l1(l);
		for (auto e : l1)
		{
			cout << e << endl;
		}
		cout << endl;


		list<int>::iterator it = l1.begin();
		*it = 0;


		for (auto e : l)
		{
			cout << e << endl;
		}
		cout << endl;


		for (auto e : l1)
		{
			cout << e << endl;
		}
		cout << endl;
	}


	//operator=测试
	void test5()
	{
		list<int> l({ 1,2,3,4,5 });
		list<int> l1 = { 1,2,3,4,6 };


		l1 = l;


		for (const auto& e : l)
		{
			cout << e << endl;
		}
		cout << endl;


		for (const auto& e : l1)
		{
			cout << e << endl;
		}
		cout << endl;


		list<int>::iterator it = l1.begin();
		*it = 0;


		for (const auto& e : l)
		{
			cout << e << endl;
		}
		cout << endl;


		for (const auto& e : l1)
		{
			cout << e << endl;
		}
		cout << endl;
	}

    //反向迭代器测试
	void test6()
	{
		list<int> l({ 1,2,3,4,5 });
		list<int>::iterator it = l.begin();
		while (it != l.end())
		{
			cout << *it << endl;
			++it;
		}

		list<int> l2({ 1,2,3,4,5 });
		list<int>::reverse_iterator it1 = l2.rbegin();
		while (it1 != l2.rend())
		{
			cout << *it1 << endl;
			++it1;
		}
	}
}

3. list与vector的对比

vector与list都是STL中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及应用场景不 同,其主要不同如下:

 下次再见~~很高兴帮助到你~~

如果有问题欢迎指正批评~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2035817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MyBatisPlus 第二天

常用注解 1 TableName:数据库表名和实体类名不同时,会出现以下报错 在实体类上添加 TableName("t_user") 在开发的过程中&#xff0c;我们经常遇到以上的问题&#xff0c;即实体类所对应的表都有固定的前缀&#xff0c;例如t_或tbl_此时&#xff0c;可以使用MyBa…

el-tree自定义节点内容

<el-tree :data"data" :props"defaultProps" ref"treeRef" show-checkbox check-change"handleCheckChange"><!-- 自定义节点内容 --><template #default"{ node, data, store }"><span class"tr…

无人值守人工智能智慧系统数据分析:深度洞察与未来展望

无人值守人工智能智慧系统数据分析&#xff1a;深度洞察与未来展望 随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已逐渐渗透到社会经济的各个领域&#xff0c;其中无人值守人工智能智慧系统作为AI技术应用的前沿阵地&#xff0c;正引领着一场深刻的…

【数量关系】毛娃儿笔记

一、导学 1、比例的常见作用 &#xff08;1&#xff09;通过份数求数量 甲&#xff1a;乙1:2 那么甲乙的人数总和一定是3的倍数 &#xff08;2&#xff09;得到倍数关系 不同的说法都可以转化为比例&#xff0c;比如甲是乙的两倍2:1、甲是乙的4/34:3、甲比乙多25%5:4 &am…

基于vue框架的4S店汽车维修保养管理系统28a7y(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;客户,技师,车辆信息,财务,客户维修,维修分配,维修订单,保养预约,保养分配,保养订单,维修费用,保养费用 开题报告内容 基于Vue框架的4S店汽车维修保养管理系统 开题报告 一、项目背景与意义 随着汽车产业的迅猛发展&#xff0c;4S店作…

【微前端中常见的问题及其解决办法】

随着前端技术的飞速发展&#xff0c;大型应用系统的复杂性和规模性日益增加&#xff0c;传统的单体前端架构逐渐暴露出维护成本高、升级困难、技术栈单一等问题。为了应对这些挑战&#xff0c;微前端&#xff08;Micro-Frontends&#xff09;作为一种新的架构模式应运而生。微前…

自研Vue3低代码海报制作平台第一步:基础拖拽组件开发

学习来源&#xff1a;稀土掘金 - 幽月之格大佬的技术专栏可拖拽、缩放、旋转组件 - 著作&#xff1a;可拖拽、缩放、旋转组件实现细节 非常感谢大佬&#xff01;受益匪浅&#xff01; 前面我们学习了很多vue3的知识&#xff0c;是时候把它们用起来做一个有意思的平台&#xf…

合合信息OCR支持30类国内常见票据一站式分类识别,支持医疗发票、数电票识别

合合信息TextIn平台明星产品——国内通用票据识别&#xff0c;重磅更新&#xff01; 产品支持票据类型扩展到23大类、30小类&#xff0c;覆盖场景更全面&#xff0c;同时升级优化了多款票据识别模型&#xff0c;平均识别率较前版本提升11.5%&#xff0c;整体识别速度提升21.9%…

关于k8s的Pod控制器

目录 1.Pod控制器及其作用 2.pod控制器类型 2.1 ReplicaSet: 2.2 Deployment 2.3 DaemonSet 2.4 StatefulSet 2.5 Job 2.6 Cronjob 3.Pod与控制器之间的关系 3.1 Deployment 3.2 SatefulSet 3.3 DaemonSet 3.4 job 3.5 cronjob 1.Pod控制器及其作用 Pod控制器&am…

北京某银行成功替换F5!更多实施细节曝光→

随着国家对金融行业技术创新的持续关注&#xff0c;金融行业的诸多用户正积极开展业务系统的数字化创新。 在这一领域&#xff0c;保障业务稳定性和连续性始终是最重要的议题。今天&#xff0c;为大家介绍的最佳实践来自北京某银行&#xff0c;他们通过积极探索和评估&#xf…

Python酷库之旅-第三方库Pandas(078)

目录 一、用法精讲 321、pandas.Series.str.len方法 321-1、语法 321-2、参数 321-3、功能 321-4、返回值 321-5、说明 321-6、用法 321-6-1、数据准备 321-6-2、代码示例 321-6-3、结果输出 322、pandas.Series.str.ljust方法 322-1、语法 322-2、参数 322-3、…

HMAC算法:构建安全认证的基石

在信息安全领域&#xff0c;数据完整性和认证是至关重要的。HMAC&#xff08;Hash-based Message Authentication Code&#xff09;算法作为一种基于哈希的消息认证码&#xff0c;广泛应用于数据传输过程中的安全认证。本文将带你了解HMAC算法的原理、特点及其应用场景。 HMAC算…

全方位解析RAG技术:从概念理论到代码实操,一文助你掌握检索增强生成的精髓!

一、LLMs 已经具备了较强能力了&#xff0c;为什么还需要 RAG(检索增强生成)? 尽管 LLM 已展现出显著的能力&#xff0c;但以下几个挑战依然值得关注&#xff1a; 幻觉问题&#xff1a;LLM 采用基于统计的概率方法逐词生成文本&#xff0c;这一机制内在地导致其可能出现看似…

Git基础使用教程

版本控制手册 本文中出现的 [ ] 为根据需求自行修改的变量。 基本命令 git init&#xff1a;将当前目录配置成git仓库&#xff0c;信息记录在隐藏的.git文件夹中。 git config --global user.name [xxx]&#xff1a;设置全局用户名&#xff0c;信息记录在~/.gitconfig文件中。…

厦门商家微信小程序、抖音、支付宝小程序同步上线

想要迅速在厦门开设微信小程序店铺&#xff1f;乔拓云网站提供了简便快捷的解决方案。只需四步&#xff0c;轻松复制模板&#xff0c;定制内容&#xff0c;即可上线专属小程序。 首先&#xff0c;访问乔拓云官网&#xff0c;完成免费注册&#xff0c;轻松获得您的专属账号。不论…

winform程序集的名称

1.更改程序集名称后 AssemblyInfo.cs中也要手动更改 2.鼠标放在程序集上右键&#xff0c;点击最后一栏 “属性” 3.更改Settings.Designer.cs中的名称 4.可能还有别的地方需要改&#xff0c;可以搜索旧名称来找到需要更改的地方进行更新。 PS: 当更改程序集名称时&#xff0c;…

图算法系列1: 图算法的分类有哪些?(上)

大约在公元9世纪上半叶&#xff0c;来自中亚古国花剌子模的波斯数学家花剌子米(al-Khwarizmi)先后出版了两本对数学界有深远影响的书籍《印度数字算术》与《代数学》​&#xff0c;前者在12世纪被翻译为拉丁文传入欧洲&#xff0c;十进制也因此传入欧洲&#xff0c;最终所形成的…

DLL文件损坏怎么办?10种DLL修复方法帮你搞定

在日常使用Windows电脑时&#xff0c;我们常常遇到应用程序无法打开、系统崩溃甚至蓝屏的问题&#xff0c;背后原因往往是DLL文件的损坏或丢失。DLL文件是系统和软件运行的关键部分&#xff0c;一旦出现问题&#xff0c;会严重影响我们的日常操作。为了避免这些困扰&#xff0c…

字符串 - 反转字符串

344. 反转字符串 方法一&#xff1a;双指针 /*** param {character[]} s* return {void} Do not return anything, modify s in-place instead.*/ var reverseString function(s) {let l -1, r s.length;while(l < --r) [s[l], s[r]] [s[r], s[l]]; };

车身域测试学习、CANoe工具实操学习、UDS诊断测试、功能安全测试、DTC故障注入测试、DBC数据库、CDD数据库、CAN一致性测试、ECU刷写测试

每日直播时间&#xff1a;&#xff08;直播方式&#xff1a;腾讯会议&#xff09;周一到周五&#xff1a;20&#xff1a;00-23&#xff1a;00周六与周日&#xff1a;9&#xff1a;00-17&#xff1a;00 进腾讯会议学习的&#xff0c;可以关注我并后台留言 直播内容&#xff1a;&…