C++进阶:map和set的使用

目录

一.序列式容器和关联式容器

二.set系列的使用

2.1set容器的介绍

2.2set的构造和迭代器

2.3set的增删查

2.4insert和迭代器遍历的样例

2.5find和erase的样例

 ​编辑

2.6multiset和set的差异

2.7简单用set解决两道题

两个数组的交集

 环形链表二

三.map系列的使用

3.1map类的介绍

3.2pair类型介绍

3.3map的构造

3.4map的增删查

3.5map的数据修改

3.6构造遍历和增删查使用样例

 3.7map的迭代器和[]功能样例

 3.8multimap和map的差异

3.9用map解决两道题

随机链表的复制

前k个高频单词 


一.序列式容器和关联式容器

关于序列式容器,STL中的如:string、vector、list、deque、array、forward_list等,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间一般没有紧密的关联关系,比如交换一下,他依旧是序列式容器。顺序容器中的元素是按他们在容器中的存储位 置来顺序保存和访问的。

关联式容器也是用来存储数据的,与序列式容器不同的是,关联式容器逻辑结构通常是非线性结构, 两个位置有紧密的关联关系,交换一下,他的存储结构就被破坏了。顺序容器中的元素是按关键字来保存和访问的。关联式容器有map/set系列和unordered_map/unordered_set系列。

map和set底层是红黑树,红黑树是⼀颗平衡二叉搜索树。set是key搜索场景的结构, map是key/value搜索场景的结构。

二.set系列的使用

2.1set容器的介绍

• set的声明如下,T就是set底层关键字的类型

• set默认要求T支持小于比较,如果不支持或者想按自己的需求走可以自行实现仿函数传给第二个模版参数

• set底层存储数据的内存是从空间配置器申请的,如果需要可以自己实现内存池,传给第三个参 数。

• 一般情况下,我们都不需要传后两个模版参数。

• set底层是用红黑树实现,增删查效率是O(logN) ,迭代器遍历是走的搜索树的中序,所以是有序 的。

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;

2.2set的构造和迭代器

set的支持正向和反向迭代遍历,遍历默认按升序顺序,因为底层是二叉搜索树,迭代器遍历走的中序;支持迭代器就意味着支持范围for,set的iterator和const_iterator都不支持迭代器修改数据,修改关键字数据,破坏了底层搜索树的结构。

//默认构造
explicit set(const key_compare& comp = key_compare(),
	const allocator_type& alloc = allocator_type());
//迭代器构造
template <class InputIterator>
set(InputIterator first, InputIterator last,
	const key_compare& comp = key_compare(),
	const allocator_type& alloc = allocator_type());
//拷贝构造
set(const set& x);
// 正向迭代器 
iterator begin();
iterator end();
// 反向迭代器 
reverse_iterator rbegin();
reverse_iterator rend();

2.3set的增删查

以下是一些我们需要关注的接口

// 单个数据插入,如果已经存在则插入失败 
pair<iterator, bool> insert(const value_type& val);

// 列表插入,已经在容器中存在的值不会插入 
void insert(initializer_list<value_type> il);

// 迭代器区间插入,已经在容器中存在的值不会插入 
template <class InputIterator>
void insert(InputIterator first, InputIterator last);

// 查找val,返回val所在的迭代器,没有找到返回end() 
iterator find(const value_type& val);

// 查找val,返回Val的个数 
size_type count(const value_type& val) const;

// 删除一个迭代器位置的值 
iterator erase(const_iterator position);

// 删除val,val不存在返回0,存在返回1 
size_type erase(const value_type& val);

// 删除⼀段迭代器区间的值 
iterator erase(const_iterator first, const_iterator last);

// 返回大于等于val位置的迭代器 
iterator lower_bound(const value_type& val) const;

// 返回大于val位置的迭代器 
iterator upper_bound(const value_type& val) const;

2.4insert和迭代器遍历的样例

#include<iostream>
#include<set>
using namespace std;
int main()
{
	// 去重+升序排序 
	set<int> s;
	// 去重+降序排序(给一个大于的仿函数) 
	//set<int, greater<int>> s;

	s.insert(5);
	s.insert(2);
	s.insert(7);
	s.insert(5);
	//set<int>::iterator it = s.begin();

	auto it = s.begin();
	while (it != s.end())
	{
		// error C3892: “it”: 不能给常量赋值 
		// *it = 1;

		cout << *it << " ";
		++it;
	}
	cout << endl;
	// 插入一段initializer_list列表值,已经存在的值插入失败 
	s.insert({ 2,8,3,9 });
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	set<string> strset = { "sort", "insert", "add" };
	// 遍历string比较ascll码大小顺序遍历的 
	for (auto& e : strset)
	{
		cout << e << " ";
	}
	cout << endl;
}

 输出:

2.5find和erase的样例

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

int main()
{
	set<int> s = { 4,2,7,2,8,5,9 };
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	// 删除最小值 
	s.erase(s.begin());
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	// 直接删除x
	int x;
	cin >> x;//9
	int num = s.erase(x);//删除失败返回0
	if (num == 0)
	{
		cout << x << "不存在!" << endl;
	}

	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	// 直接查找再利用迭代器删除x 
	cin >> x;//8
	auto pos = s.find(x);
	if (pos != s.end())//没有查找到返回end()
	{
		s.erase(pos);
	}
	else
	{
		cout << x << "不存在!" << endl;
	}
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;

	// 算法库的查找 O(N) 
	auto pos1 = find(s.begin(), s.end(), x);
	// set自身实现的查找 O(logN) 
	auto pos2 = s.find(x);
	// 利用count间接实现快速查找 
	cin >> x;//5
	if (s.count(x))
	{
		cout << x << "在!" << endl;
	}
	else
	{
		cout << x << "不存在!" << endl;
	}
	return 0;
}

输出: 

 

当然也可以使用lower_bound和upper_bound 来进行区间删除。

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

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

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

	// 实现查找到的[itlow,itup)包含[30, 60]区间 

	// 返回 >= 30 
	auto itlow = myset.lower_bound(30);
	// 返回 > 60 
	auto itup = myset.upper_bound(60);
	// 删除这段区间的值 
	myset.erase(itlow, itup);
	for (auto e : myset)
	{
		cout << e << " ";
	}
	cout << endl;
	return 0;
}

2.6multiset和set的差异

multiset和set的使用基本一样,但是multiset支持冗余

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

int main()
{
	// 相比set不同的是,multiset是排序,但是不去重 
	multiset<int> s = { 4,2,7,2,4,8,4,5,4,9 };
	auto it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	// 相比set不同的是,x可能会存在多个,find查找中序的第一个 
	int x;
	cin >> x;//4
	auto pos = s.find(x);
	while (pos != s.end() && *pos == x)
	{
		cout << *pos << " ";
		++pos;
	}
	cout << endl;
	// 相比set不同的是,count会返回x的实际个数 
	cout << s.count(x) << endl;
	// 相比set不同的是,erase给值时会删除所有的x 
	s.erase(x);
	for (auto e : s)
	{
		cout << e << " ";
	}
	cout << endl;
	return 0;
}

输出:

2.7简单用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());
        //进入set后自动去重
        vector<int> ret;
        set<int>::iterator it1=s1.begin();
        set<int>::iterator it2=s2.begin();
        while(it1!=s1.end()&&it2!=s2.end())
        {
            if(*it1<*it2)
            {
                it1++;
            }
            else if(*it1>*it2)
            {
                it2++;
            }
            else
            {
                ret.push_back(*it1);
                it1++;
                it2++;
            }
        }
        return ret;
    }
};

 环形链表二

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        set<ListNode*> s;
        ListNode* cur=head;
        while(cur)
        {
            pair<set<ListNode*>::iterator,bool> ret=s.insert(cur);
            if(ret.second==false)
            {
                return cur;
            }
            cur=cur->next;
        }
        return nullptr;
    }
};

三.map系列的使用

3.1map类的介绍

map的声明如下,Key就是map底层关键字的类型,T是map底层value的类型,map默认要求Key支持小于比较,如果不支持或者需要的话可以自行实现仿函数传给第二个模版参数,map底层存储数据的内存是从空间配置器申请的。⼀般情况下,我们都不需要传后两个模版参数。map底层是用红黑树实 现,增删查改效率是O(logN) ,迭代器遍历是走的中序,所以是按key有序顺序遍历的。

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;

3.2pair类型介绍

介绍pair类型之前要先了解pair是什么。map底层的红⿊树节点中的数据,使用pair存储键值对数据。

typedef pair<const Key, T> value_type;
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拷贝构造
	template<class U, class V>
	pair(const pair<U, V>& pr) 
		: first(pr.first)
		, second(pr.second)
	{}
}; 
template <class T1, class T2>
inline pair<T1, T2> make_pair(T1 x, T2 y)
{
	return (pair<T1, T2>(x, y));
}

3.3map的构造

map的支持正向和反向迭代遍历,遍历默认按key的升序顺序,因为底层是二叉搜索树,迭代器遍历走的中序;支持迭代器就意味着支持范围for,map支持修改value数据,不支持修改key数据,修改关键字数据,破坏了底层搜索树的结构。

//无参默认构造
explicit map(const key_compare& comp = key_compare(),
    const allocator_type& alloc = allocator_type());
//迭代器区间构造
template <class InputIterator>
map(InputIterator first, InputIterator last,
    const key_compare& comp = key_compare(),
    const allocator_type& alloc = allocator_type());
//拷贝构造
map(const map& x);
//列表构造
map(initializer_list<value_type> il,
    const key_compare& comp = key_compare(),
    const allocator_type& alloc = allocator_type());
// 正向迭代器 
iterator begin();
iterator end();
// 反向迭代器 
reverse_iterator rbegin();
reverse_iterator rend();

3.4map的增删查

map增接口,插入的pair键值对数据,跟set所有不同,但是查和删的接口只⽤关键字key跟set是完全类似的,不过find返回iterator,不仅仅可以确认key在不在,还找到key映射的value,同时通过迭代器还可以修改value。

key_type->The first template parameter(Key)
mapped_type->The second template parameter(T)
value_type->pair<const key_type, mapped_type>
// 单个数据插入,如果已经key存在则插入失败,key存在相等value不相等也会插入失败 
pair<iterator, bool> insert(const value_type& val);

// 列表插入,已经在容器中存在的值不会插入 
void insert(initializer_list<value_type> il);

// 迭代器区间插入,已经在容器中存在的值不会插入 
template <class InputIterator>
void insert(InputIterator first, InputIterator last);

// 查找k,返回k所在的迭代器,没有找到返回end() 
iterator find(const key_type& k);

// 查找k,返回k的个数 
size_type count(const key_type& k) const;

// 删除⼀个迭代器位置的值 
iterator erase(const_iterator position);

// 删除k,k存在返回0,存在返回1 
size_type erase(const key_type& k);

// 删除一段迭代器区间的值 
iterator erase(const_iterator first, const_iterator last);

// 返回大于等k位置的迭代器 
iterator lower_bound(const key_type& k);

// 返回大于k位置的迭代器 
const_iterator lower_bound(const key_type& k) const;

3.5map的数据修改

map支持修改mapped_type数据,不支持修改key数据,修改关键字数据,破坏了底层搜索树的结构。

map第一个支持修改的方式时通过迭代器,迭代器遍历时或者find返回key所在的iterator修改,map还有一个非常重要的修改接口operator[],但是operator[]不仅仅支持修改,还支持插入数据和查找数据,所以他是一个多功能复合接口

// 查找k,返回k所在的迭代器,没有找到返回end(),如果找到了通过iterator可以修改key对应的
//mapped_type值
iterator find(const key_type& k);
// insert插入⼀个pair<key, T>对象 
// 1、如果key已经在map中,插入失败,则返回一个pair<iterator,bool>对象,返回pair对象
//first是key所在结点的迭代器,second是false
// 2、如果key不在在map中,插入成功,则返回一个pair<iterator,bool>对象,返回pair对象
//first是新插入key所在结点的迭代器,second是true
// 也就是说无论插入成功还是失败,返回pair<iterator,bool>对象的first都会指向key所在的迭
//代器
// 那么也就意味着insert插入失败时充当了查找的功能,正是因为这一点,insert可以用来实现
//operator[]
// 需要注意的是这里有两个pair,不要混淆了,一个是map底层红黑树节点中存的pair<key, T>,另
//一个是insert返回值pair<iterator, bool>

pair<iterator, bool> insert(const value_type& val);
mapped_type& operator[] (const key_type& k);
// operator的内部实现 
mapped_type& operator[] (const key_type& k)
{
	// 1、如果k不在map中,insert会插入k和mapped_type默认值,同时[]返回结点中存储
	//mapped_type值的引用,那么我们可以通过引用修改返映射值。所以[]具备了插入 + 修改功能
	// 2、如果k在map中,insert会插入失败,但是insert返回pair对象的first是指向key结点的
	//迭代器,返回值同时[]返回结点中存储mapped_type值的引用,所以[]具备了查找 + 修改的功能
	pair<iterator, bool> ret = insert({ k, mapped_type() });
	iterator it = ret.first;
	return it->second;
}

3.6构造遍历和增删查使用样例

#include<iostream>
#include<map>
using namespace std;
int main()
{
	map<string,string> dict = { {"left", "左边"}, {"right", "右边"},
{"insert", "插入"},{ "string", "字符串" } };
	//map<string, string>::iterator it = dict.begin();
	auto it = dict.begin();
	while (it != dict.end())
	{
		//cout << (*it).first <<":"<<(*it).second << endl;

		// map的迭代基本都使用operator->,这里省略了一个-> 
		// 第一个->是迭代器运算符重载,返回pair*,第二个箭头是结构指针解引用取pair数据
		//cout << it.operator->()->first << ":" << it.operator->()-> second << endl;

		cout << it->first << ":" << it->second << endl;
		++it;
	}
	cout << endl;

	// insert插入pair对象的4种方式,对比之下,最后一种最方便 
	pair<string, string> kv1("first", "第一个");
	dict.insert(kv1);
	dict.insert(pair<string, string>("second", "第二个"));
	dict.insert(make_pair("sort", "排序"));
	dict.insert({ "auto", "自动的" });
	// "left"已经存在,插入失败 
	dict.insert({ "left", "左边,剩余" });

	// 范围for遍历 
	for (const auto& e : dict)
	{
		cout << e.first << ":" << e.second << endl;
	}
	cout << endl;

	string str;
	while (cin >> str)
	{
		auto ret = dict.find(str);
		if (ret != dict.end())
		{
			cout << "->" << ret->second << endl;
		}
		else
		{
			cout << "无此单词,请重新输入" << endl;
		}
	} 
	return 0;
}

输出: 

 3.7map的迭代器和[]功能样例

#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
	// 利用find和iterator修改功能,统计水果出现的次数 
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
   "苹果", "香蕉", "苹果", "香蕉" };
	map<string, int> countMap;
	for (const auto& str : arr)
	{
		// 先查找水果在不在map中 
		// 1、不在,说明水果第⼀次出现,则插入{水果, 1} 
		// 2、在,则查找到的节点中水果对应的次数++ 
		map<string,int>::iterator ret = countMap.find(str);
		if (ret == countMap.end())
		{
			countMap.insert({ str, 1 });
		}
		else
		{
			ret->second++;
		}
	}
	for (const auto& e : countMap)
	{
		cout << e.first << ":" << e.second << endl;
	}
	cout << endl;

	return 0;
}
#include<iostream>
#include<map>
#include<string>
using namespace std;

int main()
{
	// 利用[]插入+修改功能,巧妙实现统计水果出现的次数 
	string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜",
		"苹果", "香蕉", "苹果", "香蕉" };
	map<string, int> countMap;
	for (const auto& str : arr)
	{
		// []先查找水果在不在map中 
		// 1、不在,说明水果第一次出现,则插入{水果, 0},同时返回次数的引用,++一下就变成1次了
		// 2、在,则返回水果对应的次数++ 
		countMap[str]++;
	}
	for (const auto& e : countMap)
	{
		cout << e.first << ":" << e.second << endl;
	}
	cout << endl;
	return 0;
}

#include<iostream>
#include<map>
#include<string>
using namespace std;

int main()
{
	map<string, string> dict;
	dict.insert(make_pair("sort", "排序"));
	// key不存在->插入 {"insert", string()} 
	dict["insert"];
	// 插入+修改 
	dict["left"] = "左边";
	// 修改 
	dict["left"] = "左边、剩余";
	// key存在->查找 
	cout << dict["left"] << endl;
	for (const auto& e : dict)
	{
		cout << e.first << ":" << e.second << endl;
	}
	return 0;
}

 

 3.8multimap和map的差异

multimap和map的使用基本完全类似,主要区别点在于multimap支持关键值key冗余,那么 insert/find/count/erase都围绕着支持关键值key冗余有所差异,这里跟set和multiset完全⼀样,比如find时,有多个key,返回中序第一个。其次就是multimap不支持[],因为支持key冗余,[]就只能支持插入了,不能支持修改。

3.9用map解决两道题

随机链表的复制

class Solution {
public:
    Node* copyRandomList(Node* head) {
        map<Node*,Node*> nodemap;
        Node* copyhead=nullptr;
        Node* copytail=nullptr;
        Node* cur=head;
        //先不管random,把所有节点复制下来
        while(cur)
        {
            if(copytail==nullptr)
            {
                copyhead=copytail=new Node(cur->val);
            }
            else
            {
                copytail->next=new Node(cur->val);
                copytail=copytail->next;
            }
            //原链表节点与copy的链表节点一一赋值给map
            nodemap[cur]=copytail;
            cur=cur->next;
        }
        cur=head;
        Node* copy=copyhead;
        //之后再去管random
        while(cur)
        {
            if(cur->random==nullptr)
            {
                copy->random=nullptr;
            }
            else
            {
                //因为原链表的random指针指向的位置我们都知道
                //在nodemap里节点是一一对应的,cur的random指向,我们可以利用map得到我们复制链表里的位置
                //nodemap[cur->random]==我们复制链表里的,与原链表random指向对应的节点
                copy->random=nodemap[cur->random];
            }
            cur=cur->next;
            copy=copy->next;
        }
        return copyhead;
    }
};

前k个高频单词 

class Solution {
    typedef pair<string,int> PSI;
    struct cmp
    {
        bool operator()(const PSI& a,const PSI& b)
        {
            if(a.second==b.second)//频次相同,创建大根堆
            {
                return a.first < b.first;//比较字典序
            }
            //创建小根堆
            return a.second > b.second;//比较频次
        }
    };
public:
    vector<string> topKFrequent(vector<string>& words, int k) {
        map<string,int> hash;
        //用哈希表统计每个单词出现的次数
        for(auto& e:words)
        {
            hash[e]++;
        }
        priority_queue<PSI,vector<PSI>,cmp> heap;
        //heap里只保存k个PSI
        for(auto& s:hash)
        {
            heap.push(s);
            if(heap.size()>k) heap.pop();
        }
        vector<string> ret(k);
        //注意顺序,因为升序建大堆,降序建小堆,堆顶元素与我们想要的是反着的
        for(int i=k-1;i>=0;i--)
        {
            ret[i]=heap.top().first;
            heap.pop();
        }
        return ret;
    }
};

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

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

相关文章

Android Framework AMS(04)startActivity分析-1(am启动到ActivityThread启动)

该系列文章总纲链接&#xff1a;专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明&#xff1a; 说明&#xff1a;本章节主要解读AMS通过startActivity启动Activity的整个流程的第一阶段&#xff1a;从am启动到ActivityThread启动。 第二阶段文章链接为&#xf…

FFmpeg的简单使用【Windows】--- 视频倒叙播放

实现功能 点击【选择文件】按钮可以选择视频&#xff0c;当点击【开始处理】按钮之后&#xff0c;会先将视频上传到服务器&#xff0c;然后开始进行视频倒叙播放的处理&#xff0c;当视频处理完毕之后会将输出的文件路径返回&#xff0c;同时在页面中将处理好的视频展示出来。…

SHELL脚本之重定向符号的使用。

一.shell脚本&#xff08;对应完成某一个功能的命令熟悉与否&#xff0c;决定着shell脚本的熟练与否。&#xff09; 一个shell脚本就是一个普通的文本文件。 作用&#xff1a;将重复执行的操作写成脚本&#xff0c;自动执行。 二.Linux操作系统中重定向符号的使用。 类型&a…

ESP32接入扣子(Coze) API使用自定义智能体

使用ESP32接入Coze API实现聊天机器人的教程 本示例将使用ESP32开发板通过WiFi接入 Coze API&#xff0c;实现一个简单的聊天机器人功能。用户可以通过串口向机器人输入问题&#xff0c;ESP32将通过Coze API与智能体进行通信&#xff0c;并返回对应的回复。本文将详细介绍了如…

selenium有多个frame页时的操作方法(5)

之前文章我们提到&#xff0c;在webdriver.WebDriver类有一个switch_to方法&#xff0c;通过switch_to.frame()可以切换到不同的frame页然后才再定位某个元素做一些输入/点击等操作。 比如下面这个测试网站有2个frame页&#xff1a;http://www.sahitest.com/demo/framesTest.h…

wordpress 子比主题美化 四宫格 多宫格 布局插件

wordpress 主题美化 四宫格 多宫格 布局插件&#xff08;只在子比主题上测试过&#xff0c;其它主题没测试&#xff09; A5资源网四宫格布局插件是一个功能丰富的WordPress插件,专为创建自适应的四宫格布局而设计。这个插件具有以下主要特点: 灵活的布局: 支持1到8个宫格的自定…

如何设置 GitLab 密码长度?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 60天专业…

星海智算:【RVC】无需部署一键启动

镜像介绍 RVC全称 Retrieval-based-Voice-Conversion-WebUI 简称 RVC 一个基于VITS的简单易用的语音转换&#xff08;变声器&#xff09;框架 RVC 是一款前沿的音色替换项目&#xff0c;可以进行歌曲的翻唱&#xff0c;和实时的变声&#xff0c;具有低延迟、优秀的变声效果、…

【可答疑】基于51单片机的自动烘手器(含仿真、代码、报告、演示视频等)

✨哈喽大家好&#xff0c;这里是每天一杯冰美式oh&#xff0c;985电子本硕&#xff0c;大厂嵌入式在职0.3年&#xff0c;业余时间做做单片机小项目&#xff0c;有需要也可以提供就业指导&#xff08;免费&#xff09;~ &#x1f431;‍&#x1f409;这是51单片机毕业设计100篇…

C++ 算法学习——1.8 快速幂算法

背景知识&#xff1a; 1.位运算 在C中&#xff0c;位运算是对整数类型的位进行操作的一种运算方式。常见的位运算符包括按位与&#xff08;&&#xff09;、按位或&#xff08;|&#xff09;、按位异或&#xff08;^&#xff09;、取反&#xff08;~&#xff09;、左移&am…

芯课堂 | Synwit_UI_Creator(μgui)平台之图像处理篇

今天小编给大家介绍的是UI_Creator&#xff08;μgui&#xff09;平台下关于图像处理的选项。 UI_Creator&#xff08;μgui&#xff09;平台图片类控件有图像控件和分级图像控件&#xff0c;均包含以下选项&#xff1a; 1、消除水波纹&#xff1a; 由于16位真彩色&#xff08…

基础IO -- 理解文件(1)

目录 一&#xff1a;回顾文件 二&#xff1a;加深对文件的理解 1.概念 2.以w写方式打开 3.以a追加方式打开 4.重定向 一&#xff1a;回顾文件 以前学习过在C语言中的文件操作&#xff0c; 但那根本是不足以理解文件的&#xff0c;即站在语言角度是不可能理解文件的 我们要…

QT 中如何保存matlab 能打开的.mat数据矩阵!

Windows 上安装并使用 MATIO 库来保存 MATLAB 格式的 .mat 文件&#xff0c;需要进行以下步骤&#xff1a; 1. 下载并安装 CMake MATIO 使用 CMake 构建项目&#xff0c;因此你需要先安装 CMake。 前往 CMake 官网下载适用于 Windows 的安装程序并安装。 2. 下载 MATIO 库源…

说下SSL/TLS四次握手过程?

参考自&#xff1a;SSL/TLS四次握手过程是怎么样的&#xff1f;HTTPS、SSL、TLS三者之间的联系和区别 一.SSL/TLS 简介 SSL(Secure Socket Layer 安全套接层)是基于 HTTPS 下的一个协议加密层&#xff0c;用于解决 HTTP 在传输数据时使用明文而导致的不安全问题。 SSL 是 HT…

AD报错failed to add class member\net

什么原因导致的我到现在还没弄懂&#xff0c;总之解决方法是在PCB端删除所有现有的并且可删除的nets与components。下次问题复现了再补充截图&#xff08;不想再遇到了球球了这种玄学问题&#xff09;。 网络截图&#xff1a; 解决步骤&#xff1a;设计->类 把可删除的网络…

西门子828d的plc一些信息记录

1、虽然是200的plc但是引入了DB的形式替代原来的V存储区。 2、用户自定义DB块范围&#xff0c;DB9000-DB9063,共64个DB块。 可用地址范围如上图 机床MCP483面板地址表&#xff0c;其它类型的面板地址自己在828d简明调试手册里查看。 如何上载828d的plc程序&#xff1a; 1.通…

coze bot开发的最小实践

一、coze专业版开通 网站地址&#xff1a;扣子专业版-火山引擎 开通流程&#xff1a; 1."立即使用" 扣子专业版 1.点击【立即使用】2.登录账号(上一步已登录可跳过) 2.进行实名认证后&#xff0c;开启【扣子专业版】&#xff08;已认证可跳过&#xff09; 1. 前…

Mysql行转列的写法

一、何为行转列&#xff1f; 在搞清楚这一概率之前&#xff0c;不妨来认识一下我们mysql表二维表结构数据&#xff0c;例如学生成绩表格&#xff0c;属性有学生姓名&#xff0c;学生科目&#xff0c;成绩&#xff0c;表结构如下&#xff1a; CREATE TABLE test_9 (id int(11) …

Android map 获取值

Android Map 获取值的完整指南 在Android开发中&#xff0c;使用Map&#xff08;映射&#xff09;来存储和检索数据是非常常见的需求。Map是一种键值对集合&#xff0c;能够快速而高效地根据特定的键获取值。在这篇文章中&#xff0c;我们将深入探讨如何在Android应用中使用Ma…

Linux的zookeeper安装部署

1.zookeeper是一个分布式的,开放源码的分布式应用程序协调服务,是hadoop和HBASE的重要组件 2.下载zookeeper安装包zookeeper安装包https://archive.apache.org/dist/zookeeper/zookeeper-3.5.9/ 移动到Linux解压 解压到/export/server文件夹 命令: tar -xvf apache-zooke…