【C++】map和set的使用

news2024/10/5 13:33:58

​🌠 作者:@阿亮joy.
🎆专栏:《吃透西嘎嘎》
🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根
在这里插入图片描述

目录

    • 👉关联式容器👈
    • 👉键值对👈
    • 👉树形结构的关联式容器👈
      • set
        • 1. set 的介绍
        • 2. set 的使用
      • multiset
        • 1. multiset 的介绍
        • 2. multiset 的使用
      • map
        • 1. map 的介绍
        • 2. map 的使用
      • multimap
        • 1. multimap 的介绍
        • 2. multimap 的使用
    • 👉前K个高频单词👈
    • 👉两个数组的交集👈
    • 👉总结👈

👉关联式容器👈

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

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

👉键值对👈

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量 key 和 value,key 代表键值,value 表示与 key 对应的信息。比如:现在要建立一个英汉互译的字典,那该字典中必然有英文单词与其对应的中文含义,而且,英文单词与其中文含义是一一对应的关系,即通过该应该单词,在词典中就可以找到与其对应的中文含义。

SCI - 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)
	{}
};

👉树形结构的关联式容器👈

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

set

1. 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 中查找某个元素,时间复杂度为 l o g 2 N log_2 N log2N

2. set 的使用

  1. set 的模板参数列表

在这里插入图片描述
T:set 中存放元素的类型,实际在底层存储 <value, value> 的键值对。
Compare:set 中元素默认按照小于来比较,即中序遍历的结果是升序(注:Compare 可以自己写一个仿函数来控制比较的方式)。
Alloc:set 中元素空间的管理方式,使用 STL 提供的空间配置器管理。

  1. set 的构造和赋值运算符重载
函数声明功能介绍
set (const Compare& comp = Compare(), const Allocator = Allocator() );构造空的 set
set (InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator() );用 [first, last) 区间中的元素构造
set (const set& x);set 的拷贝构造
set& operator= (const set& x);set 的运算符重载

注:set 的拷贝构造和赋值运算符重载,代价是比较大的!

  1. set 的修改操作
函数声明功能介绍
pair<iterator,bool> insert (const value_type& x )在 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) 区间中的元素
void swap (set<Key,Compare,Allocator>&st );交换 set 中的元素,通过交换根节点就可以实现了。
void clear ( )将 set 中的元素清空
iterator find ( const key_type& x ) const返回 set 中值为 x 的元素的位置
size_type count ( constkey_type& x ) const返回 set 中值为 x 的元素的个数,可以通过该接口判断 x 在不在

注:set 中的元素不允许修改,因为修改元素可能会破坏二叉搜索树的结构。

在这里插入图片描述

  1. set 的使用举例
void SetTest1()
{
	// 排序+去重
	set<int> s = { 1, 2,1,6,3, 8,5,9 };	// C++11的列表初始化
	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

在这里插入图片描述

void SetTest2()
{
	// greater的该文件是functional
	set<int, greater<int>> s = { 1, 2,1,6,3, 8,5,9 };	// C++11的列表初始化
	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

在这里插入图片描述

void SetTest3()
{
	int arr[] = { 1,2,1,6,3,8,5,9 };
	// 迭代器区间初始化
	set<int, greater<int>> s(arr, arr + sizeof(arr) / sizeof(arr[0]));	
	
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;

	s.erase(3);
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;

	auto it = s.find(2);
	if (it != s.end())
	{
		s.erase(it);
		for (auto e : s)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

在这里插入图片描述
注:find 函数如果没有找到指定的 key 值,会返回 end();如果找到了,会返回该 key 值的迭代器位置。所以如果要通过迭代器位置来删除元素,需要判断该迭代器位置是否为 end()。而通过 key 值来删除的话,容器中没有指定 key 值的话,就返回 0;如果有的话,就返回 1。(注:这里的 0 和 1 是 key 值在容器 set 中的个数)

void SetTest4()
{
	set<int> myset;
	set<int>::iterator itlow, itup;

	for (int i = 1; i < 10; i++) 
		myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90

	itlow = myset.lower_bound(30);	// 返回大于等于val的第一个元素的迭代器位置     
	itup = myset.upper_bound(60);   // 返回大于val的第一个元素的迭代器位置

	myset.erase(itlow, itup);                     // 10 20 70 80 90

	std::cout << "myset contains:";
	for (auto it = myset.begin(); it != myset.end(); ++it)
		std::cout << ' ' << *it;
	cout << endl;
}

在这里插入图片描述

void SetTest5()
{
	std::set<int> myset;

	for (int i = 1; i <= 5; i++) myset.insert(i * 10);   // myset: 10 20 30 40 50

	std::pair<std::set<int>::const_iterator, std::set<int>::const_iterator> ret;
	// equal_range的返回值是键值对pair<iterator,iterator>
	ret = myset.equal_range(30);  // x <= val < y

	std::cout << "the lower bound points to: " << *ret.first << '\n';
	std::cout << "the upper bound points to: " << *ret.second << '\n';
}

在这里插入图片描述

multiset

1. 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 ( l o g 2 N ) O(log_2 N) O(log2N)
  7. multiset 的作用是可以对元素进行排序。

2. multiset 的使用

void MultisetTest1()
{
	int arr[] = { 1, 2,1,8,5,7,6,2,9 };
	multiset<int> s(arr, arr + sizeof(arr) / sizeof(arr[0]));

	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << s.count(1) << endl;

	auto pos = s.find(2);
	while (pos != s.end())
	{
		cout << *pos << " ";
		++pos;
	}
	cout << endl;

	s.erase(2);
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

注:find 返回的是中序遍历中第一个 key 值的迭代器位置,通过 key 值来调用 erase 函数是会删除所有的 key 值的。

map

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 通常被实现为二叉搜索树(更准确地说,是平衡二叉搜索树(红黑树))。

2. map 的使用

  1. map 的模板参数说明

在这里插入图片描述
key:键值对中 key 的类型

T:键值对中 value 的类型

Compare:比较器的类型,map 中的元素是按照 key 来比较的,缺省情况下按照小于来比较。一般情况下,该参数(内置类型)不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)。

Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器。

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

map 的修改操作和 set 的修改操作基本是相同的,就是 map 比 set 多了一个 value 值。

在这里插入图片描述
注:make_pair 是一个函数模板,其通常被定义成内联函数,其头文件是 utility,通过会被间接包含。

void MapTest1()
{
	map<string, string> dict;
	// 有名对象
	pair<string, string> kv1("sort", "排序");
	dict.insert(kv1);
	// 匿名对象
	dict.insert(pair<string, string>("test", "测试"));
	dict.insert(pair<string, string>("sort", "排序"));
	dict.insert(pair<string, string>("string", "字符串"));

	typedef pair<string, string> DictKV;
	dict.insert(DictKV("left", "左边"));
	dict.insert(make_pair("left", "剩下"));	// make_pair是个函数模板

	//map<string, string>::iterator it = dict.begin();
	auto it = dict.begin();
	while (it != dict.end())
	{
		//cout << (*it).first << ":" << (*it).second << endl;
		// operator->返回的是结构的指针,再加上一个->就是结构中的数据
		// 为了可读性,编译器省略了一个->
		cout << it->first << ":" << it->second << endl;
		++it;
	}
	cout << endl;

	for (auto& kv : dict)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << endl;
}

注:map 的 operator* 返回的是结构体 pair。

在这里插入图片描述
注:map 和 set 的迭代器都是双向迭代器!!!

统计出现次数

void MapTest2()
{
	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 (auto& kv : countMap)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << endl;
}

在这里插入图片描述

在这里插入图片描述

void MapTest3()
{
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
	map<string, int> countMap;
	for (auto& str : arr)
	{
		// 1. str不在countMap中,插入pair(str, int()),再对value的引用进行++
		// 2. str在countMap中,对value的引用进行++
		++countMap[str];
	}

	for (auto& kv : countMap)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << endl;
}

multimap

1. 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 是可以重复的。

2. multimap 的使用

multimap 中没有重载[],原因是 multimap 允许键值冗余。当有多个相同的键值时,不知道返回哪一个。

void MultimapTest()
{
	multimap<string, string> mdict;
	mdict.insert(make_pair("sort", "排序"));
	mdict.insert(make_pair("left", "左边"));
	mdict.insert(make_pair("left", "剩下"));
	mdict.insert(make_pair("string", "字符串"));

	for (auto& kv : mdict)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	cout << endl;
}

在这里插入图片描述

👉前K个高频单词👈

给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序排序。

在这里插入图片描述

思路一:可以通过优先级队列来做,认为出现次数多的单词优先级高。如果出现次数相同,则在字典顺序靠前的优先级高。根据优先级比较的规则,我们自己实现一个仿函数即可。

class Solution 
{
    struct Less
    {
        bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2) const
        {
            if(kv1.second < kv2.second)
                return true;
            else if(kv1.second == kv2.second && kv1.first > kv2.first)
                return true;
            else
                return false;
        }
    };
public:
    vector<string> topKFrequent(vector<string>& words, int k) 
    {
        // 统计出现的次数
        map<string, int> countMap;
        for(auto& str : words)
        {
            ++countMap[str];
        }
        // TOPK问题
        priority_queue<pair<string, int>, vector<pair<string, int>>, Less> mh(countMap.begin(), countMap.end());

        vector<string> v;
        while(k--)
        {
            v.push_back(mh.top().first);
            mh.pop();
        }
        return v;
    }
};

在这里插入图片描述

思路二:因为countMap中已经按照字典顺序排序了,所以我们可以采用稳定的排序对countMap中的元素按照出现次数来排序就行了。sort 底层是一个快排,快排是不稳定排序,那么我们可以给 sort 传一个比较方式,就可以保证稳定性了。注:sort 要求传入的迭代器是随机迭代器,而 map 的迭代器是双向迭代器。那我们可以先将 map 的元素存储 vector 中。

class Solution 
{
    struct Greater
    {
        bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2) const
        {
            if(kv1.second > kv2.second)
                return true;
            else if(kv1.second == kv2.second && kv1.first < kv2.first)
                return true;
            else
                return false;
        }
    };
public:
    vector<string> topKFrequent(vector<string>& words, int k) 
    {
        // 统计出现的次数
        map<string, int> countMap;
        for(auto& str : words)
        {
            ++countMap[str];
        }

        vector<pair<string, int>> sortV(countMap.begin(), countMap.end());  
        sort(sortV.begin(), sortV.end(), Greater());

        vector<string> v;
        for(size_t i = 0; i < k; ++i)
        {
            v.push_back(sortV[i].first);
        }
        return v;
    }
};

在这里插入图片描述
上面的解法是通过比较方式来控制稳定性的。那么我们也可以使用库里提供的稳定排序stable_sort来控制稳定性。

class Solution 
{
    struct Greater
    {
        bool operator()(const pair<string, int>& kv1, const pair<string, int>& kv2) const
        {
            if(kv1.second > kv2.second)
                return true;
            else
                return false;
        }
    };
public:
    vector<string> topKFrequent(vector<string>& words, int k) 
    {
        // 统计出现的次数
        map<string, int> countMap;
        for(auto& str : words)
        {
            ++countMap[str];
        }

        vector<pair<string, int>> sortV(countMap.begin(), countMap.end());  
        stable_sort(sortV.begin(), sortV.end(), Greater());

        vector<string> v;
        for(size_t i = 0; i < k; ++i)
        {
            v.push_back(sortV[i].first);
        }
        return v;
    }
};

在这里插入图片描述

思路三:因为countMap已经按照字典顺序排序了,那可以将其中的元素依次插入到以整型为 key 值的multimap中即可。

class Solution 
{
public:
    vector<string> topKFrequent(vector<string>& words, int k) 
    {
        // 统计出现的次数
        map<string, int> countMap;
        for(auto& str : words)
        {
            ++countMap[str];
        }
		// 传greater<int>也是为了保证稳定性
        multimap<int, string, greater<int>> sortMap;
        for(auto& str : countMap)
        {
            sortMap.insert(make_pair(str.second, str.first));
        }

        vector<string> v;
        auto it = sortMap.begin();
        for(size_t i = 0; i < k; ++i)
        {
            v.push_back(it->second);
            ++it;
        }
        return v;
    }
};

在这里插入图片描述

👉两个数组的交集👈

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序 。

在这里插入图片描述

思路:因为set容器是对元素进行排序加上去重的,所以我们可以用数组中的元素来构造set,然后再来求交集。求交集的思路:谁小谁往后走,相等就添加到vector中并同时往后走。

class Solution 
{
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
    {
        set<int> s1(nums1.begin(), nums1.end());
        set<int> s2(nums2.begin(), nums2.end());

        auto it1 = s1.begin();
        auto it2 = s2.begin();

        vector<int> v;

        while(it1 != s1.end() && it2 != s2.end())
        {
            if(*it1 < *it2)
                ++it1;
            else if(*it1 > *it2)
                ++it2;
            else
            {
                v.push_back(*it1);
                ++it1;
                ++it2;                
            }
        }

        return v;
    }
};

在这里插入图片描述
补充:求差集的思路:先用两个数组的元素构造出两个et,然后遍历set。谁小就将谁添加到vector中并且往后走,相等时就同时加加。求并集只需要将两个数组的元素插入到set中就能得到两个数组的并集了。

class Solution 
{
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
    {
        set<int> s1(nums1.begin(), nums1.end());
        set<int> s2(nums2.begin(), nums2.end());

        auto it1 = s1.begin();
        auto it2 = s2.begin();

        vector<int> v;

        while(it1 != s1.end() && it2 != s2.end())
        {
            if(*it1 < *it2)
            {
                v.push_back(*it1);
                ++it1;
            }
            else if(*it1 > *it2)
            {
                v.push_back(*it2);
                ++it2;
            }
            else
            {
                ++it1;
                ++it2;                
            }
        }

        // 后面的元素都是相差的元素
        while(it1 != s1.end())
        {
            v.push_back(*it1);
            ++it1;
        }
        while(it2 != s2.end())
        {
            v.push_back(*it2);
            ++it2;
        }

        return v;
    }
};

👉总结👈

本篇博客主要讲解了键值对、关联式容器 set、multiset、map 和 multiset 以及两道 OJ 题前 K 个高频单词和两个数组的交集等等。那么以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以点个三连支持一下!谢谢大家!💖💝❣️

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

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

相关文章

码二哥的技术专栏 总入口

已发表的技术专栏&#xff08;订阅即可观看所有专栏&#xff09; 0  grpc-go、protobuf、multus-cni 技术专栏 总入口 1  grpc-go 源码剖析与实战  文章目录 2  Protobuf介绍与实战 图文专栏  文章目录 3  multus-cni   文章目录(k8s多网络实现方案) 4  gr…

JVM整理笔记之测试工具JCStress的使用及其注解的应用

文章目录前言如何使用JCStress测试代码JCStress 注解说明前言 如果要研究高并发&#xff0c;一般会借助高并发工具来进行测试。JCStress&#xff08;Java Concurrency Stress&#xff09;它是OpenJDK中的一个高并发测试工具&#xff0c;它可以帮助我们研究在高并发场景下JVM&a…

RecyclerView 倒计时和正计时方案

本章内容一.方案制定二.设计三.编码相信不少同学都会在这里栽跟头&#xff0c;在思考这个问题设计了两套方案&#xff0c;而我的项目需求中需要根据业务是否反馈来进行倒计时和正计时的操作。一.方案制定 1.在Adapter中使用CountDownTimer 2.修改数据源更新数据 3.只修改页面展…

leetcode--各种数据结构相关的题

数据结构1.数组&#xff08;1&#xff09;找到所有数组中消失的数字(448)&#xff08;2&#xff09;旋转图像(48)&#xff08;3&#xff09;搜索二维矩阵 II(240)&#xff08;4&#xff09;最多能完成排序的块(769)2.栈和队列&#xff08;1&#xff09;用栈实现队列(232)&#…

“链引擎”(PBC)计划 | 太保集团长安链应用展示

引言 长安链“链引擎”计划&#xff08;Powered by Chainmaker&#xff09;(简称&#xff1a;PBC计划)是由长安链生态联盟发起的一项应用赋能计划&#xff0c;旨在以长安链技术体系为核心支撑&#xff0c;汇聚产业各方力量&#xff0c;为应用方提供技术、品牌、生态等支持&…

面试干货!初级软件测试面试题及答案题库一起奉上

软件测试工程师面试通常要经历技术面以及HR面&#xff0c;HR面一般都是日常问题&#xff0c;面试人可以临场发挥过去&#xff0c;但关乎岗位职责的技术面&#xff0c;可就没那么容易了&#xff0c;尤其是对于很多初次去面试测试岗位的没有任何测试岗位面试经验的转行人员&#…

Java并发面试题

基础知识 并发编程的优缺点 为什么要使用并发编程&#xff08;并发编程的优点&#xff09; 充分利用多核CPU的计算能力&#xff1a;通过并发编程的形式可以将多核CPU的计算能力发挥到极致&#xff0c;性能得到提升方便进行业务拆分&#xff0c;提升系统并发能力和性能&#…

【网络安全】内网介绍+windows信息收集(含命令)

目录 前言 一、内网渗透测试是什么&#xff1f; 1.介绍 2.内外网区别 3.工作组是什么&#xff1f; 4.域是什么&#xff1f; 5.域的知识点 6.活动目录 7.活动目录主要功能 8.域权限 二、windows信息收集 &#xff08;1&#xff09;系统信息 &#xff08;2&#xff0…

【pandas】17 数据处理和绘图

【pandas】17 数据处理和绘图 2023.1.16 pandas数据处理方法和绘图&#xff1a;读取数据、更改数据、时间数据等 主要参考&#xff1a;https://mofanpy.com/tutorials/data-manipulation/pandas/time 17.1运算方法 17.1.1 筛选赋值运算 就是用前面的方法对数据进行筛选&#…

AI中Deepfake的部分研究前沿与文献综述

AI中Deepfake的部分研究前沿与文献综述一、研究现状二、典型算法&#xff1a;三、存在问题四、未来的研究热点参考文献&#xff1a;一、研究现状 由于Deepfake其潜在的安全威胁&#xff0c;它已经引起了学术界和工业界的研究兴趣。为了减轻这种风险&#xff0c;人们提出了许多…

【Nginx01】Ngnix入门

1.版本 Nginx开源版Nginx plus商业版OpenrestyTengine 2.Nginx开源版安装 2.1下载 2.2编译安装 如果本身没有c语言的编译器 命令&#xff1a; yum install -y gcc 解压Nginx 命令&#xff1a; tar -zxvf nginx-1.22.1.tar.gz 安装perl库 命令&#xff1a; yum install -y p…

广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署”

文章目录广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署”服务 Docker 构建及部署代码支持服务打包&构建服务部署广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署” 服务 Docker 构建及部署 在 ADX 系统中&#xff0c;全链路涉及 大大小小的微服务…

SpringBoot+VUE前后端分离项目学习笔记 - 【22 权限菜单 下】

本节主要实现用户角色菜单分配功能&#xff0c;并且实现前端的动态渲染以及动态路由 数据库&#xff1a; sys_user表增加role字段; sys_role增加flag字段;sys_menu表增加page_path字段。前两者表示用户角色标识&#xff0c;后者是前端页面vue路径&#xff0c;用以实现动态路由 …

verilog学习笔记- 13)呼吸灯实验

目录 简介&#xff1a; 实验任务&#xff1a; 硬件设计&#xff1a; 程序设计&#xff1a; 下载验证&#xff1a; 简介&#xff1a; 呼吸灯采用 PWM 的方式&#xff0c;在固定的频率下&#xff0c;通过调整占空比的方式来控制 LED 灯亮度的变化。PWM即脉冲宽度调制&#x…

2021年帆软杯一等奖作品 |《基于数据可视化的中国编程岗位需求分析》

# 作品主题 #——基于数据可视化的中国编程岗位需求分析一、团队介绍 团队名称&#xff1a;汪汪队立大功 团队成员&#xff1a;乔好鑫、许春阳、窦晨辉 指导老师&#xff1a;施金妹 团队的三位成员均是来自于海南科技职业大学大数据技术与应用专业&#xff0c;专业课主修了pyt…

SpringBoot+2次MD5登录密码加密+MyBatisPlus+Thymeleaf+Bootstrap简单实现登录功能,一文轻松搞定!

这里写目录标题一、演示GIF二、开发前期准备1、数据库2、依赖POM.XML3、idea结构目录三、后端1、实体类2、mapper接口3、mapper.xml4、Servicce接口5、Impl实现6、Controller控制器7、全局异常处理类GlobalExceptionGlobalExceptionHandler8、工具类MD5UtilUUIDUtilCookieUtilV…

消息批处理端口说明

为满足用户需要对多文件做批处理的需求&#xff0c;在2022版本的知行之桥中&#xff0c;开发人员开发设计了3个新的端口&#xff0c;分别是Batch Create 端口、Batch Merge 端口和Batch Split 端口。 功能是对传入端口的消息做批处理&#xff0c;使得消息可以在批处理组中分组在…

mybatis-plus分布式id重复问题

问题起因 k8s 部署的一个服务的两个节点集群 最近频繁报错&#xff0c;数据库主键ID重复&#xff0c;导致数据插入报错 问题定位 还在定位。。。。 问题解决 解决办法主要有两个 指定mybatis-plus workerId dataCenterId 全局配置 #注意这里使用的随机策略 随机区间 …

智能边缘网关

背景介绍 调研发现&#xff0c;数字经济为工业物联网、智能交通以及智慧医疗等场景提出了新的解决方案。工程师利用传感器边缘网关云服务器的系统架构&#xff0c;通过大数据及人工智能算法进行辅助决策&#xff0c;最终为工业设备赋能&#xff0c;提高加工生产效率。近年来&am…

sqli-labs 11~14 多命通关攻略(报错注入)

sqli-labs 11~14 多命通关攻略&#xff08;报错注入&#xff09;描述判断注入类型返回结果错误输入总结符号注释判断返回结果中的列数判断返回结果中的列数为 1判断返回结果中的列数为 2报错注入通过报错注入爆破数据库中的表名通过报错注入爆破数据库中的表名&#xff08;逻辑…