【C++进阶篇】C++容器完全指南:掌握set和map的使用,提升编码效率

news2025/5/19 16:49:50

C++容器的实践与应用:轻松掌握set、map与multimap的区别与用法

  • 一. 序列式容器与关联式容器
    • 1.1 序列式容器 (Sequential Containers)
    • 1.2 关联式容器 (Associative Containers)
  • 二. set系列使用
    • 2.1 set的构造和迭代器
    • 2.2 set的增删查
      • 2.2.1 插入
      • 2.2.2 查找
      • 2.2.3 删除
    • 2.3 multiset和set的差异
  • 三. map系列使用
    • 3.1 pair类
      • 3.1.1 定义与创建
      • 3.1.2 访问元素
    • 3.2 map构造
    • 3.3 map增删查
      • 3.3.1 插入
      • 2.2.2 查找
      • 2.2.3 删除
    • 3.4 map[]功能(重点)
      • 3.4.1 基本功能
      • 3.4.2 返回值类型
      • 3.4.3 自动插入特性
    • 3.5 multimap和map的差异
  • 四. 最后

在C++中,容器是存储和操作数据的核心工具。序列式容器(如vector、list)通过线性顺序存储数据,而关联式容器(如set、map)则通过键值对存储数据,允许更高效的查找、插入和删除。set是一个存储唯一元素的容器,内部自动排序,底层通常使用红黑树实现。它支持高效的查找和元素去重。map是存储键值对的容器,每个键都是唯一的,值可以重复,同样基于红黑树实现,提供快速的键值对查找。在需要快速检索、插入或删除元素时,set和map是非常实用的选择。

一. 序列式容器与关联式容器

1.1 序列式容器 (Sequential Containers)

序列式容器按照元素的插入顺序进行存储,它们提供了对元素的线性访问。序列式容器的元素是有顺序的,可以通过下标或迭代器来访问。常见的序列式容器包括:

  • vector:动态数组,支持快速的随机访问。适用于频繁访问元素,但在中间插入或删除元素时性能较差。

  • deque:双端队列,支持在两端快速插入和删除元素,但相比 vector,在访问和修改元素时稍慢。

  • list:双向链表,支持在任意位置快速插入和删除元素,但不支持随机访问。

  • array:固定大小的数组,支持快速随机访问,但在大小固定时使用。

  • forward_list:单向链表,比 list 更节省内存,但只支持向前遍历。

1.2 关联式容器 (Associative Containers)

关联式容器是基于键值对的容器,每个元素由键和值组成,并且通过键进行访问。它们通常提供基于键的排序和查找功能,能够高效地查找、插入和删除元素。常见的关联式容器包括:

  • set:存储唯一元素的集合,自动排序。可以高效地判断元素是否存在。

  • map:存储键值对,其中每个键都是唯一的,值可以重复。自动按照键排序。

  • multiset:与 set 类似,但允许存储重复的元素。

  • multimap:与 map 类似,但允许存储重复的键。

声明:本篇文章重点介绍关联式容器中的set,map

二. set系列使用

set的底层是用红黑树实现的,增删查效率是 O(logN),迭代器的遍历是中序,所以是有序的。

2.1 set的构造和迭代器

set的迭代器是双向迭代器,遍历默认是升序的,因为底层说到底还是二叉搜索树,所以迭代器(const和非const版本迭代器)都不支持修改数据,会破坏二叉搜索树的结构。

构造类型原型功能
无参默认构造explicit set (const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());构造一个指定类型T的对象
迭代器区间构造template set(InputIterator first, InputIterator last,const key_compare & comp = key_compare(),const allocator_type & = allocator_type());使用迭代器区间初始化对象
初始化列表构造set(initializer_list<value_type> il,const key_compare & comp = key_compare(),const allocator_type & alloc = allocator_type());使用初始化列表构造对象
拷贝构造set (const set& x);使用拷贝构造对象
迭代器原型功能
正向迭代器iterator begin();iterator end()正向遍历容器中的数据
反向迭代器reverse_iterator rbegin();reverse_iterator rend();反向遍历容器中的数据

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#include<iostream>
#include<set>
using namespace std;

int main()
{
	//无参默认构造
	set<int> s1;
	cout << "修改前s1: ";
	for (auto ch : s1)
	{
		cout <<"原:s1 " << ch;
	}
	cout << endl;

	//迭代器区间构造
	set<int> s2({ 1,2,3,4,5,6,7,8,9,10 });//initializer 列表构造
	//set<int> s1(s2.begin(), s2.end());错误写法,s1重定义
	//使用赋值,或者直接插入
	//s1.insert(s2.begin(),s2.end())
	s1 = set<int>(s2.begin(), s2.end());//创建临时对象,进行赋值

	cout << "修改后s1:";
	for (auto ch : s1)
	{
		cout << ch << " ";
	}
	cout << endl;

	//拷贝构造
	set<int> s3(s1);
	cout << "s3: ";
	for (auto ch : s3)
	{
		cout <<ch << " ";
	}
	cout << endl;

	// 正确的反向遍历
	cout << "Reverse traversal of s3: ";
	for (auto rit = s3.rbegin(); rit != s3.rend(); ++rit) {
		cout << *rit << " ";
	}
	cout << endl;

	return 0;
}

2.2 set的增删查

2.2.1 插入

类型原型功能
单个插入pair<iterator,bool> insert (const value_type& val);插入单个数据,插入已经存在插入失败
列表插入insert (initializer_list<value_type> il);使用初始化列表插入元素
迭代器区间插入template void insert(InputIterator first, InputIterator last);使用迭代器区间插入元素

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#include<iostream>
#include<set>
using namespace std;


int main()
{
	int a = 10;
	set<int> s;
	s.insert(a);//插入单个数据
	for (auto ch : s)
	{
		cout << ch;
	}
	cout << endl;
	
	s.insert({ 1,2,3,4,5,6,7,8,9 });//初始化列表插入
	for (auto ch : s)
	{
		cout << ch<<" ";
	}
	cout << endl;

	set<int> s3({ 10,20,30,40,50,60,70,80,90,100 });
	s.insert(s3.begin(), s3.end());//迭代器区间插入数据
	for (auto ch : s)
	{
		cout << ch << " ";
	}
	cout << endl;
	return 0;
}

2.2.2 查找

类型原型功能
查找单个元素iterator find (const value_type& val);查找val,返回val所在的迭代器,没有找到返回end()
查找每个元素的总出现个数size_type count (const value_type& val) const;查找val,返回Val的个数

下面将给出一个整合代码演示上述的功能:

  • 示例代码:

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

int main()
{
	set<int> s;
	s.insert({ 1,2,3,4,5,6,7,8,9 });//初始化列表插入
	for (auto ch : s)
	{
		cout << ch<<" ";
	}
	cout << endl;
	auto it = s.find(6);//存在返回所在迭代器
	cout << *it << endl;

	it = s.find(10);//不存在不可进行解引用
	//cout << *it << endl;error程序会终止

	int ret = s.count(6);
	cout << ret << endl;//查找6出现的总个数
	return 0;
}

2.2.3 删除

类型原型功能
删除单个元素size_type erase (const value_type& val);删除val,val不存在返回0,存在返回1
删除迭代器位置iterator erase (const_iterator position);删除⼀个迭代器位置的值
删除迭代器区间iterator erase (const_iterator first, const_iterator last)删除⼀段迭代器区间的值

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
	set<int> s;
	s.insert({ 1,2,3,4,5,6,7,8,9 });//初始化列表插入
	cout << "删除前: ";
	for (auto ch : s)
	{
		cout << ch<<" ";
	}
	cout << endl;

	cout << "删除5后: ";
	s.erase(5);//删除单个值
	for (auto ch : s)
	{
		cout << ch << " ";
	}
	cout << endl;

	cout << "删除8后: ";
	auto it = s.find(8);
	s.erase(it);//删除迭代器位置的值
	for (auto ch : s)
	{
		cout << ch << " ";
	}
	cout << endl;

	cout << "全部删除后: ";
	s.erase(s.begin(), s.end());//删除迭代器区间区间的值,等效于s.clear()
	for (auto ch : s)
	{
		cout << ch << " ";
	}
	cout << endl;
	return 0;
}

补充:

// 返回⼤于等val位置的迭代器

  • iterator lower_bound (const value_type& val) const;

// 返回⼤于val位置的迭代器

  • iterator upper_bound (const value_type& val) const;

2.3 multiset和set的差异

multiset和set的使⽤基本完全类似,主要区别点在于multiset⽀持值冗余,说白就是允许插入相同的值。
下面主要来看insert/find/count/erase都围绕着⽀持值冗余有所差异,示例代码:


```cpp
#include<iostream>
#include<set>
using namespace std;
int main()
{
	// 相⽐set不同的是,multiset是排序,但是不去重
	multiset<int> s = { 4,2,7,2,4,8,4,5,4,9 };
	auto it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	// 相⽐set不同的是,x可能会存在多个,find查找中序的第⼀个
	int x;
	cin >> x;
	auto pos = s.find(x);
	while (pos != s.end() && *pos == x)
	{
		cout << *pos << " ";
		++pos;
	}
	cout << endl;
	// 相⽐set不同的是,count会返回x的实际个数
	cout << s.count(x) << endl;
	// 相⽐set不同的是,erase给值时会删除所有的x
	s.erase(x);
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	return 0;
}

三. map系列使用

map的底层是红黑树,key/value结构场景,也是有序的。

3.1 pair类

在C++中,pair 是标准模板库(STL)提供的一个模板类,用于将两个可能不同类型的对象组合成一个单一单元。

3.1.1 定义与创建

#include // 包含pair的头文件
// 创建pair的几种方式
std::pair<int, double> p1; // 默认构造,两个元素被值初始化
std::pair<int, double> p2(1, 3.14); // 直接初始化 std::pair<int,
double> p3 = {2, 2.718}; // 列表初始化(C++11起) auto p4 =
std::make_pair(3, 1.618); // 使用make_pair辅助函数

3.1.2 访问元素

int first_element = p2.first; // 访问第一个元素(int类型)
double second_element = p2.second; // 访问第二个元素(double类型)

结论:pair 是C++中处理简单二元组合的高效工具,在需要临时组合两个相关值时非常有用。对于更复杂的数据结构,建议使用 struct 或 class 来提高代码可读性。

3.2 map构造

map的迭代器是双向迭代器,遍历默认是升序的,因为底层说到底还是二叉搜索树,所以迭代器(const和非const版本迭代器)都不支持修改数据,会破坏二叉搜索树的结构。

构造类型原型功能
无参默认构造explicit map(const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());构造一个指定类型T的对象
迭代器区间构造template map(InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type & = allocator_type());使用迭代器区间初始化对象
初始化列表构造map(initializer_list<value_type> il,const key_compare & comp = key_compare(),const allocator_type & alloc = allocator_type());使用初始化列表构造对象
拷贝构造map (const map& x);使用拷贝构造对象
迭代器原型功能
正向迭代器iterator begin();iterator end();正向遍历容器中的数据
反向迭代器reverse_iterator rbegin();reverse_iterator rend();反向遍历容器中的数据

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#include<iostream>
#include<map>
using namespace std;

int main()
{
	//无参默认构造
	map<string, string> t1;
	for (auto entry : t1)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	//初始化列表构造
	map<string, string> t2({{ "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });
	for (auto entry : t2)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	//迭代器区间构造
	map<string, string> t3(t2.begin(), t2.end());
	for (auto entry : t3)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	//拷贝构造
	map<string, string> t4(t2);
	for (auto entry : t4)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	//正向迭代器遍历
	auto it = t4.begin();
	while (it != t4.end())
	{
		cout << it->first << " " << it->second << endl;
		++it;
	}
	cout << endl;

	//反向迭代器遍历
	for (auto it = t4.rbegin(); it != t4.rend(); it++)
	{
		cout << it->first << " " << it->second << endl;
	}

	return 0;
}

3.3 map增删查

3.3.1 插入

类型原型功能
单个插入pair<iterator,bool> insert (const value_type& val);单个数据插⼊,如果已经key存在则插⼊失败,key存在相等value不相等也会插⼊失败
列表插入void insert (initializer_list<value_type> il);列表插⼊,已经在容器中存在的值不会插⼊
迭代器区间插入template void insert(InputIterator first, InputIterator last);使用迭代器区间插入元素

下面将给出一个整合代码演示上述的功能:

  • 示例代码:

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


int main()
{

	pair<string, string> s("insert", "插入");
	map<string, string> t1;
	t1.insert(s);//插入单个元素
	cout << "t1: ";
	for (auto entry : t1)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	map<string, string> t2;
	t2.insert({ { "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });//初始化列表插入
	cout << "t2: ";
	for (auto entry : t2)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	map<string, string> t3;
	t3.insert(t2.begin(), t2.end());//迭代器区间插入
	cout << "t3: ";
	for (auto entry : t3)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	return 0;
}

2.2.2 查找

类型原型功能
查找单个元素iterator find (const value_type& val);查找val,返回val所在的迭代器,没有找到返回end()
查找每个元素的总出现个数size_type count (const value_type& val) const;查找val,返回Val的个数

下面将给出一个整合代码演示上述的功能:

  • 示例代码:
#include<iostream>
#include<map>
using namespace std;


int main()
{
	map<string, string> t2;
	t2.insert({ { "apple", "苹果" },{ "apple", "苹果" },{ "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });//初始化列表插入
	cout << "t2: ";
	for (auto entry : t2)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}

	auto it = t2.find("apple");//返回apple位置所在的迭代器
	cout << it->first << " " << it->second << endl;

	int ret = t2.count("apple");//查找apple出现的总次数
	cout << ret << endl;
	return 0;
}

2.2.3 删除

类型原型功能
删除单个元素size_type erase (const value_type& val);删除val,val不存在返回0,存在返回1
删除迭代器位置iterator erase (const_iterator position);删除⼀个迭代器位置的值
删除迭代器区间iterator erase (const_iterator first, const_iterator last)删除⼀段迭代器区间的值

示例代码:


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


int main()
{
	map<string, string> t2;
	t2.insert({ { "apple", "苹果" },{ "apple", "苹果" },{ "apple", "苹果" }, { "banana", "香蕉" }, { "orange", "橙子" } });//初始化列表插入
	cout << "删除前t2: ";
	for (auto entry : t2)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	t2.erase("apple");//删除指定元素值
	cout << "前t2: ";
	for (auto entry : t2)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	auto it = t2.find("orange");
	t2.erase(it);//删除迭代器位置的值
	cout << "中t2: ";
	for (auto entry : t2)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	cout << endl;

	t2.erase(t2.begin(), t2.end());//删除迭代器区间的值
	cout << "后t2: ";
	for (auto entry : t2)
	{
		cout << entry.first << " -> " << entry.second << endl;
	}
	return 0;
}

3.4 map[]功能(重点)

3.4.1 基本功能

  1. 访问元素:如果键存在于map中,operator[]会返回该键对应的值的引用。
  2. 修改元素:通过返回的引用,可以直接修改该键对应的值。
  3. 插入元素:如果键不存在于map中,operator[]会插入一个新的键值对,其中键是给定的键,值是值类型的默认构造值(对于内置类型如int、string等,默认构造值通常是0或空字符串;对于自定义类型,则是其默认构造函数创建的对象)。

3.4.2 返回值类型

operator[]返回的是值的引用(value_type&),这允许对值进行直接修改。

3.4.3 自动插入特性

当使用operator[]访问一个不存在的键时,map会自动插入一个新的键值对。
新插入的键的值部分是其值类型的默认构造值。

  • 使用实例:
#include<iostream>
#include<map>
#include<string>
using namespace std;

int main() {
    map<string, int> wordCount;

    // 访问并修改现有元素
    wordCount["apple"] = 10; // 插入或修改键为"apple"的元素
    cout << "apple: " << wordCount["apple"] << endl; // 输出: apple: 10

    // 访问不存在的键,自动插入新元素
    cout << "banana: " << wordCount["banana"] << endl; // 输出: banana: 0(因为int的默认构造值是0)

    // 修改自动插入的元素
    wordCount["banana"] += 5;
    cout << "banana: " << wordCount["banana"] << endl; // 输出: banana: 5

    // 使用at()方法访问元素(需要确保键存在)
    try {
        cout << "orange: " << wordCount.at("orange") << endl;
    } catch (const out_of_range& e) {
        cout << "orange: " << e.what() << endl; // 输出: orange: map::at: key not found
    }

    return 0;
}

3.5 multimap和map的差异

multimap和map的使⽤基本完全类似,主要区别点在于multimap⽀持关键值key冗余,那么
insert/find/count/erase都围绕着⽀持关键值key冗余有所差异,

  • 示例代码:
#include <iostream>
#include <map>
#include <string>

using namespace std;

int main() {
    // 创建multimap并插入数据
    multimap<string, int> scores = {
        {"Alice", 90},
        {"Bob", 85},
        {"Alice", 95},  // 允许重复的key
        {"Charlie", 88}
    };

    // 1. 查找操作(返回第一个匹配项)
    auto it = scores.find("Alice");
    if (it != scores.end()) {
        cout << "找到Alice的第一个分数: " << it->second << endl; // 输出90
    }

    // 2. 计数操作(统计重复key的数量)
    int count = scores.count("Alice");
    cout << "Alice出现的次数: " << count << endl; // 输出2

    // 3. 范围查找(获取所有匹配项)
    cout << "所有Alice的分数: ";
    auto range = scores.equal_range("Alice");
    for (auto itr = range.first; itr != range.second; ++itr) {
        cout << itr->second << " "; // 输出90 95
    }
    cout << endl;

    // 4. 删除操作(删除所有匹配项)
    scores.erase("Alice");
    cout << "删除Alice后剩余元素数量: " << scores.size() << endl; // 输出2(Bob和Charlie)

    // 5. 尝试使用[]操作符(会编译失败)
    // scores["David"] = 78; // 错误:multimap不支持[]操作符

    return 0;
}

通过这个示例可以看出,multimap在处理需要多个相同key的场景时比map更灵活,但相应地也失去了一些特性(如[]操作符的直接访问能力)。在实际开发中,应根据是否需要key唯一性来选择合适的数据结构。

四. 最后

本文详述了C++中关联式容器set、multiset、map、multimap的用法,涵盖构造、迭代器、增删查等操作。set自动排序去重,multiset允许重复;map存储键值对,multimap支持键冗余。重点解析了map的[]操作符自动插入特性及multimap的范围查找。通过代码示例展示了各容器的核心功能与应用场景,是学习C++标准库关联容器的实用指南。

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

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

相关文章

世界模型+大模型+自动驾驶 论文小汇总

最近看了一些论文&#xff0c;懒得一个个写博客了&#xff0c;直接汇总起来 文章目录 大模型VLM-ADVLM-E2EOpenDriveVLAFASIONAD&#xff1a;自适应反馈的类人自动驾驶中快速和慢速思维融合系统快系统慢系统快慢结合 世界模型End-to-End Driving with Online Trajectory Evalu…

C++函数三剑客:缺省参数·函数重载·引用的高效编程指南

前引&#xff1a;在C编程中&#xff0c;缺省参数、函数重载、引用是提升代码简洁性、复用性和效率的三大核心机制。它们既能减少冗杂的代码&#xff0c;又能增强接口设计的灵活性。本文将通过清晰的理论解析与实战案列&#xff0c;带你深入理解这三者的设计思想、使用场景以及闭…

SWUST数据结构下半期实验练习题

1068: 图的按录入顺序深度优先搜索 #include"iostream" using namespace std; #include"cstring" int visited[100]; char s[100]; int a[100][100]; int n; void dfs(int k,int n) {if(visited[k]0){visited[k]1;cout<<s[k];for(int i0;i<n;i){i…

机器学习 Day18 Support Vector Machine ——最优美的机器学习算法

1.问题导入&#xff1a; 2.SVM定义和一些最优化理论 2.1SVM中的定义 2.1.1 定义 SVM 定义&#xff1a;SVM&#xff08;Support Vector Machine&#xff0c;支持向量机&#xff09;核心是寻找超平面将样本分成两类且间隔最大 。它功能多样&#xff0c;可用于线性或非线性分类…

答题pk小程序道具卡的获取与应用

道具卡是答题PK小程序中必不可少的一项增加趣味性的辅助应用&#xff0c;那么道具卡是如何获取与应用的呢&#xff0c;接下来我们来揭晓答案&#xff1a; 一、道具卡的获取&#xff1a; 签到获取&#xff1a;在每日签到中签到不仅可获得当日的签到奖励积分&#xff0c;同时连…

leetcode3265. 统计近似相等数对 I-medium

1 题目&#xff1a;统计近似相等数对 I 官方标定难度&#xff1a;中 给你一个正整数数组 nums 。 如果我们执行以下操作 至多一次 可以让两个整数 x 和 y 相等&#xff0c;那么我们称这个数对是 近似相等 的&#xff1a; 选择 x 或者 y 之一&#xff0c;将这个数字中的两个…

【架构篇】代码组织结构设计

代码组织结构设计&#xff1a;模块化分层与高效协作实践 摘要 本文以Java项目为例&#xff0c;解析后端代码组织的标准化结构&#xff0c;涵盖模块划分原则、依赖管理策略及实际应用场景。通过模块化设计提升代码可维护性、团队协作效率及系统扩展能力。 一、模块化设计的核心…

日期数据渲染转换问题

今天在学习Springboot框架时&#xff0c;想做一个非常简单的增删改查巩固一下&#xff0c;结果在数据渲染上出现了一个小问题&#xff0c;如图数据库中的数据一切正常 但是在前端渲染时&#xff0c;是下面这个效果 这是因为数据库存储的日期类型数据在前端渲染时&#xff0c;没…

ubuntu18.04编译qt5.14.2源码

ubuntu18.04编译qt5.14.2源码 文章目录 ubuntu18.04编译qt5.14.2源码[toc]1 前言2 参考文档3 下载源码3.1 方法13.2 方法23.3 方法3 4 ubuntu编译qt源码4.1 环境准备4.2 设置交换分区大小4.3 编译源码4.4 添加环境变量4.5 验证编译结果4.6 编译帮助文档&#xff08;qch&#xf…

创建指定版本的vite项目

1、获取vite的版本号 npm view create-vite versions 注:4.4.1版本即对应着node16版本的项目 2、创建制定版本的vite项目 npm init vite<version>

iOS 初识RunLoop

iOS 初识RunLoop 文章目录 iOS 初识RunLoopRunLoop的概念RunLoop的功能RunLoop和线程的关系RunLoop的结构ModeObserverTimer 和 source小结 RunLoop的核心RunLoop的流程RunLoop的应用AutoreleasePool响应触控事件刷新界面常驻线程网络请求NSTimer 和 CADisplayLinkNSTimerGCDTi…

电子电路仿真实验教学平台重磅上线!——深圳航天科技创新研究院倾力打造,助力高校教学数字化转型

在传统电子电路课堂中&#xff0c;实验室的灯光总与高昂的成本、拥挤的设备、反复的耗材损耗相伴&#xff0c;而教师不得不面对这样的现实&#xff1a;有限的硬件资源束缚着教学深度&#xff0c;不可逆的实验风险制约着创新探索&#xff0c;固化的时空场景阻碍着个性化学习。当…

搭建一个WordPress网站需要多少成本

WordPress 最初可能只是一个简单的博客平台。但近年来&#xff0c;它不仅成为了最好的博客平台&#xff0c;还成为了一个全面的内容管理系统。白宫、jQuery、NGINX、《纽约时报》等企业都把 WordPress 作为自己的网上家园。 不过&#xff0c;它们只是其中的佼佼者。根据 Built…

Python数据可视化 - Pyecharts绘图示例

文章目录 一、Pyecharts简介及安装1. Pyecharts简介2. 安装Pyecharts 二、准备数据三、饼图示例1. 初始化选项配置2. 饼图相关设置3. 全局配置项3.1 标题配置项3.2 图例配置项3.3 提示框配置项3.4 工具箱配置项3.5 视觉映射配置项 4. 系列配置项4.1 标签选项配置4.2 图元样式配…

NC016NC017美光固态芯片NC101NC102

NC016NC017美光固态芯片NC101NC102 在存储技术的演进历程中&#xff0c;美光科技的NC016、NC017、NC101与NC102系列固态芯片&#xff0c;凭借其技术创新与市场适应性&#xff0c;成为行业关注的焦点。本文将从技术内核、产品性能、行业动向、应用场景及市场价值五个维度&#…

[Android] 青木扫描全能文档3.0,支持自动扫描功能

声明&#xff1a;根据许多帖友的反馈&#xff0c;我也根据重新实测得出结论&#xff1a;该app是提供一天的体验时间&#xff0c;后续还是采取收费才能使用功能的措施。因为现在市面上免费使用的扫描工具很少了&#xff0c;所以当初我初步测试感觉软件不错就发布了出来&#xff…

通俗解释Transformer在处理序列问题高效的原因(个人理解)

Transformer出现的背景 CNN 的全局关联缺陷卷积神经网络&#xff08;CNN&#xff09;通过多层堆叠扩大感受野&#xff0c;但在自然语言处理中存在本质局限&#xff1a; 局部操作的语义割裂&#xff1a;每个卷积核仅处理固定窗口&#xff08;如 3-5 词&#xff09;&#xff0c;…

区间带边权并查集,XY4060泄露的测试点

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 码蹄集 二、解题报告 1、思路分析 关于带边权并查集&#xff1a;并查集&…

【数据结构】1-4算法的空间复杂度

数据结构知识点合集 知识点 空间复杂度的定义以及计算 空间复杂度--空间开销&#xff08;内存开销&#xff09;与问题规模 n 之间的关系 无论问题规模怎么变&#xff0c;算法运行所需的内存空间都是固定的常量&#xff0c;算法空间复杂度为S(n) O(1)&#xff0c;S 表示 “Spac…

OpenAI推出Codex — ChatGPT内置的软件工程Agents

OpenAI继续让ChatGPT对开发者更加实用。 几天前,他们增加了连接GitHub仓库的支持,可以"Deep Research"并根据你自己的代码提问。 今天,该公司在ChatGPT中推出了Codex的研究预览版,这是迄今为止最强大的AI编码Agent。 它可以编写代码、修复错误、运行测试,并在…