【C++庖丁解牛】基于红黑树实现的两种常用的关联容器map和set以及multimap

🍁你好,我是 RO-BERRY
📗 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油

在这里插入图片描述


目录

  • 1. 关联式容器
  • 2. 键值对
  • 3. 树形结构的关联式容器
  • 4. set的介绍
  • 5. set的使用
    • 5.1 set的模板参数列表
    • 5.2 set的构造
    • 5.3 set的迭代器
    • 5.4 set的容量
    • 5.5 set修改操作
    • 5.6 set的使用举例
      • 构造及其遍历
      • find and erase
      • count
      • lower_bound
      • upper_bound
      • equal_range
  • 6. map的介绍
  • 7.map的使用
    • 7.1 map的模板参数说明
    • 7.2 map的构造
    • 7.3 map的迭代器
    • 7.4 map的容量与元素访问
    • 7.5 map中元素的修改
    • 7.5 pair函数
  • 8. multiset的介绍
  • 9.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的介绍

  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中的底层使用二叉搜索树(红黑树)来实现

5. set的使用

5.1 set的模板参数列表

在这里插入图片描述

T:set中存放元素的类型,实际在底层存储<value, value>的键值对。
Compare:set中元素默认按照小于来比较
Alloc:set中元素空间的管理方式,使用STL提供的空间配置器管理

5.2 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
set ( const set<Key,Compare,Allocator>& x);set的拷贝构造

5.3 set的迭代器

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

5.4 set的容量

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

5.5 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 ( const key_type& x ) const返回set中值为x的元素的个数

5.6 set的使用举例

构造及其遍历

#include<iostream>
using namespace std;

#include<set>

void test_set1()
{
	set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(2);
	s.insert(3);
	s.insert(4);
	s.insert(4);
	s.insert(6);
	s.insert(6);

	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	// 正向打印set中的元素,从打印结果中可以看出:set可去重
	for (auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;

}

int main()
{
	test_set1();

	return 0;
}

输出结果:
在这里插入图片描述

我们会发现一个奇怪的结果,我们的迭代器输出的结果是有序的,这是为什么?

这是因为我们的迭代器去遍历这个搜索二叉树走的是中序,顺便帮我们实现排序,而且可以去重,这种方式的好处就是便于我们进行插入删除

find and erase

在这里插入图片描述

注意:find返回的是一个迭代器

在这里插入图片描述

#include<iostream>
using namespace std;

#include<set>

void test_set1()
{
	set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(2);
	s.insert(3);
	s.insert(4);
	s.insert(4);
	s.insert(6);
	s.insert(6);

	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	// 正向打印set中的元素,从打印结果中可以看出:set可去重
	for (auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;

	auto i = s.find(4);
	s.erase(i);

	s.erase(1);  //也可以直接传值

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

int main()
{
	test_set1();

	return 0;
}

在这里插入图片描述

erase找到这个值就删除,没有这个值就不会进行任何操作


count

返回这个值存在几个

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

#include<set>

void test_set1()
{
	set<int> s;
	s.insert(5);
	s.insert(1);
	s.insert(2);
	s.insert(3);
	s.insert(4);
	s.insert(4);
	s.insert(6);
	s.insert(6);

	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	// 正向打印set中的元素,从打印结果中可以看出:set可去重
	for (auto& e : s)
	{
		cout << e << " ";
	}
	cout << endl;

	auto i = s.find(4);
	s.erase(i);

	s.erase(1);  //也可以直接传值

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

	cout << s.count(3) << endl;
}

int main()
{
	test_set1();

	return 0;
}

在这里插入图片描述


lower_bound

lower_bound Return iterator to lower bound (public member function)

lower_bound是set容器提供的一个成员函数,用于查找第一个大于或等于给定值的元素的迭代器。
具体来说,lower_bound函数接受一个参数,表示要查找的值,然后返回一个指向set容器中第一个大于或等于该值的元素的迭代器。如果不存在这样的元素,则返回指向set容器中的end()迭代器。
下面是lower_bound函数的用法示例:

#include <iostream>
using namespace std;
#include <set>


int main() {
    set<int> mySet = {10, 20, 30, 40, 50};

    auto it = mySet.lower_bound(25);
    if (it != mySet.end()) {
        cout << "lower_bound(25) = " << *it << endl;
    } else {
        cout << "No element greater than or equal to 25 found." << endl;
    }

    return 0;
}

在这里插入图片描述

upper_bound

upper_bound Return iterator to upper bound (public member function)

upper_bound函数是set容器的一个成员函数,用于查找大于给定值的第一个元素的迭代器。具体来说,upper_bound函数返回一个指向set容器中第一个大于给定值的元素的迭代器,如果不存在这样的元素,则返回set容器的end迭代器。
下面是upper_bound函数的使用示例:

#include <iostream>
using namespace std;
#include <set>

int main() {
    set<int> mySet = {10, 20, 30, 40, 50};

    auto it = mySet.upper_bound(25);
    if (it != mySet.end()) {
        cout << "The first element greater than 25 is: " << *it << std::endl;
    } else {
        cout << "No element greater than 25 found." << endl;
    }

    return 0;
}

在这里插入图片描述

equal_range

equal_range Get range of equal elements (public member function)

equal_range是set容器提供的一个成员函数,用于查找指定值的范围。

equal_range函数接受一个参数,即要查找的值,它返回一个pair对象,包含两个迭代器。第一个迭代器指向第一个等于给定值的元素,第二个迭代器指向第一个大于给定值的元素。如果没有找到等于给定值的元素,那么两个迭代器都指向第一个大于给定值的元素。

下面是equal_range函数的用法示例:

#include <iostream>
using namespace std;
#include <set>

int main() {
    set<int> mySet = {1, 2, 3, 4, 5};

    auto range = mySet.equal_range(3);

    cout << "Range of elements equal to 3: ";
    for (auto it = range.first; it != range.second; ++it) {
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

在这里插入图片描述

6. 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;

  1. 在内部,map中的元素总是按照键值key进行比较排序的。
  2. map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  3. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
  4. map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。

7.map的使用

7.1 map的模板参数说明

在这里插入图片描述

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

7.2 map的构造

函数声明功能介绍
map()构造一个空的map

7.3 map的迭代器

函数声明功能介绍
begin()和end()begin:首元素的位置,end最后一个元素的下一个位置
cbegin()和cend()与begin和end意义相同,但cbegin和cend所指向的元素不能修改
rbegin()和rend()反向迭代器,rbegin在end位置,rend在begin位置,其++和–操作与begin和end操作移动相反
crbegin()和crend()与rbegin和rend位置相同,操作相同,但crbegin和crend所指向的元素不能修改

7.4 map的容量与元素访问

函数声明功能简介
bool empty ( ) const检测map中的元素是否为空,是返回true,否则返回false
size_type size() const返回map中有效元素的个数
mapped_type& operator[] (const key_type& k)返回去key对应的value

问题:当key不在map中时,通过operator获取对应value时会发生什么问题?

在这里插入图片描述
注意:在元素访问时,有一个与operator[]类似的操作at()(该函数不常用)函数,都是通过key找到与key对应的value然后返回其引用,不同的是:当key不存在时,operator[]用默认value与key构造键值对然后插入,返回该默认value,at()函数直接抛异常。

7.5 map中元素的修改

函数声明功能简介
pair<iterator,bool> insert ( const value_type& x )在map中插入键值对x,注意x是一个键值对,返回值也是键值对:iterator代表新插入元素的位置,bool代表释放插入成功
void erase ( iterator position )删除position位置上的元素
size_type erase ( const key_type& x )删除键值为x的元素
void erase ( iterator first, iterator last )删除[first, last)区间中的元素
void swap ( map<Key,T,Compare,Allocator>& mp )交换两个map中的元素
void clear ( )将map中的元素清空
iterator find ( const key_type& x )在map中插入key为x的元素,找到返回该元素的位置的迭代器,否则返回end
const_iterator find ( const key_type& x ) const在map中插入key为x的元素,找到返回该元素的位置的const迭代器,否则返回cend
size_type count ( const key_type& x ) const返回key为x的键值在map中的个数,注意map中key是唯一的,因此该函数的返回值要么为0,要么为1,因此也可以用该函数来检测一个key是否在map中

7.5 pair函数

pair是C++标准库中的一个模板类,用于存储两个不同类型的值。它可以将两个值组合成一个单元,形成一个键值对的结构。pair类定义在<utility>头文件中。

pair类的定义如下:

template <class T1, class T2>
struct pair {
	typedef T1 first_type;
	typedef T2 second_type;

	T1 first;
	T2 second;

	pair();
	pair(const T1& x, const T2& y);
	template<class U, class V> pair(const pair<U, V>& p);
};

pair类有两个成员变量:first和second,分别表示键和值。可以通过pair对象的first和second成员来访问这两个值。
pair类还提供了一些构造函数和操作符重载,方便对pair对象进行初始化和操作。例如,可以使用make_pair函数来创建一个pair对象,使用==和!=操作符来比较两个pair对象是否相等。

使用实例:

void TestMap()
{
	map<string, string> m;
	// 向map中插入元素的方式:
	// 将键值对<"peach","桃子">插入map中,用pair直接来构造键值对
	m.insert(pair<string, string>("peach", "桃子"));
	
	//C++11支持这样隐式调用
	m.insert({"peach", "桃子"});
	// 将键值对<"peach","桃子">插入map中,用make_pair函数来构造键值对,C++98习惯这样使用
	m.insert(make_pair("banan", "香蕉"));

	// 借用operator[]向map中插入元素
	/*
	operator[]的原理是:
	 用<key, T()>构造一个键值对,然后调用insert()函数将该键值对插入到map中
	 如果key已经存在,插入失败,insert函数返回该key所在位置的迭代器
	 如果key不存在,插入成功,insert函数返回新插入元素所在位置的迭代器
	 operator[]函数最后将insert返回值键值对中的value返回
	*/
	// 将<"apple", "">插入map中,插入成功,返回value的引用,将“苹果”赋值给该引用结果,
	m["apple"] = "苹果";
	// key不存在时抛异常
	 //m.at("waterme") = "水蜜桃";
	cout << m.size() << endl;
	// 用迭代器去遍历map中的元素,可以得到一个按照key排序的序列
	for (auto& e : m)
		cout << e.first << "--->" << e.second << endl;
	cout << endl;
	// map中的键值对key一定是唯一的,如果key存在将插入失败
	auto ret = m.insert(make_pair("peach", "桃色"));
	if (ret.second)
		cout << "<peach, 桃色>不在map中, 已经插入" << endl;
	else
		cout << "键值为peach的元素已经存在:" << ret.first->first << "--->"<< ret.first->second << " 插入失败" << endl;
	// 删除key为"apple"的元素
	m.erase("apple");
	if (1 == m.count("apple"))
		cout << "apple还在" << endl;
	else
		cout << "apple被吃了" << endl;
}

【总结】

  1. map中的的元素是键值对
  2. map中的key是唯一的,并且不能修改
  3. 默认按照小于的方式对key进行比较
  4. map中的元素如果用迭代器去遍历,可以得到一个有序的序列
  5. map的底层为平衡搜索树(红黑树),查找效率比较高 O ( l o g 2 N ) O(log_2 N) O(log2N)
  6. 支持[]操作符,operator[]中实际进行插入查找。

8. 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的作用:可以对元素进行排序

9.multiset的使用

此处只简单演示set与multiset的不同,其他接口接口与set相同,同学们可参考set。

#include <set>
void TestSet()
{
 	int array[] = { 2, 1, 3, 9, 6, 0, 5, 8, 4, 7 };
 
	// 注意:multiset在底层实际存储的是<int, int>的键值对
	multiset<int> s(array, array + sizeof(array)/sizeof(array[0]));
	for (auto& e : s)
		cout << e << " ";
	cout << endl;
	return 0;
}

在这里插入图片描述

  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;

  1. 在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序的。
  2. multimap通过key访问单个元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍历multimap中的元素可以得到关于key有序的序列。
  3. multimap在底层用二叉搜索树(红黑树)来实现。

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

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

  1. multimap中的key是可以重复的。
  2. multimap中的元素默认将key按照小于来比较
  3. multimap中没有重载operator[]操作。
  4. 使用时与map包含的头文件相同:

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

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

相关文章

最短路径——Floyd算法、Dijkstra算法(未完...)

这里写目录标题 例题引入&#xff1a; 路径——蓝桥2021省赛题目分析题解&#xff01;&#xff01;&#xff01;求最短路径问题&#xff01;&#xff01;&#xff01;应用场景图的基础Floyd算法Acwing-843.有边数限制的最短路简单的思路讲解 Dijkstra算法 例题引入&#xff1a;…

鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

随后迎来了不少互联网公司与华为鸿蒙原生应用达成了合作&#xff0c;像我们常见的阿里、京东、小红书、得物……等公司&#xff0c;还有一些银行也都与华为鸿蒙达成了合作。使得一时之间市场紧缺鸿蒙开发人才&#xff0c;不少公司不惜重金争抢人才。 据智联招聘的最新数据显示…

最强的营销团队,这样打造!

在瞬息万变的商业环境中&#xff0c;构建无可挑剔的营销团队结构的重要性毋庸置疑。营销团队的力量不仅在于其成员的个人才能&#xff0c;还在于这些才能如何有效地协调在一起。建立完美的营销团队结构类似于拼图。每块拼图都代表了独特的技能和视角&#xff0c;如果放置得当&a…

未来5年|个人电脑“变”AI PC

随着生成式AI热潮达到白热化阶段&#xff0c;笔记本电脑市场正面临一场范式转变。根据Tech Insights预测数据&#xff0c;到2029年&#xff0c;配备专用AI加速芯片&#xff08;即NPU&#xff09;的AI赋能笔记本电脑将在整个笔记本市场占据主导地位&#xff0c;占比高达95%&…

【MySQL】事务是什么?事务的特性又是什么?

文章目录 ✍事务是什么&#xff1f;✍事务的特性&#xff08;四个&#xff09;✍事务并发时出现的问题✍事务的隔离性 ✍事务是什么&#xff1f; 事务是由一个或多个SQL语句构成的&#xff0c;在事务中&#xff0c;这些的SQL不可分割&#xff0c;是一个整体&#xff0c;整个事…

牛客NC30 缺失的第一个正整数【simple map Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/50ec6a5b0e4e45348544348278cdcee5 核心 Map参考答案Java import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可…

web前端之罗盘时钟、不一样的补零方式、LED字体、padStart

MENU 效果图htmlJavaScriptstyle 效果图 html <div class"clock"><div class"second-box"></div><div class"minute-box"></div><div class"hour-box"></div><div class"day-box&…

HarmonyOS 应用开发之Stage模型启动FA模型PageAbility

本小节介绍Stage模型的两种应用组件如何启动FA模型的PageAbility组件。 UIAbility启动PageAbility UIAbility启动PageAbility和UIAbility启动UIAbility的方式完全相同。 说明&#xff1a; 需注意FA模型中abilityName由bundleName AbilityName组成&#xff0c;具体见示例。 i…

蓝桥杯第十三届电子类单片机组程序设计

目录 前言 单片机资源数据包_2023 一、第十三届比赛省赛 1.比赛题目 2.赛题解读 二、部分功能实现 1.继电器的开启与关闭 2.长按切换显示状态功能的实现 3.对于温度传感器小数部分的处理 4.其他处理 1&#xff09;关于数码管显示小数的处理 2&#xff09;关于5s后继…

vue3+ts+elementplus写一个登录页面教程

文章目录 前言1. 安装 Vue CLI 和 TypeScript 支持2. 创建登录组件 文章重点内容 前言 前期准备步骤&#xff1a; 创建一个使用 Vue 3 和 TypeScript 的登录页面涉及到多个步骤。以下是一个基本的教程&#xff0c;帮助你从头开始构建这样一个页面&#xff1a; 1. 安装 Vue CL…

Ollama部署在线ai聊天

概述&#xff1a;虽然ollama在Windows方面还有很多bug&#xff0c;但不妨碍它在ai领域上面的成就 第一步&#xff1a;安装Ollama 官网&#xff1a;Download Ollama on Windows 下载安装即可。说明一下ollama的安装位置只能是c盘&#xff0c;好像改不了&#xff0c;但是数据模…

算法学习——LeetCode力扣动态规划篇8

算法学习——LeetCode力扣动态规划篇8 300. 最长递增子序列 300. 最长递增子序列 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删…

FA模型切换Stage模型之module的切换

从FA模型切换到Stage模型时&#xff0c;开发者需要将config.json文件module标签下的配置迁移到module.json5配置文件module标签下&#xff0c;具体差异见下列表格。 表1 FA模型module标签与Stage模型module标签差异对比 表2 FA模型metaData和Stage中metadata对比 表3 FA模型me…

【UI框架】——保姆式使用教程

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

深度学习500问——Chapter05: 卷积神经网络(CNN)(2)

文章目录 5.6 有哪些池化方法 5.7 1x1卷积作用 5.8 卷积层和池化层有什么区别 5.9 卷积核是否一定越大越好 5.10 每层卷积是否只能用一种尺寸的卷积核 5.11 怎样才能减少卷积层参数量 5.12 在进行卷积操作时&#xff0c;必须同时考虑通道和区域吗 5.13 采用宽卷积的好处有什么 …

多线程JUC 第2季 synchornized和Lock锁(重入,公平)

一 锁 1.1 锁的介绍 synchronized&#xff0c;和lock锁都是一种悲观锁。悲观锁适用于写多场景&#xff0c;乐观锁适用于读多场景&#xff0c;实现策略有&#xff1a;版本号和cas自旋算法。 1.2 类锁和对象锁的使用场景 1.3 任何对象都有一把锁 之所以任何一个对象都有把锁…

html第二次作业

骨架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, initi…

PyTorch深度学习快速入门(小土堆)

文章目录 16. 神经网络的基本骨架17.卷积操作18.卷积层 16. 神经网络的基本骨架 forward: import torch from torch import nnclass Tudui(nn.Module):def __init__(self):super().__init__()def forward(self,input):outputinput1return output#创建Tudui的实例对象 tuduiTu…

Django详细教程(二) - 部门用户管理案例

文章目录 前言一、新建项目二、新建app三、设计表结构四、新建数据库五、新建静态文件六、部门管理1.部门展示2.部门添加3.部门删除4.部门编辑 七、模板继承八、用户管理1.辨析三种方法方法一&#xff1a;原始方法方法二&#xff1a;Form组件(简便)方法三&#xff1a;ModelForm…

ARM-按键中断实验

代码 #include "stm32mp1xx_gic.h" #include "stm32mp1xx_exti.h" extern void printf(const char *fmt, ...); unsigned int i 0; void do_irq(void) {//获取要处理的中断的中断号unsigned int irqnoGICC->IAR&0x3ff;switch (irqno){case 99:pr…