【STL巨头】set、map、multiset、multimap的介绍及使用

news2024/11/29 5:45:54

set、map、multiset、multimap的介绍及使用

  • 一、关联式容器
  • 二、键值对
    • 键值对概念
    • 定义
  • 三、set
    • set的介绍
    • set的使用
      • set的模板参数列表
      • set的构造
      • set的迭代器
      • set的容量
        • empty
        • size
      • set的修改操作
        • insert
        • find && erase
        • count
        • lower_bound 和 upper_bound
    • Multiset的用法
  • 四、map
    • map的介绍
    • map的用法
      • map的模板参数
    • map迭代器
    • map的构造
    • map的常见修改操作
      • insert
      • erase
      • find
      • count
    • map的容量与元素访问 -- operator[]
    • 利用map统计出现次数
      • 用直接插入法
      • 用[]法
    • multimap
      • multimap介绍
      • multimap的使用
  • 五、题目
    • 前k个高频词
      • 题目描述
      • 解题思路
      • 解题代码
    • 两个数组的交集
      • 题目描述
      • 解题思路
      • 解题代码
      • 差集思想


一、关联式容器

初期,我们接触了list,vector,deque等容器,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。
关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高。

在这里插入图片描述

二、键值对

键值对概念

用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。

定义

SGI-STL中关于键值对pair的定义:

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

三、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中查找某个元素,时间复杂度为: l o g 2 n log_2 n log2n
7. set中的元素不允许修改(为什么?)
8. set中的底层使用二叉搜索树(红黑树)来实现。

总结:set的本质就是key模型。

set的使用

set支持的操作为增删查,不能修改!

set的模板参数列表

在这里插入图片描述
T:set中存放元素的类型,实际在底层存储的是<value, value>的键值对
Compare:仿函数,set容器中默认使用库函数中的less函数来比较,我们如果想实现More函数我们可以自己进行写一个More函数以实现不同的功能。
Alloc:set中元素空间的管理方式,使用STL提供的空间配置器。

set的构造

在这里插入图片描述

void testset1()
{
	set<int> set1;
	int num[10] = { 1,2,4,3,5,7,6,8,9,10 };

	// 区间构造
	set<int> set2(num, num + sizeof(num) / sizeof(num[0]));

	// 拷贝构造
	set<int> set3(set2);// 拷贝构造代价太大

	// for循环打印set2
	for (auto& e : set2)
	{
		cout << e << " ";
	}
	cout << endl;

	// for循环打印set3
	for (auto& e : set3)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

set的迭代器

在这里插入图片描述

如图所示:

在这里插入图片描述

void testset2()
{
	set<int> set1 = { 1,2,1,4,5,3,7,6,5,8,9 };
	set<int>::iterator it = set1.begin();
	// 去重+排序
	while (it != set1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	// 范围for
	for (auto& e : set1)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

我们如果想要将这个排序变成降序该咋办呢?很简单,用一个Greater仿函数即可:

void testset3()
{
	int a[10] = { 1,3,1,2,4,5,7,6,5,8 };
	// 这个greater仿函数是set库函数中的函数
	// 就是进行降序的函数
	set<int, greater<int>> set1(a, a + sizeof(a) / sizeof(a[0]));

	// for循环
	for (auto& e : set1)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

set的容量

empty

在这里插入图片描述

size

在这里插入图片描述

set的修改操作

insert

在这里插入图片描述
这里我们直接用cplusplus网站上的插入介绍和代码解析:

在这里插入图片描述

void testset4()
{
	std::set<int> myset;
	std::set<int>::iterator it;
	std::pair<std::set<int>::iterator, bool> ret;

	// for循环并单个插入
	for (int i = 1; i <= 5; ++i)
		myset.insert(i * 10);

	// 单个插入
	ret = myset.insert(20);

	if (ret.second == false) 
		it = ret.first;

	// 插入迭代器所代表的值
	myset.insert(it, 25);
	myset.insert(it, 24);
	myset.insert(it, 26);

	// 插入一段区间
	int myints[] = { 5,10,15 };
	myset.insert(myints, myints + 3);

	std::cout << "myset contains:";
	for (it = myset.begin(); it != myset.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';
}
find && erase

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

void testset5()
{
	std::set<int> myset;
	std::set<int>::iterator it;

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

	it = myset.begin();
	++it; // 第二个位置

	// 删除第二个位置
	myset.erase(it);

	// 删除一个数
	myset.erase(40);

	// 删除一个迭代器区间
	it = myset.find(60);
	myset.erase(it, myset.end());

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

在这里插入图片描述

上面是erase,我们下面介绍一下find:
在这里插入图片描述
在这里插入图片描述

void testset6()
{
	std::set<int> myset;
	std::set<int>::iterator it;

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

	it = myset.find(20);
	myset.erase(it); // 删除20这个迭代器的值
	myset.erase(myset.find(40)); // 删除40这个迭代器的值

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

在这里插入图片描述

看似没什么问题,有一个问题,那我们假如说删除了一个并不存在的数值或者是迭代器呢?
在这里插入图片描述
所以我们在写完find以后需要判断一下是否是真的找到了,找到了才能删除,找不到就不删除即可。

	// 删除一个不存在的迭代器
	set<int>::iterator pos = myset.find(70);
	if (pos != myset.end())
	{
		myset.erase(pos);
	}
count

在这里插入图片描述

在这里插入图片描述

lower_bound 和 upper_bound

在这里插入图片描述

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

	for (int i = 1; i < 10; ++i)
	{
		myset.insert(i * 10);
	}

	itlow = myset.lower_bound(35);
	itup = myset.upper_bound(60);
	cout << "[" << *itlow << "," << *itup << "]" << endl;

	myset.erase(itlow, itup);

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

在这里插入图片描述

Multiset的用法

multiset的用法和set基本是一致的,唯一一个区别是multiset允许键值对冗余,即使用multiset可以让数字重复。

void testset10()
{
	// multiset
	int a[10] = {1,3,2,4,1,2,5,6,7,10};
	multiset<int> set1(a, a + sizeof(a) / sizeof(a[0]));
	for (auto& e : set1)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

还有一个find和erase呢?
find是返回中序中的第一个(在有多个重复值的情况下)。
在这里插入图片描述

erase是将所有的想删除的值全部删掉。

四、map

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

map的用法

map的模板参数

在这里插入图片描述

key: 键值对中key的类型
T: 键值对中value的类型
Compare: 比较器的类型,map中的元素是按照key来比较的,缺省情况下按照小于来比较,一般情况下(内置类型元素)该参数不需要传递,如果无法比较时(自定义类型),需要用户自己显式传递比较规则(一般情况下按照函数指针或者仿函数来传递)
Alloc:通过空间配置器来申请底层空间,不需要用户传递,除非用户不想使用标准库提供的空间配置器

map迭代器

在这里插入图片描述

void testmap1()
{
	map<string, string> map1;
	map1.insert(make_pair("banana", "香蕉"));
	map1.insert(make_pair("apple", "苹果"));
	map1.insert(make_pair("orange", "橙子"));
	map<string, string>::iterator it = map1.begin();
	while (it != map1.end())
	{
		cout << it->first << it->second << endl;
		++it;
	}
}

在这里插入图片描述

map的构造

在这里插入图片描述

void testmap2()
{
	map<int, int> map1; // 空的构造
	int a[] = { 1,2,3,4,5,6,7,8,88,9,10 };
	for (auto& e : a)
	{
		map1.insert(make_pair(e, e));
	}
	map<int, int> map2(map1.begin(), map1.end()); // 迭代器区间构造
	map<int, int> map3(map2); // 拷贝构造

	for (auto& e : map3)
	{
		cout << e.first << "->" << e.second << endl;
	}
}

在这里插入图片描述

map的常见修改操作

insert

在这里插入图片描述

void testmap3()
{
	std::map<char, int> mymap;

	// 匿名对象
	mymap.insert(std::pair<char, int>('a', 100));
	mymap.insert(std::pair<char, int>('z', 200));

	// 在map中插入一个键值对,迭代器加判断是否插入成功
	std::pair<std::map<char, int>::iterator, bool> ret;
	ret = mymap.insert(std::pair<char, int>('z', 500));
	if (ret.second == false) 
	{
		std::cout << "element 'z' already existed";
		std::cout << " with a value of " << ret.first->second << '\n';
	}

	// 插入一个迭代器位置加值
	std::map<char, int>::iterator it = mymap.begin();
	mymap.insert(it, std::pair<char, int>('b', 300));
	mymap.insert(it, std::pair<char, int>('c', 400));

	// 迭代器区间插入,利用begin()到find('c')的位置
	std::map<char, int> anothermap;
	anothermap.insert(mymap.begin(), mymap.find('c'));

	std::cout << "mymap contains:\n";
	for (it = mymap.begin(); it != mymap.end(); ++it)
		std::cout << it->first << " => " << it->second << '\n';

	std::cout << "anothermap contains:\n";
	for (it = anothermap.begin(); it != anothermap.end(); ++it)
		std::cout << it->first << " => " << it->second << '\n';
}

还有一种很省力的方法,使用make_pair(匿名对象),因为是make_pair返回的就是pair<T1,T2>(x, y),即自动识别类型。
在这里插入图片描述

#include<iostream>
using namespace std;
int main()
{
	std::map<int, int> map1;
	map1.insert(make_pair(1, 1));
	map1.insert(make_pair(2, 2));
	map1.insert(make_pair(3, 3));
	for(auto& e : map1)
	{
		cout << e << " ";
	}
	cout << endl;
}

erase

在这里插入图片描述

void testmap4()
{
	std::map<char, int> mymap;
	std::map<char, int>::iterator it;

	mymap.insert(make_pair('a', 10));
	mymap.insert(make_pair('b', 20));
	mymap.insert(make_pair('c', 30));
	mymap.insert(make_pair('d', 40));
	mymap.insert(make_pair('e', 50));
	mymap.insert(make_pair('f', 60));

	// 删除b这个位置的整个迭代器
	it = mymap.find('b');
	mymap.erase(it);

	// 删除键值为c的元素
	mymap.erase('c');

	// 删除迭代器区间
	it = mymap.find('e');
	mymap.erase(it, mymap.end());

	for (it = mymap.begin(); it != mymap.end(); ++it)
		std::cout << it->first << " => " << it->second << '\n';
}

find

在这里插入图片描述

void testmap5()
{
	std::map<char, int> mymap;
	std::map<char, int>::iterator it;

	mymap.insert(pair<char, int>('a', 50));
	mymap.insert(make_pair('b', 100));
	mymap.insert(pair<char, int>('c', 150));
	mymap.insert(pair<char, int>('d', 200));

	// 找到b这个键值对
	it = mymap.find('b');
	if (it != mymap.end()) // 判断是否找到
		mymap.erase(it);

	std::cout << "elements in mymap:" << '\n';
	std::cout << "a => " << mymap.find('a')->second << '\n';
	std::cout << "c => " << mymap.find('c')->second << '\n';
	std::cout << "d => " << mymap.find('d')->second << '\n';
}

count

void testmap6()
{
	std::map<char, int> mymap;
	char c;

	mymap.insert(make_pair('a', 101));
	mymap.insert(make_pair('b', 202));
	mymap.insert(make_pair('c', 303));
	mymap.insert(make_pair('d', 404));

	for (c = 'a'; c < 'h'; c++)
	{
		std::cout << c;
		if (mymap.count(c) > 0) // 数值大于0则输出是个有值的map
			std::cout << " is an element of mymap.\n";
		else
			std::cout << " is not an element of mymap.\n";
	}
}

在这里插入图片描述

map的容量与元素访问 – operator[]

在这里插入图片描述

empty和size都好讲,一个是判空,一个是算里面的数量,而重头戏在operator[]。

在这里插入图片描述

[]:有插入、查找和修改的功能。
1、map中有这个key,返回value的引用。
2、map中没有这个key的匹配值,则先构造一个pair(key, T()),先插入这个key值,再将value进行默认构造,最后返回value的引用。‘

在这里插入图片描述

[]的底层实现:

在这里插入图片描述

底层实现有两个pair的方式:
第一个是像上面所述的当key在map中的时候,返回的pair(key_iterator, false),当key不在map中,返回的是pair(new_key_iterator, true),即返回的是迭代器和bool值。
第二种则是kv模型的pair,是插入的pair的数据。

V& operator[](const K& key)
{
	pair<iterator, bool> ret = insert(make_pair(key, V());
	return ret.first->second;
}

利用map统计出现次数

用直接插入法

void test_map()
{
	string arr[] = { "苹果","香蕉","橙子","苹果","香蕉","橙子","苹果","香蕉","橙子","梨","柠檬" };

	map<string, int> fruitcount;
	for (auto& e : arr)
	{
		map<string, int>::iterator it = fruitcount.find(e);
		if (it != fruitcount.end())
		{
			it->second++;
		}
		else
		{
			// 刚进入
			fruitcount.insert(make_pair(e, 1));

		}
	}

	// 遍历
	map<string, int>::iterator it = fruitcount.begin();
	while (it != fruitcount.end())
	{
		cout << it->first << "=>" << it->second << endl;
		++it;
	}
	cout << endl;
}

用[]法

void test_map1()
{
	string arr[] = { "苹果","香蕉","橙子","苹果","香蕉","橙子","苹果","香蕉","橙子","梨","柠檬" };
	map<string, int> fruitcount;
	for (auto& e : arr)
	{
		//1、e不在fruitcount中,插入pair(e, int()),然后对返回次数++
		//2、e在的话,就返回value的引用次数++
		fruitcount[e]++;
	}
	// 遍历
	map<string, int>::iterator it = fruitcount.begin();
	while (it != fruitcount.end())
	{
		cout << it->first << "=>" << it->second << endl;
		++it;
	}
	cout << endl;
}

multimap

multimap介绍

  1. Multimaps是关联式容器,它按照特定的顺序,存储由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的使用

void test_map2()
{
	multimap<string, string> mdict;
	mdict.insert(make_pair("sort", "排序"));
	mdict.insert(make_pair("left", "左边"));
	mdict.insert(make_pair("left", "右边"));
	mdict.insert(make_pair("left", "不知道"));

	// 遍历
	for (auto& e : mdict)
	{
		cout << e.first << "=>" << e.second << endl;
	}
	cout << endl;
}

在这里插入图片描述

五、题目

前k个高频词

题目描述

在这里插入图片描述

解题思路

在这里插入图片描述

解题代码

class Solution {
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        // 用来记录次序的,本身就是按照字典序进行统计次数的
        map<std::string, int> countmap;
        for(const auto& e : words)
        {
            countmap[e]++;
        }

        // 用来排序的
        multimap<int, string, greater<int>> sortmap;
        // i - 2 love - 2 leetcode - 1 coding - 1
        for(auto& e : countmap)
        {
            sortmap.insert(make_pair(e.second, e.first));
        }

        // 开辟一个字符串数组
        vector<string> v;
        multimap<int, string, greater<int>>::iterator it = sortmap.begin();
        for(int i = 0; i < k; i++)
        {
            v.push_back(it->second);
            ++it;
        }
        return v;
    }
};

两个数组的交集

题目描述

在这里插入图片描述

解题思路

在这里插入图片描述

解题代码

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());
        set<int>::iterator it1 = s1.begin();
        set<int>::iterator 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);
                ++it2;
                ++it1;
            }
        }
        return v;
    }
};

差集思想

在这里插入图片描述

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

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

相关文章

WebGL笔记:绘制矩形面的几种方式以及封装封装多边形对象来绘制不同图形

绘制矩形面 可以绘制的面只有三角面&#xff0c;要绘制矩形面的话&#xff0c;只能用两个三角形去拼 1 &#xff09; 使用 三角带 TRIANGLE_STRIP 绘制矩形 回顾一下之前的规律&#xff1a; 第一个三角形&#xff1a;v0>v1>v2第偶数个三角形&#xff1a;以上一个三角形…

预编译(2)

#和## #运算符&#xff1a; #运算符将宏的⼀个参数转换为字符串字⾯量。它仅允许出现在带参数的宏的替换列表中。 #运算符所执⾏的操作可以理解为“字符串化”。 举例&#xff1a; 当我们有⼀个变量 int a 10; 的时候&#xff0c;我们想打印出&#xff1a; the value of …

volatile修饰数组

结论&#xff1a;volatile修饰对象或数组时&#xff0c;只能保证他们的引用地址的可见性。 非volatile数组的可见性问题 public class Test {static int[] a new int[]{1};public static void main(String[] args) {new Thread(() -> { //线程Atry {Thread.sleep(1000);}…

ElasticSearch一对多关系方案

一、前言 使用MySQL做为存储&#xff0c;表与表之间有很多是一对多关系&#xff0c;比如订单和订单商品明细&#xff0c;客户和客户地址等等&#xff0c;但是因为ES本身是扁平化文档结构&#xff0c;一般不同索引之间是没有关系的&#xff0c;ES在处理这种关系时相比MySQL并不…

Python计算巴氏距离

Python计算巴氏距离 巴氏距离简介 在统计中&#xff0c;巴氏距离&#xff08;Bhattacharyya Distance&#xff09;测量两个离散或连续概率分布的相似性。它与衡量两个统计样品或种群之间的重叠量的巴氏系数密切相关。巴氏距离和巴氏系数以20世纪30年代曾在印度统计研究所工作…

分布式事务-TCC异常-幂等性

1、幂等性问题&#xff1a; 二阶段提交时&#xff0c;如果二阶段执行成功通知TC时出现网路或其他问题中断&#xff0c;那么TC没有收到执行成功的通知&#xff0c;TC内部有定时器不断的重试二阶段方法&#xff0c;导致接口出现幂等性问题。 2、解决方法 和空回滚问题一样也是…

Elastic SQL 输入:数据库指标可观测性的通用解决方案

作者&#xff1a;Lalit Satapathy, Ishleen Kaur, Muthukumar Paramasivam Elastic SQL 输入&#xff08;metricbeat 模块和输入包&#xff09;允许用户以灵活的方式对许多支持的数据库执行 SQL 查询&#xff0c;并将结果指标提取到 Elasticsearch。 本博客深入探讨了通用 SQL …

基于SpringBoot的课程答疑系统

目录 前言 一、技术栈 二、系统功能介绍 学生信息管理 科目类型管理 老师回答管理 我的收藏管理 学生问题 留言反馈 交流区 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#x…

SPSS探索性分析

前言&#xff1a; 本专栏参考教材为《SPSS22.0从入门到精通》&#xff0c;由于软件版本原因&#xff0c;部分内容有所改变&#xff0c;为适应软件版本的变化&#xff0c;特此创作此专栏便于大家学习。本专栏使用软件为&#xff1a;SPSS25.0 本专栏所有的数据文件可在个人主页—…

求解平面上物体的有向3d包围盒

算法流程&#xff1a; &#xff08;1&#xff09;点云下采样&#xff08;体素滤波&#xff09;&#xff1b; &#xff08;2&#xff09;ransac算法分割拟合地面平面&#xff1b; &#xff08;3&#xff09;裁剪工作区域&#xff08;指定空间中四个点&#xff0c;裁剪点云只保留…

C++_基础语法

一、关键字 常用语法 #include<iostream>using namespace std;// 全局常量 #define DAY 30void main() {/** 变量与输出*/// 局部常量const int year 2023;// 控制台输出cout << "hello world" << endl;cout << "天&#xff1a;"…

国庆加速度!新增功能点锁定功能,敏捷开发新增估算功能,助力项目快速突破!

大家好&#xff0c;CoCode开发云旗下Co-Project V3.6智能项目管理平台正式发布&#xff0c;平台新增功能点锁定功能、敏捷开发模式新增估算板块和两种估算方式。 功能点锁定功能进一步提高了项目估算的灵活性和准确性&#xff0c;有利于提高项目估算效率&#xff1b;而敏捷开发…

Unity2023打包首包从78Mb到3.0Mb-震惊-我做对了什么

&#xff08;全程并没有使用AssetBundle , 历史原因&#xff0c;Resources目录还有不少资源残留&#xff09; 曾经的我在2019打包过最小包10m左右&#xff0c;后来发现到了Unity2020之后暴增到40m&#xff0c;又加上2023版本URP&#xff0c;1个Unity输出包可能至少55M 如下图…

Ubuntu基于Docker快速配置GDAL的Python、C++环境

本文介绍在Linux的Ubuntu操作系统中&#xff0c;基于Docker快速配置Python、C等不同编程语言均可用的地理数据处理库GDAL的方法。 首先&#xff0c;我们访问GDAL库的Docker镜像官方网站&#xff08;https://github.com/OSGeo/gdal/tree/master/docker&#xff09;。其中&#x…

Abstract Factory 抽象工厂模式简介与 C# 示例【创建型】

〇、简介 1、什么是抽象工厂模式&#xff1f; 一句话解释&#xff1a; 提供一个接口&#xff0c;以创建一系列相关或相互依赖的抽象对象&#xff0c;而无需指定它们具体的类。&#xff08;将一系列抽象类装进接口&#xff0c;一次接口实现&#xff0c;就必须实例化这一系列抽象…

如何在Ubuntu中切换root用户和普通用户

问题 大家在新装Ubuntu之后&#xff0c;有没有发现自己进入不了root用户&#xff0c;su root后输入密码根本进入不了&#xff0c;这怎么回事呢&#xff1f; 打开Ubuntu命令终端&#xff1b; 输入命令&#xff1a;su root&#xff1b; 回车提示输入密码&#xff1b; 提示&…

[ubuntu]ubuntu设置虚拟内存

首先查看自己是否加过虚拟内存或者查看虚拟内存当前状态可以命令&#xff1a; free -mh 创建交换分区&#xff1a; sudo mkdir /swap cd /swap sudo dd if/dev/zero ofswapfile bs1024 count12582912 其中count是自己分配内存大小&#xff0c;上面为12GB&#xff0c;你可…

视频异常检测:Human Kinematics-inspired Skeleton-based Video Anomaly Detection

论文作者&#xff1a;Jian Xiao,Tianyuan Liu,Genlin Ji 作者单位&#xff1a;Nanjing Normal University;The Hong Kong Polytechnic University 论文链接&#xff1a;http://arxiv.org/abs/2309.15662v1 内容简介&#xff1a; 1&#xff09;方向&#xff1a;视频异常检测…

Opengl之混合

OpenGL中,混合(Blending)通常是实现物体透明度(Transparency)的一种技术。透明就是说一个物体(或者其中的一部分)不是纯色(Solid Color)的,它的颜色是物体本身的颜色和它背后其它物体的颜色的不同强度结合。一个有色玻璃窗是一个透明的物体,玻璃有它自己的颜色,但它最终的…

rtp流广播吸顶喇叭网络有源吸顶喇叭

SIP-7043 rtp流广播吸顶喇叭网络有源吸顶喇叭 一、描述 SIP-7043是我司的一款SIP网络有源吸顶喇叭&#xff0c;具有10/100M以太网接口&#xff0c;内置有一个高品质扬声器&#xff0c;将网络音源通过自带的功放和喇叭输出播放&#xff0c;可达到功率20W。SIP-7043作为SIP系统的…