秒懂C++之stack、queue、堆

news2025/1/10 1:41:31

fe594ea5bf754ddbb223a54d8fb1e7bc.gif

目录

前言

一.stack常用接口

二.stack模拟实现

三.例题

3.1 最小栈

题目解析:

算法解析:

代码:

 3.2 栈的压入、弹出序列

题目解析:

算法解析:

代码:

3.3 逆波兰表达式求值

题目解析:

算法解析:

拓展:

代码:

四.queue常用接口

五.queue模拟实现

六.例题

6.1 二叉树的层序遍历

题目解析:

算法解析:

代码:

七.priority_queue常用接口

八.priority_queue模拟实现

8.1 仿函数

九.例题

9.1 数组中的第K个最大元素

题目解析:

算法解析:

代码:

十. 全部代码


前言

本次学习的容器在功能上基本与前面一致~对接口模拟感兴趣的友友们可以移步前面的文章:

秒懂C++之vector(下)-CSDN博客

秒懂C++之string类(下)-CSDN博客

本篇文章主要以算法题为主~

一.stack常用接口

二.stack模拟实现

namespace lj 
{
	template<class T>
	class stack
	{
		// ...
	private:
		T* _a;
		size_t _top;
		size_t _capacity;
	};
}

这是很传统的模拟实现~

template<class T, class Container = deque<T>>//给适配器搭配缺省参数
	class stack
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}

		void pop()
		{
			_con.pop_back();
		}

		const T& top()
		{
			return _con.back();
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.empty();
		}

	private:
		Container _con;
	};

这是加入了适配器后了模拟~ 

可以发现我们拿vector容器进行适配,后面的接口模拟只需要调用vector的接口实现就好了。

当然这前提当然是二者合适适配,栈里面有数组栈,也有链式栈。这意味它可以适配list与vector容器。而这里用deque容器作缺省是因为它同时具有前面二者的功能~

三.例题

3.1 最小栈

155. 最小栈 - 力扣(LeetCode)

 

题目解析:

通常想法是设置一个变量记录入栈时最小的那个数,遇到更小的就替换。但缺点是如果我们把3pop出去,那它还得重新再遍历对比一遍,效率太低了。

算法解析:

这里我们换一种思路,搞两个栈,其中一个栈用来记录数据出入,而另一个栈用来记录出入数中最小的存在~

代码:

class MinStack {
public:
    MinStack() {
        //可以用默认构造,不用写~
    }

    void push(int val) {
        _stack.push(val);
        if (_minstack.empty() || _stack.top() <= _minstack.top())//minst只有在空或者入栈的数比之前记录的还小才可以进来
        {
            _minstack.push(val);
        }

    }

    void pop() {
        if (_stack.top() == _minstack.top())//stack出栈的时候还要观察minst里面是否也要跟着出
        {
            _minstack.pop();
        }
        _stack.pop();
    }

    int top() {
        return _stack.top();
    }

    int getMin() {
        return _minstack.top();
    }
    stack<int> _stack;
    stack<int> _minstack;
};

 3.2 栈的压入、弹出序列

栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com)

题目解析:

本题核心就在于我们在入栈的同时也可以出栈,这样就能先理解哪些弹出序列是对是错了~

算法解析:

我们思路很简单,就一直对入栈数组进行入栈,直到我们能够在栈顶找到与出栈数组一致的数,那时候就出栈,然后再选定出栈数组的下一个数。就这样以此类推直到出栈数组里面的数可以全部出光那就证明这是一个合格的弹出序列~

代码:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param pushV int整型vector
     * @param popV int整型vector
     * @return bool布尔型
     */
    bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
        // write code here
        stack<int> _st;
        int pushi = 0;
        int popj = 0;
        while (pushi < pushV.size())//只要栈没入完就继续入
        {
            _st.push(pushV[pushi]);
            pushi++;
            while (!_st.empty() && _st.top() == popV[popj])//只要st栈不为空并且和popV值一样就可以出栈,这里得用while是因为可能会连续出栈
            {
                _st.pop();
                popj++;
            }
        }
        return popj == popV.size();
    }
};

3.3 逆波兰表达式求值

150. 逆波兰表达式求值 - 力扣(LeetCode)

题目解析:

本质就是要把后缀表达式转化为中缀表达式进行运算。

算法解析:

后缀表达式如何转中缀表达式如上图所示,在书面上我们可以直接模拟出结果,而在题目中我们可以利用栈来帮助我们实现最终结果。

拓展:

中缀表达式转化为后缀表达式

之所以操作符优先级比栈顶高要入栈是因为还无法确定后面的运算符是否更大,而一旦确定当前操作符比栈顶优先级相等或低就可以立马出栈运算~

ps:如果遇到括号怎么办呢?a+b*c-d/(e+a*b)

我们要知道括号最终的运算结果本身也只是一个数字罢了,我们可以采用递归的策略让其直接返回结果即可,左括号(进入递归,右括号)递归结束返回结果~最后再和上述一致推出中缀表达式即可~

代码:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(auto& e: tokens)//记得&,因为为string类
        {
            if(e=="+"||e=="-"||e=="*"||e=="/")
            {
                int right = st.top();
                st.pop();
                int left = st.top();
                st.pop();

                switch(e[0])//switch条件不支持字符串
                {
                    case '+':
                        st.push(left+right);
                        break;
                    case '-':
                        st.push(left-right);
                        break;
                    case '*':
                        st.push(left*right);
                        break; 
                    case '/':
                        st.push(left/right);
                        break;
                }
            }
            else
            {
                st.push(stoi(e));
            }
        }
        return st.top();
    }
};

四.queue常用接口

五.queue模拟实现

template<class T, class Container = deque<T>>//给适配器搭配缺省参数
	class queue
	{
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}

		void pop()
		{
			_con.pop_front();
		}

		const T& front()
		{
			return _con.front();
		}

		const T& back()
		{
			return _con.back();
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.empty();
		}

	private:
		Container _con;
	};

我们再来对队列进行适配器的使用~可以发现只需要稍微合理调用适配器的接口函数就可以帮我们实现出模拟的效果了。

注意:这里不能用vector作为适配器,因为它不具备头删的接口~

六.例题

6.1 二叉树的层序遍历

102. 二叉树的层序遍历 - 力扣(LeetCode)

题目解析:

层序遍历我们一般都是利用队列进行操作,一层出完的同时就会带入下一层

算法解析:

一开始我们可以用一个变量Levsize来记录该层数的节点个数,排出一个节点我们就自减,直到减为0就可以认为当前层数已经全部遍历完毕,最后再把当前层数的节点记录即可。

而我们在排出的过程中又会带入下一层的节点,我们下一层的Levsize更新就是数队列内数据的个数即可,用它们的个数来作为新一层是否遍历完毕的结果~

代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> vv;
        queue<TreeNode*> q;
        int Levsize = 0;
        if(root)
        {
            q.push(root);
            Levsize =1;
        }
        while(!q.empty())
        {
            vector<int> v;
            while(Levsize--)//代表需要出栈
            {
                TreeNode* node = q.front();//记录节点
                q.pop();

                v.push_back(node->val);//上传该节点数据
                
                if(node->left)
                {
                    q.push(node->left);
                }
                if(node->right)
                {
                    q.push(node->right);
                }
            }
            //该层遍历结束,更新下一层的个数
            Levsize = q.size();
            vv.push_back(v);//把该层数据上传

        }
        return vv;

    }
};

七.priority_queue常用接口

八.priority_queue模拟实现

template<class T, class Container = vector<T>>
	class priority_queue
	{
	public:
		void adjust_up(int child)
		{
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_con[child] > _con[parent])
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void adjust_down(int parent)
		{
			int child = parent * 2 + 1;

			while (child < _con.size())
			{
				if (child + 1 < _con.size() && _con[child + 1] > _con[child])
				{
					++child;
				}

				if (_con[child] > _con[parent])
				{
					swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}

		void push(const T& x)
		{
			_con.push_back(x);

			adjust_up(_con.size() - 1);
		}

		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();

			adjust_down(0);
		}

		const T& top()
		{
			return _con[0];
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.empty();
		}
	private:
		Container _con;
	};

堆的模拟实现合适的适配器是vector,关键在于[ ]的调用~

无论是尾插还是删除本质默认都是为了形成或维护大堆,如果我们想要形成小堆那就得把两个调整法中的大于号改成小于号~

有没有一种办法能在构建对象的时候就能指定想要的运算符从而改变堆的结构呢?——仿函数

8.1 仿函数

namespace lj
{
	template<class T>
	class less
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};

	template<class T>
	class greater
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};
}

仿函数本质是对()进行函数重载,我们分别封装出<(less)与>(greater)的类。

九.例题

9.1 数组中的第K个最大元素

215. 数组中的第K个最大元素 - 力扣(LeetCode)

题目解析:

这种我们一眼就知道可以使用堆来解答了~

算法解析:

可以去看之前写的文章哦,那里讲得很清楚~:数据结构——二叉树的基本概念及顺序存储(堆)_头歌数据结构二叉树的顺序存储及基本操作-CSDN博客

代码:

第一种解法:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        //k*logN
        priority_queue<int> pq(nums.begin(),nums.end());//直接通过nums来进行初始化建大堆

        while(--k)//--k,k会走k-1次,把前k-1个pop掉
        {
            pq.pop();
        }
        return pq.top();
    }
};

第二种解法:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        //当k很大时
        priority_queue<int,vector<int>,greater<int>> pq(nums.begin(),nums.begin()+k);//建立k个数的小堆
        //(N-k)*logK
        for(int i = k;i<nums.size();i++)
        {
            if(nums[i]>pq.top())
            {
                pq.pop();
                pq.push(nums[i]);
            }
        }

        return pq.top();
    }
};

十. 全部代码

//stack_queue
#pragma once
namespace lj 
{
	//template<class T>
	//class stack
	//{
	//	// ...
	//private:
	//	T* _a;
	//	size_t _top;
	//	size_t _capacity;
	//};
	//template<class T, class Container = deque<T>>//给适配器搭配缺省参数
	//class stack
	//{
	//public:
	//	void push(const T& x)
	//	{
	//		_con.push_back(x);
	//	}

	//	void pop()
	//	{
	//		_con.pop_back();
	//	}

	//	const T& top()
	//	{
	//		return _con.back();
	//	}

	//	size_t size()
	//	{
	//		return _con.size();
	//	}

	//	bool empty()
	//	{
	//		return _con.empty();
	//	}

	//private:
	//	Container _con;
	//};
	//template<class T, class Container = deque<T>>//给适配器搭配缺省参数
	//class queue
	//{
	//public:
	//	void push(const T& x)
	//	{
	//		_con.push_back(x);
	//	}

	//	void pop()
	//	{
	//		_con.pop_front();
	//	}

	//	const T& front()
	//	{
	//		return _con.front();
	//	}

	//	const T& back()
	//	{
	//		return _con.back();
	//	}

	//	size_t size()
	//	{
	//		return _con.size();
	//	}

	//	bool empty()
	//	{
	//		return _con.empty();
	//	}

	//private:
	//	Container _con;
	//};


	template<class T, class Container = vector<T>,class Compare = lj::less<int>>//类模板加入仿函数
	class priority_queue
	{
	public:
		Compare _com;//定义所需要运算符的类对象
		void adjust_up(int child)
		{
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				if (_com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}

		void adjust_down(int parent)
		{
			int child = parent * 2 + 1;

			while (child < _con.size())
			{
				if (child + 1 < _con.size() && _com(_con[child], _con[child + 1]))
				{
					++child;
				}

				if (_com(_con[parent], _con[child]))
				{
					swap(_con[child], _con[parent]);
					parent = child;
					child = parent * 2 + 1;
				}
				else
				{
					break;
				}
			}
		}

		void push(const T& x)
		{
			_con.push_back(x);

			adjust_up(_con.size() - 1);
		}

		void pop()
		{
			swap(_con[0], _con[_con.size() - 1]);
			_con.pop_back();

			adjust_down(0);
		}

		const T& top()
		{
			return _con[0];
		}

		size_t size()
		{
			return _con.size();
		}

		bool empty()
		{
			return _con.empty();
		}
	private:
		Container _con;
	};

	void test()
	{
		/*stack<int, vector<int>> st;
		st.push(1);
		st.push(1);
		st.push(1);
		st.push(1);
		while (!st.empty())
		{
			cout << st.top() << " ";
			st.pop();
		}
		cout << endl;*/
		/*queue<int> q;
		q.push(1);
		q.push(1);
		q.push(1);
		q.push(1);
		while (!q.empty())
		{
			cout << q.front() << " ";
			q.pop();
		}
		cout << endl;*/

		//priority_queue<int> pq;//默认适配器vector,默认运算符小于号——形成大堆
		//pq.push(1);
		//pq.push(2);
		//pq.push(2);
		//pq.push(3);
		//pq.push(6);
		//while (!pq.empty())
		//{
		//	cout << pq.top() << " ";
		//	pq.pop();
		//}
		//cout << endl;
		priority_queue<int,vector<int>,greater<int>> pq1;//适配器vector,运算符大于号——形成小堆
		pq1.push(6);
		pq1.push(5);
		pq1.push(4);
		pq1.push(3);
		pq1.push(2);
		while (!pq1.empty())
		{
			cout << pq1.top() << " ";
			pq1.pop();
		}
		cout << endl;
	}
}
//test.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <vector>
#include <list>
#include <queue>
#include <stack>


using namespace std;



namespace lj
{
	template<class T>
	class less
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x < y;
		}
	};

	template<class T>
	class greater
	{
	public:
		bool operator()(const T& x, const T& y)
		{
			return x > y;
		}
	};
}

#include "stack_queue.h"
int main()
{
	lj::test();

	return 0;
}




//
//class MinStack {
//public:
//    MinStack() {
//        //可以用默认构造,不用写~
//    }
//
//    void push(int val) {
//        _stack.push(val);
//        if (_minstack.empty() || _stack.top() <= _minstack.top())//minst只有在空或者入栈的数比之前记录的还小才可以进来
//        {
//            _minstack.push(val);
//        }
//
//    }
//
//    void pop() {
//        if (_stack.top() == _minstack.top())//stack出栈的时候还要观察minst里面是否也要跟着出
//        {
//            _minstack.pop();
//        }
//        _stack.pop();
//    }
//
//    int top() {
//        return _stack.top();
//    }
//
//    int getMin() {
//        return _minstack.top();
//    }
//    stack<int> _stack;
//    stack<int> _minstack;
//};
//
//class Solution {
//public:
//    /**
//     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
//     *
//     *
//     * @param pushV int整型vector
//     * @param popV int整型vector
//     * @return bool布尔型
//     */
//    bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
//        // write code here
//        stack<int> _st;
//        int pushi = 0;
//        int popj = 0;
//        while (pushi < pushV.size())//只要栈没入完就继续入
//        {
//            _st.push(pushV[pushi]);
//            pushi++;
//            while (!_st.empty() && _st.top() == popV[popj])//只要st栈不为空并且和popV值一样就可以出栈,这里得用while是因为可能会连续出栈
//            {
//                _st.pop();
//                popj++;
//            }
//        }
//        return popj == popV.size();
//    }
//};
//
//class Solution {
//public:
//    int evalRPN(vector<string>& tokens) {
//        stack<int> st;
//        for (auto& e : tokens)//记得&,因为为string类
//        {
//            if (e == "+" || e == "-" || e == "*" || e == "/")
//            {
//                int right = st.top();
//                st.pop();
//                int left = st.top();
//                st.pop();
//
//                switch (e[0])//switch条件不支持字符串
//                {
//                case '+':
//                    st.push(left + right);
//                    break;
//                case '-':
//                    st.push(left - right);
//                    break;
//                case '*':
//                    st.push(left * right);
//                    break;
//                case '/':
//                    st.push(left / right);
//                    break;
//                }
//            }
//            else
//            {
//                st.push(stoi(e));
//            }
//        }
//        return st.top();
//    }
//};
//
//
///**
// * Definition for a binary tree node.
// * struct TreeNode {
// *     int val;
// *     TreeNode *left;
// *     TreeNode *right;
// *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
// *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
// *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
// * };
// */
//class Solution {
//public:
//    vector<vector<int>> levelOrder(TreeNode* root) {
//        vector<vector<int>> vv;
//        queue<TreeNode*> q;
//        int Levsize = 0;
//        if (root)
//        {
//            q.push(root);
//            Levsize = 1;
//        }
//        while (!q.empty())
//        {
//            vector<int> v;
//            while (Levsize--)//代表需要出栈
//            {
//                TreeNode* node = q.front();//记录节点
//                q.pop();
//
//                v.push_back(node->val);//上传该节点数据
//
//                if (node->left)
//                {
//                    q.push(node->left);
//                }
//                if (node->right)
//                {
//                    q.push(node->right);
//                }
//            }
//            //该层遍历结束,更新下一层的个数
//            Levsize = q.size();
//            vv.push_back(v);//把该层数据上传
//
//        }
//        return vv;
//
//    }
//};
//
//class Solution {
//public:
//    int findKthLargest(vector<int>& nums, int k) {
//        //当k很大时
//        priority_queue<int, vector<int>, greater<int>> pq(nums.begin(), nums.begin() + k);//建立k个数的小堆
//
//        for (int i = k; i < nums.size(); i++)
//        {
//            if (nums[i] > pq.top())
//            {
//                pq.pop();
//                pq.push(nums[i]);
//            }
//        }
//
//        return pq.top();
//    }
//};
//class Solution {
//public:
//    int findKthLargest(vector<int>& nums, int k) {
//        //k*logN
//        priority_queue<int> pq(nums.begin(), nums.end());//直接通过nums来进行初始化建大堆
//
//        while (--k)//--k,k会走k-1次,把前k-1个pop掉
//        {
//            pq.pop();
//        }
//        return pq.top();
//    }
//};

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

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

相关文章

【Web】从TFCCTF-FUNNY浅析PHPCGI命令行注入漏洞利用

目录 背景 CVE-2012-1823 发散利用 法一&#xff1a;读文件 法二&#xff1a;数据外带 背景 CVE-2012-1823 PHP-CGI远程代码执行漏洞&#xff08;CVE-2012-1823&#xff09;分析 | 离别歌 省流&#xff1a; 命令行参数不光可以通过#!/usr/local/bin/php-cgi -d include…

目标检测 | yolov4 原理和介绍

1. 简介 YOLOv4是一种高效且准确的目标检测模型&#xff0c;它在YOLOv3的基础上引入了多项改进&#xff0c;这些改进主要集中在网络结构的优化和训练技巧的更新上。以下是YOLOv4中的一些关键技术或模块&#xff0c;它们对提高目标检测性能起到了重要作用&#xff1a; CSPDarkne…

MATLAB基础应用精讲-【数模应用】配对样本Wilcoxon检验(附MATLAB、R语言和python代码实现)

目录 知识储备 常用的统计假设检验的方法 算法原理 什么是Wilcoxon符号秩检验? 何时使用Wilcoxon符号秩检验 适用条件 SPSS-符号秩检验 一统计理论 二实例分析 三拓展知识 SAS --配对样本Wilcoxon符号秩检验 SPSSAU 配对样本Wilcoxon检验案例 1、背景 2、理论 …

【C++指南】函数重载:多态性的基石

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 目录 引言 一、函数重载的概念 二、函数重载的原理 三、函数重载的应用场景 四、函数重载的规则 五…

springboot整合libreoffice(两种方式,使用本地和远程的libreoffice);docker中同时部署应用和libreoffice

一、 背景 因为项目中需要使用word转pdf功能&#xff0c;因为转换速度原因&#xff0c;最后选用了libreoffice&#xff0c;原因及部署请参考 linux ubuntu环境安装libreoffice&#xff0c;word转pdf 远程调用的话可选docker部署&#xff0c;请看2.3.1 二、springboot整合libr…

AT指令处理框架

<AT框架>做什么 <AT框架>介绍 ATFrame 流程 开启AT流程: ATCommandRegister(CSQ,EXEXCMD,NULL); 发送消息队列xQueueSend(ATcmdQueue,(void *) &RegcommandInfo,(TickType_t)100) AT主流程 ATCommandSendScheduler 等待开启xQueueReceive(ATcmdQueue, (voi…

详细分析python下载文件的两种方式(附Demo)

目录 前言1. 接口方式2. Nginx 前言 基本项目的构建推荐阅读&#xff1a;构建Flask前后端不分离项目&#xff08;附Python Demo&#xff09; 对于Java的基本知识&#xff0c;推荐阅读&#xff1a; java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&…

Unknown input format pdf Pandoc can convert to PDF, but not from PDF.解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【Lua运行环境安装及配置】

首先在百度搜索“Lua菜鸟教程” 网址&#xff1a;Lua 教程 | 菜鸟教程 (runoob.com) 找到环境安装 点击Github下载地址&#xff0c;GitHub可以在正规上网下进入网址&#xff08;页面更新不出来多试几次&#xff09; 点击.exe安装 下载完成后进行安装 可自定义磁盘 项目文件很…

线程局部变量(ThreadLocal)

线程局部变量&#xff08;ThreadLocal&#xff09; 1、什么是ThreadLocal&#xff1f;2、基本用法3、注意事项 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1、什么是ThreadLocal&#xff1f; ThreadLocal 是 Java 中用于实现线程局部变…

IEC 61850标准协议解读 1.建模讲解

IEC61850协议标准和之前的101、104协议最大的区分就是在模型这里&#xff0c;模型可以说是一个变电站里面的智能设备的定义&#xff0c;里面定义了网络连接信息、数据上报方式、设备访问控制点等&#xff0c;所以说在不同系统的对接过程中&#xff0c;有了这么一个基于标准定义…

sqliabs靶场练习

关卡 熟悉Mqsql相关命令Less-1Less-2Less-3Less-4Less-5Less-6Less-7Less-8Less-9Less-10 熟悉Mqsql相关命令 首先先熟悉一下Mysql的相关命令&#xff0c;可能在SQL注入的时候会用到。 1.查询服务器主机信息 HOSTNAME 主机名称 datadir——数据库路径 version_compile_os—…

JavaDS —— 红黑树

前言 还是一样&#xff0c;这里的红黑树重点讲述插入代码的实现&#xff0c;如果对红黑树的删除感兴趣&#xff0c;可以去翻阅其他资料。 在数据结构专栏中已经对 AVL 树的旋转调整做了分析和讲解&#xff0c;这里红黑树也会使用到旋转调整的代码&#xff0c;就不讲述旋转代码…

成都云飞浩容文化传媒有限公司怎么样可靠吗?

在数字经济浪潮汹涌的今天&#xff0c;电商行业作为推动经济高质量发展的关键引擎&#xff0c;正以前所未有的速度重塑着商业版图。在这场变革中&#xff0c;成都云飞浩容文化传媒有限公司凭借其专业的电商服务能力和前瞻性的市场洞察&#xff0c;成为了众多品牌商家信赖的合作…

助力草莓智能自动化采摘,基于嵌入式端超轻量级模型LeYOLO全系列【n/s/m/l】参数模型开发构建果园种植采摘场景下草莓成熟度智能检测识别系统

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经渗透到我们生活的方方面面&#xff0c;从智能家居到自动驾驶&#xff0c;再到医疗健康&#xff0c;其影响力无处不在。然而&#xff0c;当我们把目光转向中国的农业领域时&#xff0c;一个令人惊讶的…

Git分布式版本控制--2+day018 LeetCode235 701 450

基础操作: 1.分支: 几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离 开来进行重大的Bug修改、开发新的功能&#xff0c;以免影响开发主线。 2.指令操作: 2.1 查看本地分支: git branch 2.2 创建本地分支: git branch 分支名…

Spring Boot 3.3 新特性介绍

1. 引言 Spring Boot 3.1.x 停止维护了&#xff0c;而 3.3.x 作为最新发布的版本&#xff0c;带来了许多新特性和改进。本篇文章将详细介绍这些新特性&#xff0c;并通过样例代码加以解释&#xff0c;帮助开发者更好地掌握和应用这些新功能。 Spring Boot 3.3现已正式发布&…

RNN循环网络层

文章目录 1、简介2、RNN 网络原理3、PyTorch RNN 层的使用3.1、RNN送入单个数据3.2、RNN层送入批量数据 4、RNN三个维度4.1、解释4.2、输入数据的组织4.3、示例4.4、为什么需要这种格式&#xff1f;4.5、小结 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&a…

【博士每天一篇文献-算法】持续学习经典算法之LwF: Learning without forgetting

1 介绍 年份&#xff1a;2017 作者&#xff1a;Zhizhong Li&#xff0c;Amazon AWS Rekognition&#xff1b;Derek Hoiem&#xff0c;伊利诺伊大学计算机科学教授 会议&#xff1a;IEEE transactions on pattern analysis and machine intelligence 引用量&#xff1a;4325 Li…

【NXP-MCXA153】开发板救砖教程

前言 新手接触到NXP的板子时&#xff0c;一个不留神把调试的GPIO&#xff08;RXD、TXD&#xff09;改掉&#xff0c;很容易出现MDK Keil无法识别CMSIS-DAP调试器的情况&#xff1b;主控进入了莫名其妙模式导致调试器无法识别了&#xff0c;你根本无法下载程序&#xff0c;想改…