C++初阶:8.list

news2024/11/23 22:50:41

list

一.list的介绍及使用

1. list的介绍

list的文档介绍

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
  3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
  4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
  5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

image-20240513112940012

2. list的使用

list中的接口比较多,此处类似,只需要掌握如何正确的使用,然后再去深入研究背后的原理,已达到可扩展的能力。以下为list中一些常见的重要接口

(1).list的构造

image-20240513113037693

list的构造使用代码演示

(2). list iterator的使用

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

image-20240513113200102

image-20240513113209240

【注意】

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

list的迭代器使用代码演示

(3).list capacity

image-20240513113521097

(4). list element access

image-20240513113548236

(5).list modifiers

image-20240513113629450

  • 补充:

    list的resize就是一个尾插, 尾删.

    eda2cb7660fede1d09d174a32344c8f

list的插入和删除使用代码演示
list中还有一些操作,需要用到时大家可参阅list的文档说明。

(6). list的迭代器失效

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

void TestListIterator1()
{
	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	list<int> l(array, array + sizeof(array) / sizeof(array[0]));
	auto it = l.begin();
	while (it != l.end())
	{
		// erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给
		其赋值
			l.erase(it);
		++it;
	}
}

// 改正
void TestListIterator()
{
	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	list<int> l(array, array + sizeof(array) / sizeof(array[0]));
	auto it = l.begin();
	while (it != l.end())
	{
		l.erase(it++); // it = l.erase(it);
	}
}

二.list的模拟实现

1. 模拟实现list

要模拟实现list,必须要熟悉list的底层结构以及其接口的含义,通过上面的学习,这些内容已基本掌握,现在我们来模拟实现list。

#pragma once
#include<iostream>
#include<assert.h>
#include<algorithm>

using std::cout;
using std::endl;


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

		ListNode(const T& x=T())
			:_next(nullptr)
			,_prev(nullptr)
			,_data(x)
		{}
	};

	//法二:增加两个模板参数(编译器实例化生成了两个类)
	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)
		{}
		
		// *it
		//T& operator*()
		Ref operator*()
		{
			return _node->_data;
		}

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

		// ++it
		Self& operator ++()
		{
			_node = _node->_next;
			return *this;
		}

		// it++
		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;
		}

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

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

	//法一:写两个类
	//template<class T>
	//struct ListConstIterator
	//{
	//	typedef ListNode<T> Node;
	//	typedef ListConstIterator<T> Self;

	//	Node* _node;

	//	ListConstIterator(Node* node)
	//		:_node(node)
	//	{}

	//	// *it
	//	const T& operator*()
	//	{
	//		return _node->_data;
	//	}

	//	const T* operator->()
	//	{
	//		return &(_node->_data);
	//	}

	//	// ++it
	//	Self& operator ++()
	//	{
	//		_node = _node->_next;
	//		return *this;
	//	}

	//	// it++
	//	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;
	//	}

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

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

	template<class T>
	class list
	{
		typedef ListNode<T> Node;
	public:
		//法一的typedef
		//typedef ListIterator<T> iterator;
		//typedef ListConstIterator<T> const_iterator;
		
		//法二的typedef
		typedef ListIterator<T,T&,T*> iterator;
		typedef ListIterator<T,const T&,const T*> const_iterator;

		iterator begin()
		{
			return iterator(_head->_next);
			//可以直接写return _head->_next;
			//单参数构造函数可以隐式类型转换
		}

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

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

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

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

			_size = 0;
		}

		list()
		{
			empty_init();
		}

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

		void swap(list<T>& lt)
		{
			std::swap(_head, lt._head);
			std::swap(_size, lt._size);
		}

		list<T>& operator=(list<T> lt)
		{
			swap(lt);
			return *this;
		}

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

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

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

			tail->_next = newnode;
			newnode->_prev = tail;
			newnode->_next = _head;
			_head->_prev = newnode;
		}*/
		void push_back(const T& x)
		{
			insert(end(), x);
		}

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

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

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

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

			//prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			_size++;
		}

		iterator erase(iterator pos)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			prev->_next = next;
			next->_prev = prev;
			delete cur;
			_size--;
			return iterator(next);
		}

		size_t size()const
		{
			return _size;
		}

		bool empty()const
		{
			return _size==0;
		}

	private:
		Node* _head;
		size_t _size=0;
	};
}

2. list与vector的对比

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

image-20240513121715557

image-20240513121726641

list

一.list的介绍及使用

1. list的介绍

list的文档介绍

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
  3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
  4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
  5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

image-20240513112940012

2. list的使用

list中的接口比较多,此处类似,只需要掌握如何正确的使用,然后再去深入研究背后的原理,已达到可扩展的能力。以下为list中一些常见的重要接口

(1).list的构造

image-20240513113037693

list的构造使用代码演示

(2). list iterator的使用

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

image-20240513113200102

image-20240513113209240

【注意】

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

list的迭代器使用代码演示

(3).list capacity

image-20240513113521097

(4). list element access

image-20240513113548236

(5).list modifiers

image-20240513113629450

  • 补充:

    list的resize就是一个尾插, 尾删.

    eda2cb7660fede1d09d174a32344c8f

list的插入和删除使用代码演示
list中还有一些操作,需要用到时大家可参阅list的文档说明。

(6). list的迭代器失效

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

void TestListIterator1()
{
	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	list<int> l(array, array + sizeof(array) / sizeof(array[0]));
	auto it = l.begin();
	while (it != l.end())
	{
		// erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给
		其赋值
			l.erase(it);
		++it;
	}
}

// 改正
void TestListIterator()
{
	int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	list<int> l(array, array + sizeof(array) / sizeof(array[0]));
	auto it = l.begin();
	while (it != l.end())
	{
		l.erase(it++); // it = l.erase(it);
	}
}

二.list的模拟实现

1. 模拟实现list

要模拟实现list,必须要熟悉list的底层结构以及其接口的含义,通过上面的学习,这些内容已基本掌握,现在我们来模拟实现list。

#pragma once
#include<iostream>
#include<assert.h>
#include<algorithm>

using std::cout;
using std::endl;


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

		ListNode(const T& x=T())
			:_next(nullptr)
			,_prev(nullptr)
			,_data(x)
		{}
	};

	//法二:增加两个模板参数(编译器实例化生成了两个类)
	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)
		{}
		
		// *it
		//T& operator*()
		Ref operator*()
		{
			return _node->_data;
		}

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

		// ++it
		Self& operator ++()
		{
			_node = _node->_next;
			return *this;
		}

		// it++
		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;
		}

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

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

	//法一:写两个类
	//template<class T>
	//struct ListConstIterator
	//{
	//	typedef ListNode<T> Node;
	//	typedef ListConstIterator<T> Self;

	//	Node* _node;

	//	ListConstIterator(Node* node)
	//		:_node(node)
	//	{}

	//	// *it
	//	const T& operator*()
	//	{
	//		return _node->_data;
	//	}

	//	const T* operator->()
	//	{
	//		return &(_node->_data);
	//	}

	//	// ++it
	//	Self& operator ++()
	//	{
	//		_node = _node->_next;
	//		return *this;
	//	}

	//	// it++
	//	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;
	//	}

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

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

	template<class T>
	class list
	{
		typedef ListNode<T> Node;
	public:
		//法一的typedef
		//typedef ListIterator<T> iterator;
		//typedef ListConstIterator<T> const_iterator;
		
		//法二的typedef
		typedef ListIterator<T,T&,T*> iterator;
		typedef ListIterator<T,const T&,const T*> const_iterator;

		iterator begin()
		{
			return iterator(_head->_next);
			//可以直接写return _head->_next;
			//单参数构造函数可以隐式类型转换
		}

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

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

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

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

			_size = 0;
		}

		list()
		{
			empty_init();
		}

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

		void swap(list<T>& lt)
		{
			std::swap(_head, lt._head);
			std::swap(_size, lt._size);
		}

		list<T>& operator=(list<T> lt)
		{
			swap(lt);
			return *this;
		}

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

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

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

			tail->_next = newnode;
			newnode->_prev = tail;
			newnode->_next = _head;
			_head->_prev = newnode;
		}*/
		void push_back(const T& x)
		{
			insert(end(), x);
		}

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

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

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

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

			//prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			_size++;
		}

		iterator erase(iterator pos)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

			prev->_next = next;
			next->_prev = prev;
			delete cur;
			_size--;
			return iterator(next);
		}

		size_t size()const
		{
			return _size;
		}

		bool empty()const
		{
			return _size==0;
		}

	private:
		Node* _head;
		size_t _size=0;
	};
}

2. list与vector的对比

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

image-20240513121715557

image-20240513121726641

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

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

相关文章

AXI Interconnect IP核的连接模式简介

AXI Interconnect IP核内部包含一个 Crossbar IP核&#xff0c;用于在 Slave Interfaces&#xff08;SI&#xff09;和 Master Interfaces&#xff08;MI&#xff09;之间路由传输。在连接 SI 或 MI 到 Crossbar 的每条路径上&#xff0c;可以选择性地添加一系列 AXI Infrastru…

3389端口报SSL_TLS协议信息泄露漏洞(CVE-2016-2183)【原理扫描】漏洞

1、win+R运行,输入gpedit.msc进入本地计算机策略 2、本地计算机组策略——>计算机配置——>管理模板——>网络——>ssl配置设置 3、打开ssl密码套件顺序 4、点击已开启,把密码套件替换为下一步中的套件内容。 套件内容 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_…

韵搜坊(全栈开发)-- 项目介绍

文章目录 项目介绍技术栈前端后端 业务流程 后端地址&#xff1a; https://github.com/IMZHEYA/zhesou-backend 前端地址&#xff1a; https://github.com/IMZHEYA/zhesou-frontend 图标设计&#xff08;AI生成&#xff09;&#xff1a; 项目介绍 一个聚合搜素平台&#xff…

火山引擎A/B测试平台的实验管理重构与DDD实践

本次分享的主题是火山引擎数智平台VeDI旗下的A/B测试平台 DataTester 实验管理架构升级与DDD实践。这里说明的一点是&#xff0c;代码的第一目标肯定是满足产品需求&#xff0c;能够满足产品需求的代码都是好代码。而本文中对代码的好坏的评价完全是从架构的视角&#xff0c;结…

机器人增量学习研究综述

源自&#xff1a;控制与决策 作者&#xff1a;马旭淼 徐德 “人工智能技术与咨询” 发布 摘 要 机器人的应用场景正在不断更新换代,数据量也在日益增长.传统的机器学习方法难以适应动态的环境,而增量学习技术能够模拟人类的学习过程,使机器人能利用旧知识来加快新任务的…

维护祖传项目Tomcat部署war包

文章目录 1. 安装tomcat2. 解决Tomcat启动日志乱码3. idea配置启动war包 1. 安装tomcat 选择免安装版本&#xff0c;只需要在系统变量里面配置一下。 新增系统变量 CATALINA_HOME D:\Users\common\tomcat\apache-tomcat-8.5.97-windows-x64\apache-tomcat-8.5.97 编辑追加Path…

ROS2入门21讲__第03讲__ROS2安装方法

目录 前言 Linux系统简介 Ubuntu系统简介 Ubuntu虚拟机安装 1. 下载系统镜像 2. 在虚拟机中创建系统 3. 设置虚拟机硬盘大小 4. 设置Ubuntu镜像路径 5. 启动虚拟机 6. 设置用户名和密码 7. 等待系统安装 8. 完成安装 ROS2系统安装 1. 设置编码 2. 添加源 3. 安装…

利用香港多IP服务器进行大数据分析的潜在优势?

利用香港多IP服务器进行大数据分析的潜在优势? 在当今数据驱动的时代&#xff0c;大数据分析已经成为企业获取竞争优势的不二选择。而香港作为一个拥有世界级通信基础设施的城市&#xff0c;提供了理想的环境来部署多IP服务器&#xff0c;从而为大数据分析提供了独特的优势。…

文档解析与向量化技术加速多模态大模型训练与应用

前言 随着人工智能技术的不断发展&#xff0c;多模态大模型作为一种新型的机器学习技术&#xff0c;逐渐成为人工智能领域的热点话题。多模态大模型能够处理多种媒体数据&#xff0c;如文本、图像、音频和视频等&#xff0c;并通过学习不同模态之间的关联&#xff0c;实现更加…

Mac安装jadx

1、使用命令brew安装 : brew install jadx 输入完命令,等待安装完毕 备注&#xff08;关于Homebrew &#xff09;&#xff1a; Homebrew 是 MacOS 下的包管理工具&#xff0c;类似 apt-get/apt 之于 Linux&#xff0c;yum 之于 CentOS。如果一款软件发布时支持了 homebrew 安…

[Linux][网络][协议技术][DNS][ICMP][ping][traceroute][NAT]详细讲解

目录 1.DNS1.DNS背景2.域名简介 2.ICMP协议1.ICMP功能2.ICMP两类报文 3.ping命令4.traceroute5.NAT技术1.NAT技术背景2.NAT IP转换过程3.静态地址NAT && 动态地址NAT4.网络地址端口转换NAPT5.NAT技术的缺陷6.NAT和代理服务器 6.总结1.数据链路层2.网络层3.传输层4.应用…

如何给远程服务器配置代理

目录 前言 正文 更换镜像源 开始之前 安装过程 遇到的问题 尾声 &#x1f52d; Hi,I’m Pleasure1234&#x1f331; I’m currently learning Vue.js,SpringBoot,Computer Security and so on.&#x1f46f; I’m studying in University of Nottingham Ningbo China&#x1f4…

使用Git管理github的代码库-上

1、下载安装Git https://download.csdn.net/download/notfindjob/11451730?spm1001.2014.3001.5503 2、注册一个github的账号&#xff08;已经注册的&#xff0c;可略过这一步&#xff09; 3、打开git命令行&#xff0c;配置github账号 git config --global user.name &quo…

CCleaner系统优化与隐私保护工具,中文绿色便携版 v6.23.11010

01 软件介绍 CCleaner 是一款高级的系统优化工具&#xff0c;其设计宗旨在于彻底清理 Windows 操作系统中积累的无用文件和冗余的注册表项。此举旨在显著提升计算机的运行效率并回收磁盘空间。该软件拥有高效的能力&#xff0c;可以清除包括临时文件、浏览器缓存及其历史记录在…

Java入门——继承和多态(中)

组合 和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果. public class Student { ... } public class Teacher { ... } public class School { public Student[] students; public Teacher[] teachers; } 组合并没有涉及到特殊的语法(诸如 ex…

如何通过香港站群服务器高效实现网站内容的快速更新?

如何通过香港站群服务器高效实现网站内容的快速更新? 在当今激烈的数字市场竞争中&#xff0c;网站内容的快速更新对于吸引用户和保持竞争优势至关重要。而利用香港站群服务器实现这一目标&#xff0c;则具备诸多优势。下面将详细探讨如何通过香港站群服务器高效实现网站内容…

【CSP CCF记录】数组推导

题目 过程 思路 每次输入一个Bi即可确定一个Ai值&#xff0c;用temp记录1~B[i-1]&#xff0c;的最大值分为两种情况&#xff1a; 当temp不等于Bi时&#xff0c;则说明Bi值之前未出现过&#xff0c;Ai必须等于Bi才能满足Bi是Ai前缀最大的定义。当temp等于Bi时&#xff0c;则说…

树莓派nmap扫描

debian系统安装nmap&#xff1a; sudo apt install nmap安装nmap完成后&#xff0c;输入 ip route 来查看当前Wi-Fi路由器的ip地址。 第一行的default via后显示的便是网关地址&#xff0c;也就是路由器地址。 获取到路由器ip地址后&#xff0c;在终端中输入&#xff1a; …

【产品经理必会知识点】马斯洛需求理论

马斯洛需求理论&#x1f453;从7个层次洞察人心 ❓你是否常在挑选晚餐时感到纠结&#xff0c;不知道到底想吃什么&#xff1f; ❓你是否在购物时被某些商品深深吸引&#xff0c;明明没那么需要却难以抗拒&#xff1f; ❓你是否常常感到迷失于用户五花八门的需求之中不得要领…

5. 分布式链路追踪TracingFilter改造增强设计

前言 在4. 分布式链路追踪客户端工具包Starter设计一文中&#xff0c;我们实现了基础的Starter包&#xff0c;里面提供了我们自己定义的Servlet过滤器和RestTemplate拦截器&#xff0c;其中Servlet过滤器叫做HoneyTracingFilter&#xff0c;仅提供了提取SpanContext&#xff0…