【C++】set,map,multiset,multimap的介绍和使用

set、map、multiset、multimap

    • set、multiset的介绍和使用
      • 1、关联式容器
      • 2、键值对
      • 3、树形结构的关联式容器
      • 4、set
        • set的介绍
        • set的定义
        • set的使用
      • 5、multiset
        • multiset的介绍
        • multiset的使用
    • map、multimap的介绍和使用
      • 1、map的介绍
        • map的定义
        • insert插入函数
        • map的迭代器
        • find查找函数
        • erase删除函数
        • 其它函数
        • 总结
      • 2、multimap的介绍
        • multimap的使用

set、multiset的介绍和使用

1、关联式容器

先前我们已经接触过STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。那什么是关联式容器?它与序列式容器有什么区别?

关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高。

2、键值对

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量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){}
};

3、树形结构的关联式容器

根据应用场景的不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。下面依次介绍每一个容器。

4、set

set的介绍
  1. set是按照一定次序存储元素的容器
  2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
  3. 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序
  4. set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。
  5. set在底层是用红黑树实现的。

注意:

  1. 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。
  2. set中插入元素时,只需要插入value即可,不需要构造键值对。
  3. set中的元素不可以重复(因此可以使用set进行去重)。
  4. 使用set的迭代器遍历set中的元素,可以得到有序序列
  5. set中的元素默认按照小于来比较
  6. set中查找某个元素,时间复杂度为:logN
  7. set中的元素不允许修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
  8. set中的底层使用二叉搜索树(红黑树)来实现。
set的定义
  • 构造空的set
set<int> s1;
  • set的拷贝构造
set<int> s2(s1);
  • 用[first, last)迭代器区间中的元素构造set
string s("hello world");
set<char> s3(s.begin(), s.end());
  • 构造一个指定为大于的比较方式
set<int, greater<int>> s4;
set的使用

1、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中存放元素的类型,实际在底层存储<value, value>的键值对

  • Compare:set中元素默认按照小于来比较

  • Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

2、set的迭代器

函数声明功能介绍
begin返回set中起始位置元素的迭代器
end返回set中最后一个元素后面的迭代器
cbegin返回set中起始位置元素的const迭代器
cend返回set中最后一个元素后面的const迭代器
rbegin返回set第一个元素的反向迭代器,即end
rend返回set最后一个元素下一个位置的反向迭代器,即begin
crbegin返回set第一个元素的反向const迭代器,即cend
crend返回set最后一个元素下一个位置的反向const迭代器,即cbegin

3、set的容量

函数声明功能介绍
bool empty ( ) const检测set是否为空,空返回true,否则返回false
size_type size() const返回set中有效元素的个数

4、set的修改操作

函数声明功能介绍
insert在set中插入元素x,实际插入的是<x, x>构成的键值对,如果插入成功,返回<该元素在set中的位置,true>,如果插入失败,说明x在set中已经存在,返回<x在set中的位置,false>
void erase ( iterator position )删除set中position位置上的元素
size_type erase ( const key_type& x )删除set中值为x的元素,返回删除的元素的个数
void erase ( iterator first, iterator last )删除set中[first, last)区间中的元素
swap交换set中的元素
clear将set中的元素清空
find返回set中值为val的元素的位置
count值为val的元素存在则返回1,不存在则返回0
lower_bound返回 >= val 的迭代器位置
upper_bound返回 > val 的迭代器位置
  • 示例如下:

迭代器 + insert

void test_set1()
{set<int> s;s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(1);s.insert(3);s.insert(3);set<int>::iterator it = s.begin();while (it != s.end()){//有序+去重//*it = 10; err不允许修改cout << *it << " ";//1 2 3 4 5it++;}cout << endl;//范围forfor (auto e : s){cout << e << " "; //1 2 3 4 5}
}

find + erase + count

void test_set2()
{set<int> s;s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(3);cout << s.erase(3) << endl;//1cout << s.erase(30) << endl;//0for (auto e : s){cout << e << " "; //1 2 4 5}cout << endl;set<int>::iterator pos = s.find(3);if (pos != s.end())s.erase(pos);for (auto e : s){cout << e << " "; //1 2 4 5}if (s.find(4) != s.end()){cout << "4存在" << endl;//4存在}if (s.count(4))//相较于find更加方便{cout << "4存在" << endl;//4存在}
}

lower_bound

void test_set3()
{set<int> s;s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(3);s.insert(7);s.insert(9);for (auto e : s)cout << e << " ";//1 2 3 4 5 7 9cout << endl;//lower_bound返回 >= val的位置迭代器set<int>::iterator lowIt = s.lower_bound(3);cout << *lowIt << endl;//3lowIt = s.lower_bound(6);cout << *lowIt << endl;//7//要求删除 >= x 的所有值int x;cin >> x;//6lowIt = s.lower_bound(x);s.erase(lowIt, s.end());for (auto e : s)cout << e << " ";//1 2 3 4 5
}

upper_bound

void test_set4()
{set<int> s;s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(3);s.insert(7);s.insert(9);for (auto e : s)cout << e << " ";//1 2 3 4 5 7 9cout << endl;//upper_bound返回 > val的位置迭代器set<int>::iterator upIt = s.upper_bound(5);//存在cout << *upIt << endl;//7upIt = s.upper_bound(6);//不存在cout << *upIt << endl;//7//删除 x <= val <= y的区间的值int x, y;cin >> x >> y;//x = 3, y = 7auto leftIt = s.lower_bound(x);auto rightIt = s.upper_bound(y);s.erase(leftIt, rightIt);for (auto e : s)cout << e << " ";//1 2 9cout << endl;
}

5、multiset

multiset的介绍
  1. multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
  2. 在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或删除。
  3. 在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。
  4. multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列。
  5. multiset底层结构为二叉搜索树(红黑树)。

注意:

  1. multiset中再底层中存储的是<value, value>的键值对
  2. mtltiset的插入接口中只需要插入即可
  3. 与set的区别是,multiset中的元素可以重复,set是中value是唯一的
  4. 使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
  5. multiset中的元素不能修改
  6. 在multiset中找某个元素,时间复杂度为O(logN)
  7. multiset的作用:可以对元素进行排序
multiset的使用

multiset和set的接口近乎一致,唯一不同于set的在于multiset允许键值冗余:

void test_set1()
{multiset<int> s;s.insert(4);s.insert(5);s.insert(2);s.insert(1);s.insert(1);s.insert(3);s.insert(3);set<int>::iterator it = s.begin();while (it != s.end()){//排序cout << *it << " ";//1 1 2 3 3 4 5it++;}
}

正是multiset允许了键值冗余,所以multiset的两个函数接口find和count与set的也是有区别的:

成员函数count功能说明
set对象值为val的元素存在则返回1,不存在则返回0
multiset对象返回set中值为x的元素的个数
成员函数find功能说明
set对象返回值为val的元素的迭代器位置
multiset对象返回底层搜索树中序的第一个值为val的元素的迭代器

示例:

void test_set2()
{multiset<int> multiset;multiset.insert(4);multiset.insert(5);multiset.insert(2);multiset.insert(1);multiset.insert(1);multiset.insert(3);multiset.insert(3);multiset.insert(3);//1 1 2 3 3 3 4 5set<int> set(multiset.begin(), multiset.end());cout << multiset.count(1) << endl;//2 返回1的个数cout << set.count(1) << endl;//1 返回一个bool值,存在返回1cout << multiset.erase(1) << endl;//2 返回删除的1的个数cout << set.erase(1) << endl;//1 返回一个bool值,存在删除的值返回1auto pos1 = multiset.find(3); //返回中序的第一个3的迭代器while (pos1 != multiset.end()){cout << *pos1 << " ";//3 3 3 4 5pos1++;}
}

map、multimap的介绍和使用

1、map的介绍

  1. map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
  2. 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair:typedef pair<const key, T> value_type;
  3. 在内部,map中的元素总是按照键值key进行比较排序的。
  4. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  5. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
  6. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。
template<class Key,                                     //map::Key_typeclass T,                                       //map::mapped_typeclass Compare = less<Key>,                     //map::Key_compareclass Alloc = allocator<pair<const Key,T>      //map::allocator_type>class map;
  • key: 键值对中key的类型
  • T: 键值对中value的类型
  • Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
  • Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

注意:在使用map时,需要包含头文件。

map的定义
  • 指定key和value构造一个空map
map<int, string> m1;
  • 拷贝构造同类型map
map<int, string> m2(m1);
  • 使用迭代器区间构造一块内容
map<int, string> m3(m2.begin(), m2.end());
  • 构造一个指定大于的比较方式的map
map<int, string, greater<int>> m4;
insert插入函数
  • insert函数声明:
pair<iterator,bool> insert (const value_type& x );

接口说明:
在map中插入键值对x,注意x是一个键值对,返回值也是键值对:iterator代表新插入元素的位置,bool代表释放插入成功。x的类型为value_type,而value_type即pair的别名:

typedef pair<const Key, T> value_type;
  • 解释键值对:

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量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){}
};

因此,后续在使用insert时,首先用key和value构造一个pair对象,再把pair对象作为参数传入insert函数。

  • 插入方式如下:

1、借助pair构造函数:

void test_map1()
{map<string, string> dict;pair<string, string> kv("byte", "字节");dict.insert(kv);
}

2、借助pair构造匿名对象插入:

void test_map1()
{map<string, string> dict;dict.insert(pair<string, string>("sort", "排序"));
}

3、调用make_pair函数模板插入:

void test_map1()
{map<string, string> dict;dict.insert(make_pair("left", "左边"));//make_pair是库里的,不需要自己写
}

库里的make_pair源码如下:

template <class T1, class T2>
pair<T1, T2> make_pair(T1 x, T2 y)
{return (pair<T1, T2>(x, y));
}

4、使用{}

 
void test_map1()
{map<string, string> dict;dict.insert({ "right", "右边" });//C++11支持的写法,后续详谈
}
  • insert函数返回值说明:
pair<iterator,bool> insert (const value_type& val);

insert函数的返回值是一个pair对象,该pair对象中第一个成员的类型(pair::first)为指向新插入元素的迭代器或者没有插入成功(数据冗余),返回指向跟key相等的位置结点的迭代器,第二个成员的类型为一个bool类型,具体含义如下:

  • 若待插入元素的键值key在map当中不存在,则insert函数插入成功,并返回插入后元素的迭代器和true。
  • 若待插入元素的键值key在map当中已经存在,则insert函数插入失败,并返回map当中键值为key的元素的迭代器和false。

示例:

void test()
{map<string, string> dict;auto ret1 = dict.insert(make_pair("left", "左边"));auto ret2 = dict.insert(make_pair("left", "剩余"));
}
map的迭代器
函数声明功能介绍
begin()和end()begin返回一个指向map第一个元素的迭代器,end返回指向末尾的迭代器
cbrgin()和cend()cbegin返回指向map中第一个元素的const迭代器,cend返回指向末尾的常量迭代器
rbegin()和rend()rbegin返回指向末尾的反向迭代器,rend返回指向起点的反向迭代器
crbegin()和crend()与rbegin和rend位置相同,操作相同,但crbegin和crend所指向的元素不能修改

接下来即可对map进行遍历操作:

void test_map2()
{//插入map<string, string> dict;dict.insert(make_pair("left", "左"));dict.insert(make_pair("right", "右"));dict.insert(make_pair("front", "前"));dict.insert(make_pair("back", "后"));//遍历map<string, string>::iterator it = dict.begin();while (it != dict.end()){//cout << (*it).first << ":" << (*it).second << endl;cout << it->first << ":" << it->second << endl;it++;}cout << endl;//范围forfor (const auto& e : dict)cout << e.first << ":" << e.second << endl;
}
  • 实例:统计各水果出现的次数
void test_map3()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> countMap;for (auto& str : arr){map<string, int>::iterator it = countMap.find(str);if (it != countMap.end()){it->second++;}else{countMap.insert(make_pair(str, 1));}}for (const auto& kv : countMap)cout << kv.first << ":" << kv.second << endl;
}

根据insert的特性,我们可以针对其进行优化:

void test_map3()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
//优化1:/*map<string, int> countMap;for (auto& str : arr){//pair<map<string, int>::iterator, bool> ret = countMap.insert(make_pair(str, 1));auto ret = countMap.insert(make_pair(str, 1));if (ret.second == false){ret.first->second++;}}*///优化2:map<string, int> countMap;for (auto& str : arr){countMap[str]++;}for (const auto& kv : countMap)cout << kv.first << ":" << kv.second << endl;
}

这里优化2的方式仅仅用了[]的运算符重载即可完成,接下来详细讲解[]运算符重载

  • [ ]运算符重载函数原型声明:
mapped_type& operator[] (const key_type& k);
  • 针对返回类型mapped_type 和 参数类型key_type的定义如下:
成员类型定义
key_typeThe first template parameter (Key)
mapped_typeThe second template parameter (T)
  • [ ]运算符重载函数的具体源码实现如下:
mapped_type& operator[] (const key_type& k)
{return (*((this->insert(make_pair(k, mapped_type()))).first)).second;
}

针对该返回值,其主要是进行了两大步骤:

  1. 首先调用insert函数插入键值对返回迭代器ret
  2. 通过返回的迭代器ret调用元素值value

对应代码如下:

mapped_type& operator[] (const key_type& k)
{//1、调用insert返回迭代器区间pair<iterator, bool> ret = insert(make_pair(k, mapped_type()));//2、利用ret调用value值return ret.first->second;//return (*(ret.first)).second;
}

前面我们已知mapped_type为第二个模板参数,也就是value,而mapped_type()就是构造了一个匿名对象,接下来主要分两种情况讨论:

  1. 如果k在map对象中,则插入失败,返回的bool类型为false,返回的迭代器为k所在结点的迭代器,而迭代器解引用*(ret.first)获得的就是pair,最后再通过pair访问到value值,整体可优化成ret.first->second,这里返回引用的好处为查找k对应v,修改k对应v。
  2. 如果k不在map对象中,则插入成功,返回的bool类型为true,返回的迭代器为新插入的k所在结点的迭代器位置,接着调用ret.first获得pair的迭代器,再通过->second获得value,这里返回引用的好处为插入和修改。

接下来回头看看前面统计水果出现次数的代码:

void test_map3()
{string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };map<string, int> countMap;for (auto& str : arr){countMap[str]++;}for (const auto& kv : countMap)cout << kv.first << ":" << kv.second << endl;
}

这里就很容易感悟到这里仅仅一行代码完成了主要逻辑,归根揭底在于[ ]运算符重载内部封装了一层insert,这样满足了遇到不同的key值就插入,对应的value更新为1,若遇到相同的key值就查找,对应的value累计++从而统计次数,而这又归功于[ ]运算符重载内部返回引用的缘故。

这里再给出一组[ ]的例子:

void test()
{map<string, string> dict;auto ret1 = dict.insert(make_pair("left", "左边"));auto ret2 = dict.insert(make_pair("left", "剩余"));dict["operator"] = "重载";//插入 + 修改dict["left"] = "左边、剩余";//修改dict["erase"];//插入cout << dict["left"] << endl;//左边、剩余
}

这里就足矣体现出[ ]运算符重载的好处,既可以遇到新key像insert一样插入,又满足了insert未有的功能,查找并修改。

find查找函数
  • 函数原型如下:
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;
  • 原理如下:

根据k值在map中寻找,找到后,返回对应k值位置的迭代器,若未找到,则返回map::end的迭代器。

  • 示例:
void test_map()
{map<string, string> dict;dict.insert(make_pair("left", "左"));dict.insert(make_pair("right", "右"));dict.insert(make_pair("front", "前"));dict.insert(make_pair("back", "后"));string str;cin >> str;//输入leftmap<string, string>::iterator pos = dict.find(str);if (pos != dict.end()){cout << pos->first << " : " << pos->second << endl;//left : 左}else{cout << "没找到" << endl;}
}
erase删除函数

函数原型声明如下:

(1)	void erase (iterator position);
(2)	size_type erase (const key_type& k);
(3) void erase (iterator first, iterator last);

这里和set中的erase原理相册不大,下面直接给出测试用例:

void test_map()
{map<int, string> m;m.insert(make_pair(1, "one"));m.insert(make_pair(2, "two"));m.insert(make_pair(3, "three"));m.insert(make_pair(4, "four"));m.insert(make_pair(5, "five"));m.insert(make_pair(6, "six"));//指定key值删除cout << m.erase(3) << endl;map<int, string>::iterator pos = m.find(5);//删除迭代器区间if (pos != m.end()){m.erase(pos, m.end());//删除5到6的数字}for (const auto& kv : m){cout << kv.first << ":" << kv.second << endl;}
}
其它函数
  • 1、map的容量与元素访问
函数声明功能介绍
empty检测map中的元素是否为空,是返回true,否则返回false
size返回map中有效元素的个数
  • 2、map中元素的修改
函数声明功能介绍
swap交换两个map中的元素
clear清空map中的元素
count返回key为x的键值在map中的个数,注意map中key是唯一的,因此该函数的返回值要么为0,要么为1,因此也可以用该函数来检测一个key是否在map中
总结
  1. map中的的元素是键值对
  2. map中的key是唯一的,并且不能修改
  3. 默认按照小于的方式对key进行比较
  4. map中的元素如果用迭代器去遍历,可以得到一个有序的序列
  5. map的底层为平衡搜索树(红黑树),查找效率比较高O(logN)
  6. 支持[]操作符,operator[]中实际进行插入查找。

2、multimap的介绍

  1. Multimap是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key,value>,其中多个键值对之间的key是可以重复的。
  2. 在multimap中,通常按照key排序和惟一地标识元素,而映射的value存储与key关联的内容。key和value的类型可能不同,通过multimap内部的成员类型value_type组合在一起,value_type是组合key和value的键值对:typedef pair<const Key, T> value_type;
  3. 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序的。
  4. multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍历multimap中的元素可以得到关于key有序的序列。
  5. multimap在底层用二叉搜索树(红黑树)来实现。

注意:multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的。

multimap的使用

multimap中的接口可以参考map,功能都是类似的。

注意:

  • multimap中的key是可以重复的。
  • 2、multimap中的元素默认将key按照小于来比较
  • 3、multimap中没有重载operator[]操作(因为multimap允许冗余,导致key和value面临一对多的关系)
  • 4、使用时与map包含的头文件相同

示例:

void test_multimap()
{multimap<string, string> dict;dict.insert(make_pair("left", "左边"));dict.insert(make_pair("left", "剩余"));dict.insert(make_pair("left", "左边"));
}

通过监视窗口可以看到:
在这里插入图片描述

multimap允许冗余,这也就导致其内部的find和count函数和map中的有所区别,如下:

成员函数count功能介绍
map对象值为key的元素存在则返回1,不存在则返回0
multimap对象返回set中值为key的元素的个数
成员函数find功能介绍
map对象返回键值为key的元素的迭代器位置
multimap对象返回底层搜索树中序的第一个值为key的元素的迭代器

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

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

相关文章

Midjourney基础命令和提示词

1 基础命令 1.1 /imagine prompt 生成图片的核心命令&#xff0c;prompt 后输入描述。 /imagine prompt: A majestic dragon flying over a misty mountain, cinematic lighting, 4K resolution 高级提示 1.1.1 基本参数 图片比例 --ar 图片比例 混乱 Aspect Ratios --…

【代码pycharm】动手学深度学习v2-04 数据操作 + 数据预处理

数据操作 数据预处理 1.数据操作运行结果 2.数据预处理实现运行结果 第四课链接 1.数据操作 import torch # 张量的创建 x1 torch.arange(12) print(1.有12个元素的张量&#xff1a;\n,x1) print(2.张量的形状&#xff1a;\n,x1.shape) print(3.张量中元素的总数&#xff1…

智云-一个抓取web流量的轻量级蜜罐v1.5

智云-一个抓取web流量的轻量级蜜罐v1.5 github地址 https://github.com/xiaoxiaoranxxx/POT-ZHIYUN 新增功能-自定义漏洞信息 可通过正则来添加相关路由以及响应来伪造 nacos的版本响应如下 日流量态势 月流量态势 抓取流量效果

【Android原生问题分析】夸克、抖音划动无响应问题【Android14】

1 问题描述 偶现问题&#xff0c;用户打开夸克、抖音后&#xff0c;在界面上划动无响应&#xff0c;但是没有ANR。回到Launcher后再次打开夸克/抖音&#xff0c;发现App的界面发生了变化&#xff0c;但是仍然是划不动的。 2 log初分析 复现问题附近的log为&#xff1a; 用户…

2024年11月16日 星期六 重新整理Go技术

今日格言 坚持每天进步一点点~ 一个人也可以是一个团队~ 学习全栈开发, 做自己喜欢的产品~~ 简介 大家好, 我是张大鹏, 今天是2024年11月16日星期六, 很高兴在这里给大家分享技术. 今天又是休息的一天, 做了很多的思考, 整理了自己掌握的技术, 比如Java, Python, Golang,…

go-zero(一) 介绍和使用

go-zero 介绍和使用 一、什么是 go-zero&#xff1f; go-zero 是一个基于 Go 语言的微服务框架&#xff0c;提供了高效、简单并易于扩展的 API 设计和开发模式。它主要目的是为开发者提供一种简单的方式来构建和管理云原生应用。 1.go-zero 的核心特性 高性能&#xff1a; g…

VUE+SPRINGBOOT实现邮箱注册、重置密码、登录功能

随着互联网的发展&#xff0c;网站用户的管理、触达、消息通知成为一个网站设计是否合理的重要标志。目前主流互联网公司都支持手机验证码注册、登录。但是手机短信作为服务端网站是需要付出运营商通信成本的&#xff0c;而邮箱的注册、登录、重置密码&#xff0c;无疑成为了这…

多目标优化算法:多目标蛇鹫优化算法(MOSBOA)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6,提供完整MATLAB代码

一、蛇鹫优化算法 蛇鹫优化算法&#xff08;Secretary Bird Optimization Algorithm&#xff0c;简称SBOA&#xff09;由Youfa Fu等人于2024年4月发表在《Artificial Intelligence Review》期刊上的一种新型的元启发式算法。该算法旨在解决复杂工程优化问题&#xff0c;特别是…

2024-11-15 Java开发工程师 内推

Java开发工程师 坐标&#xff1a;大连 岗位要求&#xff1a; 1、本科以上学历&#xff0c;计算机相关专业 2、22/23/24届毕业生 小结&#xff1a;有意向的私信发简历

Python绘制雪花

文章目录 系列目录写在前面技术需求完整代码代码分析1. 代码初始化部分分析2. 雪花绘制核心逻辑分析3. 窗口保持部分分析4. 美学与几何特点总结 写在后面 系列目录 序号直达链接爱心系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4…

当 docker-compose.yaml 文件部署时,Dify 线上版本升级过程

如果线上 Dify 是通过 docker-compose.yaml 文件部署的&#xff0c;那么当 Dify 版本升级时该如何操作呢&#xff1f;官方已经给出了 Docker compose 和 Source Code 两种方式。相对而言&#xff0c;前者更简单些&#xff0c;至少不需要安装依赖包和迁移数据库文件。为了更加具…

RHCSA学习超详细知识点2命令篇

输入命令行的语法 终端中执行命令需要遵照一定的语法&#xff0c;输入命令的格式如下&#xff1a; 命令 参数命令 -选项 参数 输入命令时可以包含多个选项&#xff0c;假如一个命令有-a,-b,-c,-d四个选项&#xff0c;可以写作 命令 -a -b -c -d 参数 这里的多个选项可以“提…

小米路由器用外网域名访问管理界面

本文在Redmi AX3000 (RA81)设置&#xff0c;其他型号路由器的管理界面端口可能各不相同。 开始之前需要保证路由器SSH功能正常&#xff0c;如果没有SSH可以参考这里。 1. 给WAN口开放80端口 可以通过下载mixbox的firewall插件或者其他防火墙插件开放端口。 2. 把域名解析到路…

✅DAY27贪心算法 | 455.分发饼干 | 376. 摆动序列 | 53. 最大子序和

一、贪心算法 核心理念是每一步都做出局部最优选择&#xff0c;以期最终得到全局最优解。它通常用于求解一些最优化问题&#xff0c;例如最小生成树、最短路径、背包问题等。 二、贪心算法的步骤 1. 定义选择标准&#xff1a;确定每一步如何选择当前最优解。 2. 验证贪心策…

无人机+无人车+机器狗:城市巷战突破技术详解

在城市巷战中&#xff0c;无人机、无人车和机器狗的组合可以形成一种全新的战场突破技术&#xff0c;这种组合能够大幅提升作战效率&#xff0c;减少人员伤亡。以下是对这一技术的详细解析&#xff1a; 一、无人机的作用 1.空中侦察&#xff1a;无人机能够提供高空视角&#x…

智慧环保之环境网格化监测解决方案

1. 引言 智慧环保网格化监测解决方案&#xff0c;旨在通过先进的信息技术手段&#xff0c;实现环境质量的全面、精准、实时监测&#xff0c;为环境治理提供科学依据和决策支持。 2. 背景与挑战 当前&#xff0c;环境污染问题日益严峻&#xff0c;治理难度不断加大。传统监测手…

vue2+3 —— Day5/6

自定义指令 自定义指令 需求&#xff1a;当页面加载时&#xff0c;让元素获取焦点&#xff08;一进页面&#xff0c;输入框就获取焦点&#xff09; 常规操作&#xff1a;操作dom “dom元素.focus()” 获取dom元素还要用ref 和 $refs <input ref"inp" type&quo…

2024 RISC-V 中国峰会 演讲幻灯片和视频回放 均已公开

目录 一、幻灯片地址&#xff1a; 二、演讲视频&#xff1a; 一、幻灯片地址&#xff1a; RVSC2024/slides at main cnrv/RVSC2024 GitHub 二、演讲视频&#xff1a; RISC-V国际基金会的个人空间-RISC-V国际基金会个人主页-哔哩哔哩视频 参考&#xff1a; 1、RISC-V 中…

sudu问题 --> 添加用户到系统配置文件里面

我们重新创建一个用户lisi 密码&#xff1a;lisixxxxxxxx 重新连接&#xff0c;输入用户&#xff0c;输入密码 是不行的 我们输入exit退出 打开文件 再切换身份&#xff0c;切换为超级管理员root 输入密码 再打开 我们打开后设置行号在50行左右可以看到我们的目标 我们再进行…

C++: string(二)

✨✨ 欢迎大家来到我的文章✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 分类专栏&#xff1a;c 我的主页&#xff1a;tyler s blog 文章目录 一 string的成员函数1 insert2 resize3assign4erase5replace6 find(1) find(2)rfind…