深入解析C++树形关联式容器:map、set及其衍生容器的使用与原理

文章目录

  • 一、引言
  • 二、关联式容器的中的 pair
      • a.pair 的创建及使用
      • b.pair 间的比较
  • 三、 map 与 set 详解
      • 1. map 的基本操作
      • 2. set 的基本操作
      • 3.关联式容器的迭代器
  • 四、 multimap 与 multiset 的特性
  • 五、关联式容器的使用技巧与注意事项
      • 1. 键值类型的选择与设计
      • 2. 自定义比较函数与排序规则
      • 3.其他注意事项


一、引言

1. 关联式容器的概念与重要性

关联式容器是C++标准库中的一种重要数据结构,它允许我们存储键值对(key-value pair)或单独的元素,并基于键(key)来快速访问或检索对应的值(value)或元素。关联式容器在多种场景下发挥着至关重要的作用,特别是在需要高效查找、插入和删除元素时。它们为程序员提供了便捷的工具,可以简化复杂的操作,并优化程序性能。

关联式容器通过内部的数据结构(如红黑树)来维护元素的顺序,这使得它们能够在常数时间内完成元素的查找、插入和删除操作。与顺序容器(如vector、list)相比,关联式容器在处理大量数据时具有更高的效率。

2. 关联式容器与序列式容器的区别

关联式容器与序列式容器的主要区别在于它们对元素的存储和访问方式的不同。序列式容器按照元素在容器中的位置来存储和访问元素,而关联式容器则是根据元素的键来存储和访问元素。

序列式容器(如vector、list、deque等)其底层为线性序列的数据结构,通过索引或迭代器来访问元素,里面存储的是元素本身。它们提供了对元素的顺序访问。

关联式容器则通过使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。因此,使得元素的存储和访问更加灵活和高效。它们允许我们根据键来快速查找、插入和删除元素。

⚠️关联容器不支持顺序容器的位置相关操作,例如 push_backpush_front。原因是关联容器中元素是根据关键字存储的,这些操作对其没有意义。而且,关联式容器也不支持构造函数或插入操作这些接收一个元素在和一个数量值的操作。

3. 常见的关联式容器概览

C++标准库提供了多种关联式容器,每种容器都有其特定的用途和特性。以下是一些常见的关联式容器及其简要描述:

  • std::map:存储键值对的关联容器,键是唯一的,元素按照键的值进行排序。
  • std::set:只存储键的关联容器,键是唯一的,元素按照键的值进行排序。
  • std::multimap:存储键值对的关联容器,允许有多个具有相同键的元素。
  • std::multiset:只存储键的关联容器,允许有多个相同的元素。

这些关联式容器提供了丰富的操作函数,如插入、查找、删除和遍历等,使得我们可以方便地使用它们来管理数据。通过选择适合的关联式容器,我们可以优化程序的性能并简化代码的实现。

后续C++11又提供了哈希结构的关联式容器,我们将在之后的文章做讲解。


二、关联式容器的中的 pair

在介绍关联容器之前,我们需要了解名为 pair的标准库类型,它定义在头文件 utility 中。

a.pair 的创建及使用

一个pair保存两个数据成员。类似容器,pair是用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。下面我们来看SGI-STL中关于键值对的定义:

template <class T1, class T2>
struct pair{
    typedef T1 first_type;
    typedef T2 second_type;
    T1 first;
    T2 second;
    pair(): first(T1()), second(T2()) {}
    pair(const T1& a, const T2& b): first(a), second(b) {}
};

一个pair对象包含两个数据成员:firstsecond,分别对应键和值。pair的模板参数指定了这两个成员的类型,即我们必须提供两个类项名。⚠️两个类型不要求一致!

例如,你可以创建一个pair<string, int>,其中first是一个字符串类型的键,而second是一个整数类型的值。

#include <utility> // for std::pair  
int main() {  
    std::pair<std::string, int> myPair;  
    myPair.first = "apple";  
    myPair.second = 10;  

    // 也可以使用构造函数初始化  
    std::pair<std::string, int> anotherPair("banana", 20);  
    return 0;
}

在关联容器中,pair扮演着非常重要的角色。关联容器(如smapsetmultimapmultiset)的元素类型实际上就是pair。对于mapmultimap,每个元素都是一个pair,其中first成员是键,second成员是与该键关联的值。

初始化一个 pair 可以使用构造函数,也可以使用 make_pair:

在这里插入图片描述

构造一个 pair 对象,其中第一个元素设置为 x,第二个元素设置为 y。通过传递参数给 make_pair,可以隐式推断模板类型,无需显式指定。

当我们向mapmultimap插入元素时,我们实际上是在插入一个pair对象。同样地,当我们从mapmultimap中检索元素时,我们得到的是一个指向pair的迭代器。

b.pair 间的比较

其中,<><=>= 四个运算符会先比较两个 pair 中的第一个变量,在第一个变量相等的情况下再比较第二个变量。

在这里插入图片描述

每个操作符重载,都需要传入两个 std::pair 对象 lhsrhs,它们都具有相同的模板类型 <T1, T2>。这些操作符重载的返回值都是 bool 类型。

  • operator==:判断两个 std::pair 对象是否相等。如果它们的第一个元素和第二个元素都相等,则返回 true,否则返回 false
  • operator!=:判断两个 std::pair 对象是否不相等。如果它们的第一个元素或第二个元素有一个不相等,则返回 true,否则返回 false
  • operator<:判断一个 std::pair 对象是否小于另一个 std::pair 对象。首先比较它们的第一个元素,如果第一个元素小于另一个对象的第一个元素,则返回 true;如果第一个元素相等,再比较第二个元素,如果第二个元素也小于另一个对象的第二个元素,则返回 true;否则返回 false
  • operator<=:判断一个 std::pair 对象是否小于或等于另一个 std::pair 对象。如果一个对象小于另一个对象或两个对象相等,则返回 true,否则返回 false
  • operator>:判断一个 std::pair 对象是否大于另一个 std::pair 对象。如果一个对象不小于另一个对象且两个对象不相等,则返回 true,否则返回 false
  • operator>=:判断一个 std::pair 对象是否大于或等于另一个 std::pair 对象。如果一个对象大于另一个对象或两个对象相等,则返回 true,否则返回 false

这些操作符的重载使得可以方便地比较 std::pair 对象的成员,例如在使用容器时进行查找、排序等操作。


三、 map 与 set 详解

关联式容器定义类如下表示容器关键字和值的类型:

类型别名解释
key_type此容器类型的关键字类型
mapped_type每个关键字关联的类型 ; 仅适用于map
value_type对于set,与key_type 相同;
对于map ,为 pair<const key_type,mapped_type>

对于set 类型,key_typevalue_type 是一样的;set 中保存的值就是关键字。在一个map中,元素是键值对。即,每个元素是一个pair 对象,包含一个关键之都一个关联的值。由于我们不能改变一个元素的关键字,因此这些 pair 的关键字部分是const 的。

只有 map 家族的类型才有 mapped_type

1. map 的基本操作

map是C++标准库中的一个关联容器,它存储的元素都是键值对,并且根据键的值自动排序。下面我们将详细讨论std::map的基本操作,包括插入与访问元素、查找元素、删除元素以及遍历元素。

template < class Key,                                     // map::key_type
           class T,                                       // map::mapped_type
           class Compare = less<Key>,                     // map::key_compare
           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
           > class map;

Key:表示 map 中键的类型,即 map::key_typeT:表示 map 中值的类型,即 map::mapped_type
Compare:用于定义键之间的比较方式,默认是 std::less<Key>,即默认情况下按照键的升序进行排序。可以根据需要传入自定义的比较函数对象。
Alloc:表示分配器类型,用于管理内存分配。默认情况下,使用 allocator<pair<const Key, T>> 作为默认的内存分配器。

  • 插入元素

插入元素到std::map中通常使用insert成员函数。你可以通过make_pair函数或者初始化列表来创建键值对,也可以添加一个元素的范围:

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
    map<string, int> myMap;
    // 插入元素
    myMap.insert(make_pair("apple", 10));
    myMap.insert({"pear",30});
    myMap.insert(pair<string, int>("orange",40));
    myMap.insert(map<string,int>::value_type("cherry",50));   
    myMap["banana"] = 20; // 使用下标操作符插入
    
    // 访问元素
    cout << "The value of apple is: " << myMap["apple"] << endl;
    cout << "The value of banana is: " << myMap.at("banana") << endl;
    return 0;
}

⚠️insert函数可以接收一对迭代器,也可以接收一个初始化列表,这两种行为类似的对应构造函数。对于一个给定的关键字,只有第一个带此关键字的元素才被插入到容器中。

要注意insert函数的返回值(c++98):

在这里插入图片描述

insert返回的值依赖于容器类型和参数:

  1. 单个元素插入:
    • 这种形式会尝试将值为 val 的元素插入到容器中。如果插入成功(即容器中原先没有与 val 相等的元素),则返回一个指向新插入元素的迭代器和 true;如果插入失败(容器中已经有一个与 val 相等的元素),则返回一个指向已存在元素的迭代器和 false
  2. 带有提示位置的插入:
    • 这种形式会尝试将值为 val 的元素插入到 position 所指定的位置之前。如果插入成功,则返回指向新插入元素的迭代器;如果插入失败,则返回一个指向已存在元素的迭代器**
  3. 范围插入:
    • 这种形式用于一次性插入范围 [first, last) 中的元素。该方法接受两个迭代器参数,分别指向要插入元素范围的起始和结束位置。
  • 访问元素

访问元素则可以通过下标操作符[]或者at成员函数,如果键不存在,下标操作符会创建一个新元素,而at则会抛出一个异常。都是通过键找到与键对应的值然后返回其引用:

//map::at
mapped_type& at (const key_type& k);
const mapped_type& at (const key_type& k) const;

//operator[]
mapped_type& operator[] (const key_type& k);
//使用 operator[] 函数的调用等效于以下操作:
(*((this->insert(make_pair(k,mapped_type()))).first)).second;

这个操作首先通过 make_pair(k, mapped_type()) 创建一个新的 key-value 对,并将其插入到容器中。然后,insert 方法返回一个指向新插入元素的迭代器,通过解引用 (*...) 操作获取此元素,并使用 .second 获取对应映射值的引用。

因此,对于一个map使用下标操作,其行为与数字和 vector上的下标操作不同。,通过使用 operator[],可以轻松地访问和更新 map 容器中的元素,如果元素不存在,则可以在访问时插入新元素。

  • 查找元素

对于不允许重复关键字的容器,可能使用find还是count 没什么区别。但对于允许重复关键字的容器,count还会做更多的工作。如果元素在容器中,它还会统计有多少个元素有相同的关键字。如果不需要计数,最好使用find。它返回一个迭代器,指向找到的元素,如果未找到元素,则返回end()迭代器。此外,count成员函数可以用来检查键是否存在于map中:

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
    map<string, int> myMap;
    myMap["apple"] = 10;
    myMap["banana"] = 20;
    // 查找元素
    auto it = myMap.find("apple");
    if (it != myMap.end()) 
       cout << "Found apple with value: " << it->second << endl;
    else 
        cout << "Apple not found." << endl;

    // 检查键是否存在
    if (myMap.count("banana") > 0) 
        cout << "Banana exists in the map." << endl;
    else 
        cout << "Banana does not exist in the map." << endl;
    return 0;
}
  • 删除元素

与顺序容器一样,我们可以通过传递给erase传入一个常量迭代器,或传入两个常量迭代器,表示一个范围。这两个版本的 erase 与对应的顺序容器的操作非常相似:指定的元素被删除,函数返回 void。关联容器提供一个额外的erase操作,它接受一个key_type 参数。此版本删除所有匹配给定关键字的元素(如果存在的话),返回实际删除的元素的数量。对于保存不重复关键字的容器,erase的返回值总是0或1。若返回值为0,则表明想要删除的元素并不在容器中。

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
    map<std::string, int> myMap;
    myMap["apple"] = 10;
    myMap["banana"] = 20;

    // 删除元素
    myMap.erase("apple"); // 删除键为"apple"的元素

    // 使用迭代器删除元素
    auto it = myMap.find("banana");
    if (it != myMap.end()) {
        myMap.erase(it);
    }

    return 0;
}
  • 遍历元素

遍历std::map中的元素通常使用迭代器。由于map中的元素是排序的,因此遍历将按照键的顺序进行。

示例代码:

#include <iostream>
#include <map>
#include <string>

int main() {
    std::map<std::string, int> myMap;
    myMap["apple"] = 10;
    myMap["banana"] = 20;
    myMap["cherry"] = 30;

    // 遍历元素
    for (const auto& kv : myMap) {
        std::cout << kv.first << ": " << kv.second << std::endl;
    }

    return 0;
}

在上面的代码中,我们使用了范围基于的for循环(C++11及以后版本)来遍历map中的每个键值对。kv是一个常量引用,它引用了map中的一个键值对。kv.first是键,kv.second是值。


2. set 的基本操作

template < class T,                        // set::key_type/value_type
           class Compare = less<T>,        // set::key_compare/value_compare
           class Alloc = allocator<T>      // set::allocator_type
           > class set;

T:表示 set 中元素的类型,即 set::key_typeset::value_type
Compare:用于定义元素之间的比较方式,默认是 less<T>,即默认情况下按照元素的升序进行排序。可以根据需要传入自定义的比较函数对象。
Alloc:表示分配器类型,用于管理内存分配。默认情况下,使用 allocator<T> 作为默认的内存分配器。

setmap几近相同,不再做赘述。

  • 插入元素

map相同都是使用insert进行插入。

set<int> s;  
s.insert(1);  
s.insert(2);  
s.insert(3);  
// 尝试插入已存在的元素,不会有任何效果  
s.insert(2);  
  • 查找元素

map类似,使用 find 成员函数来查找 set 中的元素。如果元素存在,find 将返回一个指向该元素的迭代器;如果元素不存在,则返回 end() 迭代器。

set<int> s = {1, 2, 3};  
auto it = s.find(2);  
if (it != s.end()) 
    cout << "Element found: " << *it << endl;  
else 
    cout << "Element not found" << endl;  

it = s.find(4);  
if (it == s.end())  
   cout << "Element not found" << endl;  
  • 删除元素

map类似,使用 erase 成员函数来删除 set 中的元素。你可以通过值或迭代器来指定要删除的元素。set可以将序列中重复性的元素去除掉。因为set要保证其有序,因此set中元素不能被直接修改,若要修改可以先删除,在插入。

set<int> s = {1, 2, 3};  
// 通过值删除元素  
s.erase(2);  
// 或者通过迭代器删除元素  
auto it = s.find(3);  
if (it != s.end()) {  
    s.erase(it);  
} 
  • 遍历元素

使用范围基于的 for循环或迭代器来遍历 set 中的元素。

#include <iostream>  
#include <set>  
using namespace std;
int main() {  
    set<int> s = {1, 2, 3};  
    //1、
    for (const auto& elem : s) 
        cout << elem << endl;  
   
    //2、
    for (set<int>::iterator it = s.begin(); it != s.end(); ++it) {  
        cout << *it << endl;  
    }  
    return 0;  
}

map中重载了[]运算符,因为其需要通过key获取value,而set中却没有。map中存储的是键值对,set中只储存了key。因map和set的底层结构都是红黑树,而红黑树是近似的平衡二叉搜索树,故查询时间复杂度为O(log N) 。


3.关联式容器的迭代器

当解引用一个关联容器选代器时,我们会得到一个类型为容器的 value_type 的的引用。

map而言,valve_type 是一个 pair 类型,其 first 成员保存const的关键字,second 成员保存值。此处假设我们有一个名为 wordsmap

map<string, int> words;		
auto map_it = words.begin();	// *map_it 是 pair<const string , int>对象的引用
cout << map_it->first << " " << map_it->second;
map_it->first = "another"; 		//错误:关键字是const的,不可改变
++map_it->second;				//正确:可以通过迭代器改变值

一个map 的 value_type 是一个 pair,我们可以改变 pair的值,但不能改变关键字成员的值。

虽然 set 类型同时定义了iteratorconst_iterator 类型,但两种类型都只允许只读访问 set 中的元素。与不能改变一个 map 元素的关键字一样,一个 set 中的关键字也是const的。可以用一个set迭代器来读取元素的值,但不能修改:

set<int> s = { 0,1,2,3,4,5,6,8,9 };
set<int>::iterator set_it = s.begin();
if (set_it != s.end()) {
    *set_it = 42;				//错误:set中的关键字是只读的 
    cout << *set_it << endl;	//正确:可以输出
}

⚠️当我们使用一个迭代器遍历一个 map、multimap、set、multiset时,迭代器按关键字升序遍历元素。


四、 multimap 与 multiset 的特性

multimapmultiset 是 C++ 标准模板库 (STL) 中的两种容器,它们分别允许存储多个具有相同键的元素和多个重复的元素。这两种容器对于处理某些特定问题非常有用,尤其是当您需要存储多个具有相同键的值或当您想要允许集合中的元素重复时。

  1. multimap

    特性:

    • 允许多值特性:与 map 不同,multimap 允许存储多个具有相同键的元素。

    主要操作:

    • 插入多个相同键值的元素:使用 insert 成员函数,可以插入具有相同键的多个元素。
    • 查找与遍历多值元素:可以使用 find 成员函数来查找具有特定键的第一个元素,然后使用迭代器来遍历所有具有该键的元素。

⚠️multimap和map的唯一不同就是:map中的key是唯一的,而multimapkey是可以重复的。且multimap中没有重载operator[]操作。

  1. multiset

    特性:

    • 允许多重元素:与 set 不同,multiset 允许存储多个相同的元素。

    主要操作:

    • 插入多个相同元素:使用 insert 成员函数,可以插入多个相同的元素。
    • 查找与遍历元素:可以使用 find 成员函数来查找特定元素,然后使用迭代器来遍历所有元素。

🙉 对允许重复关键字的容器,使用 erase删除元素的数量可能大于1。


五、关联式容器的使用技巧与注意事项

关联式容器(如 mapsetmultimapmultiset 等)在 C++ 标准库中提供了基于键值对存储元素的能力。在使用这些容器时,有一些重要的技巧和注意事项需要了解。

1. 键值类型的选择与设计

  • 唯一性:确保键值是唯一的(对于 mapset),或者可以接受重复键值(对于 multimapmultiset)。
  • 可比较性:键值类型必须支持比较操作,通常是通过定义 < 运算符或者提供一个自定义的比较函数。
  • 内存和性能:选择占用内存较小且比较操作效率高的类型作为键值类型。
  • 稳定性:如果键值类型包含动态分配的内存或资源,需要确保在键值比较和容器操作过程中这些资源的管理是安全的。

2. 自定义比较函数与排序规则

  • 自定义比较函数:当标准比较不满足需求时,可以通过提供自定义的比较函数来定义键值对的排序规则。即,使用仿函数。
  • 透明性:自定义比较函数应该保持透明性,即对于相等的键值,比较结果应该一致。
  • 性能:自定义比较函数的性能会影响容器的插入、查找和删除操作的效率。

3.其他注意事项

  • 迭代器失效:在修改关联式容器(如插入或删除元素)时,指向容器中元素的迭代器可能会失效。需要小心处理这种情况,避免使用失效的迭代器。
  • 范围查询:关联式容器提供了基于键值的范围查询功能(如 lower_bound()upper_bound())。合理利用这些功能可以提高查询效率。

关联容器支持通过关键字高效查找和提取元素。对关键字的使用将关联容器和顺序容器区分开来,顺序容器中是通过位置访问元素的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

openGauss学习笔记-241 openGauss性能调优-SQL调优-审视和修改表定义

文章目录 openGauss学习笔记-241 openGauss性能调优-SQL调优-审视和修改表定义241.1 审视和修改表定义概述241.2 选择存储模型241.3 使用局部聚簇241.4 使用分区表241.5 选择数据类型 openGauss学习笔记-241 openGauss性能调优-SQL调优-审视和修改表定义 241.1 审视和修改表定…

R语言复现:如何利用logistic逐步回归进行影响因素分析?

Logistic回归在医学科研、特别是观察性研究领域&#xff0c;无论是现况调查、病例对照研究、还是队列研究中都是大家经常用到的统计方法&#xff0c;而在影响因素研究筛选自变量时&#xff0c;大家习惯性用的比较多的还是先单后多&#xff0c;P&#xff1c;0.05纳入多因素研究&…

【深度学习笔记】8_2 异步计算

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 8.2 异步计算 此节内容对应的内容有兴趣的可以去看看原文。 今天的计算机是高度并行的系统&#xff0c;由多个CPU核、多个GPU、多个处…

yolov5模型压缩-torch_pruning

参考论文:DepGraph: Towards Any Structural Pruning(https://arxiv.org/abs/2301.12900) 主要原理:物理的移除参数,并自动找出层与层以及层之间的依赖,完成模型的自动裁剪 模型压缩效果:yolov5剪枝流程如下: pip install torch_pruning 新建prune.py: import torch_…

AppLink对51Tracking的集成方式

什么是51Tracking 51Tracking是一个提供国际物流跟踪服务的平台&#xff0c;用户可以通过该平台跟踪包裹在全球范围内的物流信息。该平台提供多家物流公司的跟踪服务&#xff0c;帮助用户更方便地了解包裹的运输情况和到达时间。提供实时运单查询、运单管理功能&#xff0c;支…

echarts绘制雷达图

<template><div><div>【云端报警风险】</div><div ref"target" class"w-full h-full" stylewidth&#xff1a;200px;height:300px></div></div> </template><script setup> import { ref, onMounte…

找视频素材软件去哪个app?推荐做短视频必备的几款APP!

做短视频的小伙伴们&#xff0c;有没有遇到过找不到合适素材的烦恼呢&#xff1f;有时候脑子里有好创意&#xff0c;却因为找不到合适的素材而搁置。 今天&#xff0c;我就来给大家推荐几个超实用的视频素材app&#xff0c;帮你的创意加加油&#xff01; 1. 蛙学网材网 首先要…

机器视觉检测设备的组成要素

机器视觉检测设备是一种先进的自动化检测技术工具&#xff0c;它利用光学、图像处理和计算机硬件及软件技术模拟并扩展人类的视觉功能&#xff0c;以实现对产品或目标物体进行自动化的尺寸测量、缺陷检测、表面质量评估、颜色识别、形状匹配以及位置判断等功能。这种设备通常包…

APP测试基本流程以及APP测试要点

一、 APP测试基本流程 1、流程图 2、测试周期 测试周期可按项目的开发周期来确定测试时间&#xff0c;一般测试时间为两三周&#xff08;即15个工作日&#xff09;&#xff0c;根据项目情况以及版本质量可适当缩短或延长测试时间。 3、测试资源 测试任务开始前&#xff0c;…

如何在群晖NAS部署WPS容器并实现无公网IP远程访问本地office软件

文章目录 1. 拉取WPS Office镜像2. 运行WPS Office镜像容器3. 本地访问WPS Office4. 群晖安装Cpolar5. 配置WPS Office远程地址6. 远程访问WPS Office小结 7. 固定公网地址 wps-office是一个在Linux服务器上部署WPS Office的镜像。它基于WPS Office的Linux版本&#xff0c;通过…

案例分析篇09:Web架构设计相关20个考点(7~11)(2024年软考高级系统架构设计师冲刺知识点总结)

专栏系列文章推荐: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例分析篇-…

TimescaleDB 安装部署

文章目录 1.Yum安装TimescaleDB1.1.安装PostgreSQL1.2.安装Timescaledb插件1.3.创建Timescaledb扩展 2.Docker安装Timescaledb 开源中间件 # TimescaleDBhttps://iothub.org.cn/docs/middleware/ https://iothub.org.cn/docs/middleware/timescale/timescale-deploy/1.Yum安装…

Rabbit算法:轻量高效的加密利器

title: Rabbit算法&#xff1a;轻量高效的加密利器 date: 2024/3/13 18:14:31 updated: 2024/3/13 18:14:31 tags: Rabbit算法流密码高安全性高性能密钥调度加密解密抗攻击性 Rabbit算法起源&#xff1a; Rabbit算法是由Martin Boesgaard和Mette Vesterager提出的一种流密码算…

1.获取DOM对象、操作元素内容、操作元素属性、自定义属性、定时器

web Api基本认知 作用&#xff1a;通过JS去操作html页面和浏览器(实现浏览器中的某些功能) 分类&#xff1a; DOM(网页)&#xff1a;Document Object Model(文档对象模型) BOM(浏览器)&#xff1a;Borwser Object Model(浏览器对象模型) DOM DOM树 将网页中标签的关系以树状…

【考研学子必看 ★2024考研国家线及调剂策略(2)】

----------------------------------------------------------------------------------------------------- 考研复试科研背景提升班 教你快速深入了解掌握考研复试面试中的常见问题以及注意事项&#xff0c;系统的教你如何在短期内快速提升自己的专业知识水平和编程以及英语…

【性能测试】移动测试md知识总结第1篇:移动端测试课程介绍【附代码文档】

移动测试完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;移动端测试课程介绍&#xff0c;移动端测试知识概览&#xff0c;移动端测试环境搭建&#xff0c;ADB常用命令学习主要内容,学习目标,学习目标,1. window安装andorid模拟器,学习目标。主流移动端自动…

【c++修仙】c语言练气第九重动态内存管理

为什么要有动态内存 例如 int a20 char arr[10]{10}; 这些的内存是固定的 但是有时候我们需要的空间大小是在程序运行的时候才能知道的 malloc和free void* malloc (size_t size) 这个函数向内存申请一块连续可用的空间&#xff0c;并返回指向这块空间的指针。 如果开辟…

环信ChatroomUIKit功能详解——超详细介绍

聊天室是当下泛娱乐社交应用中最经典的玩法&#xff0c;通过调用环信的 IM SDK 接口&#xff0c;可以快速创建聊天室。如果想根据自己业务需求对聊天室应用的 UI界面、弹幕消息、礼物打赏系统等进行自定义设计&#xff0c;最高效的方式则是使用环信的 ChatroomUIKit 。 文档地址…

抓包工具fiddler的使用

问题查询 定位bug是前端的问题还是后端的问题&#xff1f; 1.如果抓不到请求&#xff0c;显然就是前端的问题 2.如果有请求但是没有相应&#xff0c;那就是后端的问题 3.如果有请求也有相应&#xff0c;需要查看响应信息&#xff0c;如果返回报错了&#xff0c;则需要具体分析报…

模型量化(一)—— 非对称量化、对称量化(全代码)

模型量化是一种减少深度学习模型大小和提高推理速度的技术&#xff0c;通过降低模型参数的精度&#xff08;例如&#xff0c;从32位浮点数减少到8位整数&#xff09;来实现。 量化三个好处&#xff1a; 更少的内存消耗(对于智能手机等端侧设备很重要)更少的推断时间&#xff…