当前位置: 首页 > news >正文

突破编程_C++_C++11新特性(unordered_multimap)

1 概述

std::unordered_multimap 是一个哈希表实现的无序容器,它存储的元素是键值对,并且允许键的重复。这意味着同一个键可以关联多个值。在 std::unordered_multimap 中,元素的插入顺序是不确定的,并且不会因为元素的插入、删除或查找而改变。

std::unordered_multimap 与 std::multimap 的主要区别如下:

  • std::multimap 也是一个关联容器,它存储的元素也是键值对,并且同样允许键的重复。但是,std::multimap 的内部实现是基于红黑树这种有序数据结构,因此它存储的元素是按键的升序(或降序,取决于比较函数的定义)排列的。而 std::unordered_multimap 则不保证元素的任何顺序,它主要关注的是高效的查找、插入和删除操作。
  • 在性能上,std::unordered_multimap 的查找、插入和删除操作的时间复杂度通常接近 O(1),这是因为它使用了哈希表这种数据结构。而 std::multimap 的这些操作的时间复杂度则是 O(log n),因为它基于红黑树实现。因此,当对性能有较高要求,且不需要元素有序时,std::unordered_multimap 可能会是一个更好的选择。

std::unordered_multimap 的实现基于哈希表。哈希表是一种数据结构,它使用哈希函数将键映射到数组的索引,从而可以在常数时间内找到键对应的值。在 std::unordered_multimap 中,由于允许键的重复,所以每个哈希表槽位可能对应一个链表或其他动态数组结构,用于存储具有相同哈希值的键值对。

当插入一个元素时,首先计算键的哈希值,然后使用该哈希值找到数组中的对应槽位。如果槽位为空,则直接在该槽位插入新的键值对。如果槽位已有元素,则将新的键值对添加到对应的链表或动态数组中。

查找和删除操作也类似,首先计算键的哈希值找到对应的槽位,然后在槽位对应的链表或动态数组中查找或删除指定的键值对。

需要注意的是,哈希表的性能在很大程度上取决于哈希函数的质量。一个好的哈希函数应该能够将键均匀地映射到数组的各个槽位,以减少哈希冲突的发生。

2 声明与初始化

2.1 声明

首先,需要包含 <unordered_map> 头文件,然后声明一个 std::unordered_multimap 变量,并指定键和值的类型。

#include <unordered_map>  std::unordered_multimap<KeyType, ValueType> mapName;

其中 KeyType 是键的类型,ValueType 是值的类型,mapName 是你为该 unordered_multimap 变量选择的名称。

2.2 初始化

初始化 std::unordered_multimap 可以通过多种方式进行,包括默认初始化、使用列表初始化器初始化、复制初始化、移动初始化等。

(1)默认初始化

如果没有提供任何初始化器,std::unordered_multimap 将被默认初始化,这意味着它将不包含任何元素,并且会使用默认的哈希函数和键相等性比较对象。

std::unordered_multimap<std::string, int> myMultimap; // 默认初始化

(2)使用列表初始化器初始化

可以使用列表初始化器(大括号 {})来初始化 std::unordered_multimap,并直接添加一些元素。

std::unordered_multimap<std::string, int> myMultimap = {  {"apple", 1},  {"banana", 2},  {"apple", 3} // 注意:允许相同的键  
};

在这个例子中,myMultimap 初始时包含三个元素,其中有两个元素具有相同的键 “apple”。

(3)注意事项

  • std::unordered_multimap 不保证元素的顺序,因此不应该依赖特定的插入顺序。
  • 插入到 std::unordered_multimap 中的键可以重复。
  • 如果键类型没有提供默认的哈希函数和相等性比较对象,则需要提供自定义的实现(后面会详细讲解)。

3 插入元素

3.1 插入方法

(1)使用 insert 成员函数

std::unordered_multimap 提供了一个 insert 成员函数,用于向容器中插入元素。该函数接受一个键值对,并将其添加到容器中。如果容器中已经存在具有相同键的元素,insert 函数仍然会插入新的键值对,因为 std::unordered_multimap 允许键的重复。

插入单个键值对

可以使用 insert 函数插入单个键值对。这通常通过创建一个 std::pair 对象来实现,其中第一个元素是键,第二个元素是值。

#include <unordered_map>  
#include <string>  int main() 
{  std::unordered_multimap<std::string, int> myMultimap;  // 插入单个键值对  myMultimap.insert(std::make_pair("apple", 10));  // 也可以直接使用花括号初始化列表来构造 pair 对象  myMultimap.insert({"banana", 20});  return 0;  
}

这个例子创建了一个 std::unordered_multimap 对象 myMultimap,并使用 insert 函数插入了两个键值对。第一个键值对是 (“apple”, 10),第二个键值对是 (“banana”, 20)。

插入多个键值对

也可以使用初始化列表一次性插入多个键值对。

#include <unordered_map>  
#include <string>  int main() 
{  std::unordered_multimap<std::string, int> myMultimap;  // 插入多个键值对  myMultimap.insert({  {"apple", 10},  {"banana", 20},  {"orange", 30}  });  return 0;  
}

在这个例子中,使用初始化列表一次性插入了三个键值对。

(2)使用迭代器插入

insert 函数还有一个重载版本,它接受一个迭代器和一个键值对,尝试在迭代器指向的位置插入元素。如果插入成功,函数返回一个指向新插入元素的迭代器;如果插入失败(例如,由于内存不足),则返回一个指向容器中下一个有效位置的迭代器。

#include <unordered_map>  
#include <string>  int main() 
{  std::unordered_multimap<std::string, int> myMultimap;  // 插入一个键值对,并获取指向它的迭代器  auto it = myMultimap.insert(myMultimap.begin(), std::make_pair("apple", 10));  return 0;  
}

这个例子使用 insert 函数的迭代器版本在容器的开始位置尝试插入一个键值对。返回的迭代器 it 指向新插入的元素。

(3)使用 emplace 成员函数

除了 insert 函数外,std::unordered_multimap 还提供了 emplace 成员函数,它可以在容器内直接构造元素,避免了不必要的复制或移动操作。这对于大型对象或那些复制/移动成本较高的对象特别有用。

#include <unordered_map>  
#include <string>  struct LargeObject {  std::string data;  // ... 其他成员和数据 ...  LargeObject(const std::string& d) : data(d) {  // 构造函数实现  }  
};  int main() 
{  std::unordered_multimap<std::string, LargeObject> myMultimap;  // 使用 emplace 插入元素,直接在容器内构造 LargeObject 对象  myMultimap.emplace("key", "large data");  return 0;  
}

这个例子定义了一个名为 LargeObject 的结构,它有一个接受 std::string 的构造函数。我们使用 emplace 函数直接向 myMultimap 中插入一个 LargeObject 对象,避免了先构造对象再复制的额外开销。

3.2 注意事项

  • 插入操作的时间复杂度在平均情况下是 O(1),但由于哈希冲突的存在,最坏情况下的时间复杂度可能较高。因此,为了获得最佳性能,应确保键的哈希函数分布均匀,并尽量减少哈希冲突。
  • 插入操作可能会导致容器的重新哈希(rehashing),这是一个相对昂贵的操作,因为它涉及到重新分配内存和重新计算所有元素的哈希值。

4 访问元素

4.1 使用迭代器遍历元素

由于 std::unordered_multimap 是一种容器,因此可以使用迭代器来遍历并访问其中的元素。迭代器类似于指针,可以用来访问容器中的元素。

(1)遍历所有元素

可以使用 begin() 和 end() 成员函数来获取指向容器第一个元素和最后一个元素之后位置的迭代器,然后使用这些迭代器遍历容器中的所有元素。

#include <iostream>  
#include <unordered_map>  
#include <string>  int main() 
{  std::unordered_multimap<std::string, int> myMultimap = {  {"apple", 10},  {"banana", 20},  {"apple", 30},  {"orange", 40}  };  // 使用迭代器遍历所有元素  for (auto it = myMultimap.begin(); it != myMultimap.end(); ++it) {  std::cout << it->first << ": " << it->second << std::endl;  }  return 0;  
}

这个例子创建了一个 std::unordered_multimap 对象 myMultimap,并使用 begin() 和 end() 获取迭代器来遍历容器中的所有元素。it->first 访问键,it->second 访问值。

(2)遍历具有特定键的所有元素

由于 std::unordered_multimap 允许键的重复,可能需要遍历具有特定键的所有元素。这可以通过结合 equal_range 函数和迭代器来实现。

#include <iostream>  
#include <unordered_map>  
#include <string>  int main() {  std::unordered_multimap<std::string, int> myMultimap = {  {"apple", 10},  {"banana", 20},  {"apple", 30},  {"orange", 40}  };  // 查找键为 "apple" 的所有元素  auto range = myMultimap.equal_range("apple");  for (auto it = range.first; it != range.second; ++it) {  std::cout << it->second << std::endl; // 输出值  }  return 0;  
}

上面代码的输出为:

10
30

在这个例子中,equal_range 返回一个包含两个迭代器的 pair,第一个迭代器指向第一个键为 “apple” 的元素,第二个迭代器指向第一个键不为 “apple” 的元素。通过遍历这个范围来访问所有键为 “apple” 的元素。

4.2 使用 find 函数查找元素

如果只需要查找具有特定键的第一个元素,可以使用 find 函数。如果找到了匹配的元素,find 会返回一个指向该元素的迭代器;如果没有找到,则返回 end() 迭代器。

#include <iostream>  
#include <unordered_map>  
#include <string>  int main() {  std::unordered_multimap<std::string, int> myMultimap = {  {"apple", 10},  {"banana", 20},  {"apple", 30},  {"orange", 40}  };  // 查找键为 "apple" 的第一个元素  auto it = myMultimap.find("apple");  if (it != myMultimap.end()) {  std::cout << "Found apple with value: " << it->second << std::endl;  } else {  std::cout << "Apple not found." << std::endl;  }  return 0;  
}

这个例子使用 find 函数来查找键为 “apple” 的第一个元素。如果找到了,就输出它的值;否则,输出 “Apple not found.”。

5 删除元素

5.1 使用 erase 成员函数删除单个元素

erase 成员函数可以用于删除容器中的单个元素。可以通过传递一个指向要删除元素的迭代器来调用它。

#include <iostream>  
#include <unordered_map>  
#include <string>  int main() {  std::unordered_multimap<std::string, int> myMultimap = {  {"apple", 10},  {"banana", 20},  {"apple", 30},  {"orange", 40}  };  // 假设我们有一个指向要删除元素的迭代器  auto it = myMultimap.find("apple"); // 查找键为 "apple" 的一个元素  if (it != myMultimap.end()) {  // 使用 erase 删除找到的元素  myMultimap.erase(it);  }  // 输出容器内容以验证元素已被删除  for (const auto& pair : myMultimap) {  std::cout << pair.first << ": " << pair.second << std::endl;  }  return 0;  
}

上面代码的输出为:

apple: 30
banana: 20
orange: 40

在这个例子中,首先使用 find 函数找到一个键为 “apple” 的元素的迭代器。然后,检查找到的迭代器是否不等于 end(),以确保找到了有效的元素。最后,调用 erase 并传入迭代器来删除该元素。

5.2 使用 erase 成员函数删除删除一系列元素

erase 成员函数还有一个重载版本,它接受两个迭代器作为参数,用于删除一个范围内的所有元素。这在你想要删除具有特定键的所有元素时非常有用。

#include <iostream>  
#include <unordered_map>  
#include <string>  int main() 
{  std::unordered_multimap<std::string, int> myMultimap = {  {"apple", 10},  {"banana", 20},  {"apple", 30},  {"orange", 40}  };  // 查找键为 "apple" 的元素范围  auto range = myMultimap.equal_range("apple");  // 删除范围内的所有元素  myMultimap.erase(range.first, range.second);  // 输出容器内容以验证元素已被删除  for (const auto& pair : myMultimap) {  std::cout << pair.first << ": " << pair.second << std::endl;  }  return 0;  
}

上面代码的输出为:

banana: 20
orange: 40

这个例子使用 equal_range 函数来获取一个包含所有键为 “apple” 的元素的范围。然后,调用 erase 并传入这个范围的开始和结束迭代器来删除所有这些元素。

5.3 使用 clear 成员函数删除所有元素

如果想要删除 std::unordered_multimap 中的所有元素,可以使用 clear 成员函数。这将移除容器中的所有键值对,并将容器的大小变为 0。

std::unordered_multimap<int, std::string> myMap;  
// 假设 myMap 中已经填充了一些元素  myMap.clear(); // 删除所有元素,myMap 现在为空

5.4 遍历删除

在 std::unordered_multimap 中遍历并删除元素时,需要特别小心,因为删除操作会使指向已删除元素的迭代器失效。如果试图使用一个已经失效的迭代器,程序可能会崩溃或产生不可预测的行为。

一种常见的策略是使用迭代器从 begin() 到 end() 遍历容器,并在遍历过程中删除满足特定条件的元素。但是,由于直接删除当前迭代器指向的元素会使迭代器失效,需要在删除前获取下一个迭代器的位置。这可以通过递增当前迭代器来完成,然后在递增之前检查它是否指向要删除的元素。

以下是一个示例,展示如何在遍历 std::unordered_multimap 时删除所有键为 “apple” 的元素:

#include <iostream>  
#include <unordered_map>  
#include <string>  int main() 
{  std::unordered_multimap<std::string, int> myMultimap = {  {"apple", 10},  {"banana", 20},  {"apple", 30},  {"orange", 40},  {"apple", 50}  };  // 使用迭代器遍历并删除键为 "apple" 的所有元素  for (auto it = myMultimap.begin(); it != myMultimap.end(); ) {  if (it->first == "apple") {  // 删除元素,并使迭代器指向下一个有效元素  it = myMultimap.erase(it);  } else {  // 如果不删除,则递增迭代器  ++it;  }  }  // 输出容器内容以验证元素已被删除  for (const auto& pair : myMultimap) {  std::cout << pair.first << ": " << pair.second << std::endl;  }  return 0;  
}

上面代码的输出为:

banana: 20
orange: 40

这个例子使用了一个 for 循环来遍历 myMultimap。在循环内部,首先检查当前迭代器的键是否为 “apple”。如果是,则调用 erase 来删除该元素,并更新迭代器 it 为 erase 返回的下一个有效迭代器。如果不删除当前元素,就递增迭代器以继续遍历。

注意:erase 成员函数返回指向被删除元素之后的那个元素的迭代器。如果 erase 被调用在最后一个元素上,它将返回 end()。这就是为什么循环条件仍然是 it != myMultimap.end(),因为即使删除了当前元素,it 在更新后仍然可能不是 end()。

这种遍历并删除元素的方法在大多数情况下都是安全的,因为它避免了使用已经失效的迭代器。然而,如果容器在遍历过程中被其他线程修改,那么可能会出现数据竞争。在多线程环境中,应确保适当的同步机制来避免这种情况。

6 使用自定义键类型

std::unordered_multimap 也可以使用自定义键类型。当使用自定义键类型时,需要为该类型定义哈希函数和键相等性比较函数。哈希函数用于将键映射到哈希表中的位置,而键相等性比较函数则用于确定两个键是否相等。

下面是一个示例,展示了如何使用自定义键类型 Person 作为 std::unordered_multimap 的键:

#include <iostream>  
#include <unordered_map>  
#include <string>  
#include <functional> // 用于 std::hash 和 std::equal_to  // 自定义键类型  
struct Person {  Person(const std::string& name, int age) : name(name), age(age) {}  // 为了简化示例,这里只根据name字段进行比较和哈希  bool operator==(const Person& other) const {  return name == other.name;  }  std::string name;  int age;    
};  // 为Person定义哈希函数  
struct PersonHash {  std::size_t operator()(const Person& p) const {  std::size_t h1 = std::hash<std::string>()(p.name);  // 可以在这里添加更多字段的哈希计算,如果需要的话  return h1;  }  
};  // 为Person定义键相等性比较函数  
struct PersonEqual {  bool operator()(const Person& lhs, const Person& rhs) const {  return lhs.name == rhs.name;  }  
};  int main() 
{  // 使用自定义键类型的unordered_multimap  std::unordered_multimap<Person, int, PersonHash, PersonEqual> peopleMap;  // 插入元素  peopleMap.emplace(Person("Alice", 30), 1);  peopleMap.emplace(Person("Bob", 25), 2);  peopleMap.emplace(Person("Alice", 30), 3); // 相同的Person对象可以插入多次  // 遍历并打印元素  for (const auto& pair : peopleMap) {  std::cout << pair.first.name << ": " << pair.first.age << " -> " << pair.second << std::endl;  }  return 0;  
}

上面代码的输出为:

Alice: 30 -> 1
Alice: 30 -> 3
Bob: 25 -> 2

这个例子定义了一个 Person 结构体,它包含 name 和 age 两个字段。此外还为 Person 定义了哈希函数 PersonHash 和键相等性比较函数 PersonEqual。

在创建 std::unordered_multimap 时,将 Person 作为键类型,并将 PersonHash 和 PersonEqual 作为模板参数传递给 std::unordered_multimap。这样,unordered_multimap 就知道如何为 Person 对象计算哈希值以及如何比较两个 Person 对象是否相等。

注意:在哈希函数和键相等性比较函数中,只考虑了 Person 的 name 字段。在实际情况中,可能需要根据 Person 的所有字段来计算哈希值和比较相等性,以确保正确的行为。特别是当两个 Person 对象具有相同的 name 但不同的 age 时,只根据 name 进行哈希和比较可能会导致意外的行为。

相关文章:

突破编程_C++_C++11新特性(unordered_multimap)

1 概述 std::unordered_multimap 是一个哈希表实现的无序容器&#xff0c;它存储的元素是键值对&#xff0c;并且允许键的重复。这意味着同一个键可以关联多个值。在 std::unordered_multimap 中&#xff0c;元素的插入顺序是不确定的&#xff0c;并且不会因为元素的插入、删除…...

15.WEB渗透测试--Kali Linux(三)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;14.WEB渗透测试--Kali Linux&#xff08;二&#xff09;-CSDN博客 Kali工具使用 3389远…...

Android-Framework pm list packages和pm install返回指定应用信息

一、环境 高通 Android 13 注&#xff1a;Android10 和Android13有些差异&#xff0c;代码位置不变&#xff0c;参照修改即可 二、pm简单介绍 pm工具为包管理&#xff08;package manager&#xff09;的简称 可以使用pm工具来执行应用的安装和查询应用宝的信息、系统权限、…...

CSS

什么是CSS&#xff1f; CSS是一门语言&#xff0c;用于控制网页表现 CSS&#xff08;Cascading Style Sheet&#xff09;&#xff1a;层叠样式表 W3C标准&#xff1a;网页主要由三部分组成 结构&#xff1a;HTML表现&#xff1a;CSS行为&#xff1a;JavaScript CSS导入方式…...

算法详解——选择排序和冒泡排序

一、选择排序 选择排序算法的执行过程是这样的&#xff1a;首先&#xff0c;算法遍历整个列表以确定最小的元素&#xff0c;接着&#xff0c;这个最小的元素被置换到列表的开头&#xff0c;确保它被放置在其应有的有序位置上。接下来&#xff0c;从列表的第二个元素开始&#x…...

图论(蓝桥杯 C++ 题目 代码 注解)

目录 迪杰斯特拉模板&#xff08;用来求一个点出发到其它点的最短距离&#xff09;&#xff1a; 克鲁斯卡尔模板&#xff08;用来求最小生成树&#xff09;&#xff1a; 题目一&#xff08;蓝桥王国&#xff09;&#xff1a; 题目二&#xff08;随机数据下的最短路径&#…...

矩阵起源新一年喜报连连!

新春伊始 矩阵起源向大家分享 一连串好消息 首先&#xff0c;公司创始人兼CEO王龙先生获评“2023深圳创新突出贡献人物“。这一荣誉是对其在推动数据库行业技术创新和产品开发方面所做出的卓越贡献的认可。他的领导力和创新精神不仅引领我司取得了显著的成就&#xff0c;也为…...

牛客——紫魔法师(并查集)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 “サーヴァント、キャスター、Medea。”--紫魔法师 给出一棵仙人掌(每条边最多被包含于一个环&#xff0c;无自环&#xff0c;无重边&#xff0c;保证连通)&#xff0c;要求用最少的…...

最新WooCommerce教程指南-如何搭建B2C外贸独立站

WooCommerce是全球最受欢迎的开源电子商务平台之一。它基于WordPress建站&#xff0c;只需一键安装即可使用。该平台提供了丰富的功能&#xff0c;包括产品发布、库存管理、支付网关和运输发货等&#xff0c;可以帮助搭建各种类型的电子商务网站。相比其他竞争对手&#xff0c;…...

一文教会你SpringBoot是如何启动的

SpringBoot启动流程分析 流程图 源码剖析 运行Application.run()方法 我们在创建好一个 SpringBoot 程序之后&#xff0c;肯定会包含一个类&#xff1a;xxxApplication&#xff0c;我们也是通过这个类来启动我们的程序的&#xff08;梦开始的地方&#xff09;&#xff0c;而…...

车载测试面试:各大车企面试题汇总

本博主可协助大家成功进军车载测试行业 TBOX 深圳 涉及过T-BOX测试吗Ota升级涉及的台架环境是什么样的&#xff1f;上车实测之前有没有一个仿真环境台架环境都什么零部件T-BOX了解多少Linux和shell有接触吗 单片机uds诊断是在实车上座的吗 uds在实车上插的那口 诊断仪器是哪…...

Qt散文一

Qt的事件分为普通事件和系统事件&#xff0c;普通事件比如用户按下键盘&#xff0c;系统事件比如定时器事件。事件循环的开始是从main函数的QApplication&#xff0c;然后调用exec()开始的&#xff0c;在执行exec()函数之后&#xff0c;程序将进入事件循环来监听应用程序的事件…...

MySQL学习Day32——数据库备份与恢复

在任何数据库环境中&#xff0c;总会有不确定的意外情况发生&#xff0c;比如例外的停电、计算机系统中的各种软硬件故障、人为破坏、管理员误操作等是不可避免的&#xff0c;这些情况可能会导致数据的丢失、 服务器瘫痪等严重的后果。存在多个服务器时&#xff0c;会出现主从服…...

阅读基础知识

一 网络 1. 三次握手四次挥手 三次握手&#xff1a;为了建立长链接进行交互即建立一个会话&#xff0c;使用 http/https 协议 ① 客户端产生初始化序列号 Seqx &#xff0c;向服务端发送建立连接的请求报文&#xff0c;将 SYN1 同步序列号&#xff1b; ② 服务端接收建立连接…...

【NestJS 编程艺术】1. NestJS设计模式深度解析:构建高效、可维护的服务端应用

在当今快速发展的软件开发领域&#xff0c;Node.js凭借其轻量级和高性能的特点&#xff0c;已经成为了构建服务端应用的首选技术之一。然而&#xff0c;随着应用规模的扩大&#xff0c;传统的Node.js框架如Express和Koa可能在架构设计和代码组织上显得力不从心。这时&#xff0…...

QT中connect()的参数5:Qt::DirectConnection、Qt::QueuedConnection区别

原文链接&#xff1a;https://blog.csdn.net/Dasis/article/details/120916993 connect用于连接QT的信号和槽&#xff0c;在qt编程过程中不可或缺。它其实有第5个参数&#xff0c;只是一般使用默认值&#xff0c;在满足某些特殊需求的时候可能需要手动设置。 Qt::AutoConnect…...

VXLAN学习笔记

声明&#xff1a;该博客内容大部分参考参考链接整理 什么是VXLAN&#xff1f; VXLAN(Virtual Extensible LAN)即虚拟扩展局域网&#xff0c;是大二层网络中广泛使用的网络虚拟化技术。在源网络设备与目的网络设备之间建立一条逻辑VXLAN隧道&#xff0c;采用MAC in UDP的封装方…...

全排列的不同写法(茴字的不同写法)及对应的时间开销

资源课件&#xff1a; CS106B-recursion-pptstanford library-timer.hstanford library-set.h 不同的方法 1------ Set<string> permutations1Rec(string remaining) {Set<string> res;if(remaining.size() 0) {res "";}else {for(int i 0; i <…...

权衡后台数据库设计中是否使用外键

目录 引言 外键简介 对比 真实后台项目中的权衡 结论 引言 在大学学习数据库课程时&#xff0c;我们会早早的接触到外键这一概念&#xff0c;同时我相信大部分人在懂了外键的概念后都会觉得外键很重要&#xff0c;在涉及多表一定要用&#xff0c;但后来在我接触到真实项目…...

ChatGPT提示词方法的原理

关于提示词&#xff0c;我之前的一些文章可以参考&#xff1a; 【AIGC】AI作图最全提示词prompt集合&#xff08;收藏级&#xff09;https://giszz.blog.csdn.net/article/details/134815245?ydrefereraHR0cHM6Ly9tcC5jc2RuLm5ldC9tcF9ibG9nL21hbmFnZS9hcnRpY2xlP3NwbT0xMDExL…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...