目录

1.反向迭代器思路及实现

1.1. 源码及框架分析

1.2. 实现反向迭代器

2.stack和queue练习拓展-计算器实现

2.1. 后缀表达式概念

2.2. 后缀表达式运算规则

2.3. 中缀表达式转后缀表达式

2.3.1 转换思路

2.3.2 代码实现

2.4. 计算器实现


1.反向迭代器思路及实现

1.1. 源码及框架分析

SGI-STL30版本源代码,反向迭代器实现的核心源码在stl_iterator.h中。

前文我们了解到了正向迭代器是基于原生指针的封装实现,反向迭代器的逻辑与正向迭代器的逻辑正好相反,代码应该高度相似,因此在学习了stack与queue之后,明白了适配器思想,我们就复用正向迭代器代码实现反向迭代器,减少代码冗余。

下面我们截出vector和list的的反向迭代器结构框架核心部分截取出来如下:

// stl_list.h
template <class T, class Alloc = alloc>
class list {
public:typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATIONtypedef reverse_iterator<const_iterator> const_reverse_iterator;typedef reverse_iterator<iterator> reverse_iterator;
#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */typedef reverse_bidirectional_iterator<const_iterator, value_type,const_reference, difference_type> const_reverse_iterator;typedef reverse_bidirectional_iterator<iterator, value_type, reference,difference_type> reverse_iterator;
#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */iterator begin() { return (link_type)((*node).next); }const_iterator begin() const { return (link_type)((*node).next); }iterator end() { return node; }const_iterator end() const { return node; }reverse_iterator rbegin() { return reverse_iterator(end()); }const_reverse_iterator rbegin() const {returnconst_reverse_iterator(end());}reverse_iterator rend() { return reverse_iterator(begin()); }const_reverse_iterator rend() const {returnconst_reverse_iterator(begin());}
};
// stl_vector.h
template <class T, class Alloc = alloc>
class vector {
public:typedef T value_type;typedef value_type* iterator;
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATIONtypedef reverse_iterator<const_iterator> const_reverse_iterator;typedef reverse_iterator<iterator> reverse_iterator;
#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */typedef reverse_iterator<const_iterator, value_type, const_reference,difference_type> const_reverse_iterator;typedef reverse_iterator<iterator, value_type, reference, difference_type>reverse_iterator;
#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */iterator begin() { return start; }const_iterator begin() const { return start; }iterator end() { return finish; }const_iterator end() const { return finish; }reverse_iterator rbegin() { return reverse_iterator(end()); }const_reverse_iterator rbegin() const {returnconst_reverse_iterator(end());}reverse_iterator rend() { return reverse_iterator(begin()); }const_reverse_iterator rend() const {returnconst_reverse_iterator(begin());}
};
// stl_iterator.h
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
// This is the new version of reverse_iterator, as defined in the
// draft C++ standard. It relies on the iterator_traits template,
// which in turn relies on partial specialization. The class
// reverse_bidirectional_iterator is no longer part of the draft
// standard, but it is retained for backward compatibility.
template <class Iterator>
class reverse_iterator
{
protected:Iterator current;
public:typedef typename iterator_traits<Iterator>::iterator_categoryiterator_category;typedef typename iterator_traits<Iterator>::value_typevalue_type;typedef typename iterator_traits<Iterator>::difference_typedifference_type;typedef typename iterator_traits<Iterator>::pointerpointer;typedef typename iterator_traits<Iterator>::referencereference;typedef Iterator iterator_type;typedef reverse_iterator<Iterator> self;
public:reverse_iterator() {}explicit reverse_iterator(iterator_type x) : current(x) {}reverse_iterator(const self& x) : current(x.current) {}
#ifdef __STL_MEMBER_TEMPLATEStemplate <class Iter>reverse_iterator(const reverse_iterator<Iter>& x) : current(x.current) {}
#endif /* __STL_MEMBER_TEMPLATES */iterator_type base() const { return current; }reference operator*() const {Iterator tmp = current;return *--tmp;}
#ifndef __SGI_STL_NO_ARROW_OPERATORpointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */self& operator++() {--current;return *this;}self operator++(int) {self tmp = *this;--current;return tmp;}self& operator--() {++current;return *this;}self operator--(int) {self tmp = *this;++current;return tmp;}self operator+(difference_type n) const {return self(current - n);}self& operator+=(difference_type n) {current -= n;return *this;}self operator-(difference_type n) const {return self(current + n);}self& operator-=(difference_type n) {current += n;return *this;}reference operator[](difference_type n) const { return *(*this + n); }
};
template <class Iterator>
inline bool operator==(const reverse_iterator<Iterator>& x,const reverse_iterator<Iterator>& y) {return x.base() == y.base();
}
template <class Iterator>
inline bool operator<(const reverse_iterator<Iterator>& x,const reverse_iterator<Iterator>& y) {return y.base() < x.base();
}
template <class Iterator>
inline typename reverse_iterator<Iterator>::difference_type
operator-(const reverse_iterator<Iterator>& x,const reverse_iterator<Iterator>& y) {return y.base() - x.base();
}
template <class Iterator>
inline reverse_iterator<Iterator>
operator+(reverse_iterator<Iterator>::difference_type n,const reverse_iterator<Iterator>& x) {return reverse_iterator<Iterator>(x.base() - n);
}
#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
// This is the old version of reverse_iterator, as found in the original
// HP STL. It does not use partial specialization.
template <class BidirectionalIterator, class T, class Reference = T&,class Distance = ptrdiff_t>
class reverse_bidirectional_iterator {typedef reverse_bidirectional_iterator<BidirectionalIterator, T, Reference,Distance> self;
protected:BidirectionalIterator current;
public:typedef bidirectional_iterator_tag iterator_category;typedef T value_type;typedef Distance difference_type;typedef T* pointer;typedef Reference reference;reverse_bidirectional_iterator() {}explicit reverse_bidirectional_iterator(BidirectionalIterator x): current(x) {}BidirectionalIterator base() const { return current; }Reference operator*() const {BidirectionalIterator tmp = current;return *--tmp;}
#ifndef __SGI_STL_NO_ARROW_OPERATORpointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */self& operator++() {--current;return *this;}self operator++(int) {self tmp = *this;--current;return tmp;}self& operator--() {++current;return *this;}self operator--(int) {self tmp = *this;++current;return tmp;}
};
template <class RandomAccessIterator, class T, class Reference = T&,class Distance = ptrdiff_t>
class reverse_iterator {typedef reverse_iterator<RandomAccessIterator, T, Reference, Distance>self;
protected:RandomAccessIterator current;
public:typedef random_access_iterator_tag iterator_category;typedef T value_type;typedef Distance difference_type;typedef T* pointer;typedef Reference reference;reverse_iterator() {}explicit reverse_iterator(RandomAccessIterator x) : current(x) {}RandomAccessIterator base() const { return current; }Reference operator*() const { return *(current - 1); }
#ifndef __SGI_STL_NO_ARROW_OPERATORpointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */self& operator++() {--current;return *this;}self operator++(int) {self tmp = *this;--current;return tmp;}self& operator--() {++current;return *this;}self operator--(int) {self tmp = *this;++current;return tmp;}self operator+(Distance n) const {return self(current - n);}self& operator+=(Distance n) {current -= n;return *this;}self operator-(Distance n) const {return self(current + n);}self& operator-=(Distance n) {current += n;return *this;}Reference operator[](Distance n) const { return *(*this + n); }
};
#endif //__STL_CLASS_PARTIAL_SPECIALIZATION

• 源码中我们可以看到reverse_iterator实现了两个版本,通过
__STL_CLASS_PARTIAL_SPECIALIZATION 条件编译控制使用哪个版本,在旧版本中,因为因为封装是类型不好确定,我们需要自己传递参数,而有了萃取技术后,我们可以得到对应的类型,因此就不需要传递很多参数。

简单点说就是支持偏特化的迭代器萃取以后,反向迭代器使用的是这个版本, template <class Iterator>class reverse_iterator(一个参数); 之前使用的是template <class BidirectionalIterator, class T, class Reference,class Distance>class reverse_bidirectional_iterator;template <class RandomAccessIterator, class T, class Reference,class Distance>class reverse_iterator;(多个参数)


• 我们可以看到他们的差别主要是在模板参数是否传递迭代器指向的数据类型,支持偏特化的迭代器萃取以后就不需要给了,因为reverse_iterator 内部可以通过迭代器萃取获取数据类型。迭代器萃取的本质是一个特化(这里我们就不讲解了),想了解可以去看源码。

本文这里我们为了便于理解,我们主要使用模版参数传递数据类型的方式实现。


• 反向迭代器本质是一个适配器,使用模版实现,传递哪个容器的迭代器就可以封装适配出对应的反向迭代器。因为反向迭代器的功能跟正向的迭代器功能高度相似,只是遍历的方向相反,类似operator++ 底层调用迭代器的operator-- 等,所以封装一下就可以实现。


• 比较奇怪的是operator*的实现,源码内部访问的是迭代器当前位置的前一个位置

这个要结合容器中rbegin和rend实现才能看懂,rbegin返回的是封装end位置的反向迭代器,rend返回的是封装begin位置迭代器的反向迭代器,这里是为了与正向迭代器对应,专门实现出一个对称版本,begin与rend,end与rbegin,所以解引用访问的是当前位置的前一个位置,这样返回解引用rbegin时,返回上一个节点,即返回有效节点的最后一个节点,解引用rend就会正好返回哨兵节点。(这里没有其他的特殊作用,如果愿意也可以不对称实现)

1.2. 实现反向迭代器

// ReverseIterator.h
// 所有容器的反向迭代器
// 迭代器适配器
namespace zlr
{template<class Iterator, class Ref, class Ptr>struct ReverseIterator{typedef ReverseIterator<Iterator, Ref, Ptr> Self;// 正向迭代器Iterator _it;ReverseIterator(Iterator it):_it(it){}Ref operator*(){Iterator tmp = _it;return *(--tmp);}Ptr operator->(){return &(operator*());}Self& operator++(){--_it;return *this;}Self& operator--(){++_it;return *this;}Self operator++(int){Self tmp(*this);--_it;return tmp;}Self operator--(int){Self tmp(*this);--_it;return tmp;}bool operator!=(const Self& s) const{return _it != s._it;}bool operator==(const Self& s) const{return _it != s._it;}};
}
// vector.h
#include"ReverseIterator.h"
namespace zlr
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;typedef ReverseIterator<iterator, T&, T*> reverse_iterator;typedef ReverseIterator<const_iterator, const T&, const T*>const_reverse_iterator;reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}const_reverse_iterator rbegin() const{return const_reverse_iterator(end());}const_reverse_iterator rend() const{return const_reverse_iterator(begin());}iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}// ....private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;};
}
// list.h
#include"ReverseIterator.h"
namespace zlr
{template<class T>class list{typedef ListNode<T> Node;public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;typedef ReverseIterator<iterator, T&, T*> reverse_iterator;typedef ReverseIterator<const_iterator, const T&, const T*>const_reverse_iterator;reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}const_reverse_iterator rbegin() const{return const_reverse_iterator(end());}const_reverse_iterator rend() const{return const_reverse_iterator(begin());}iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}// ...private:Node* _head;size_t _size;};
}
// test.cpp
#include"list.h"
#include"vector.h"
int main()
{zlr::list<int> lt = { 1,2,3,4 };zlr::list<int>::reverse_iterator rit = lt.rbegin();while (rit != lt.rend()){//*rit = 1;cout << *rit << " ";++rit;}cout << endl;return 0;
}
//int main()
//{
// zlr::vector<int> v = { 1,2,3,4 };
// zlr::vector<int>::reverse_iterator rit = v.rbegin();
// while (rit != v.rend())
// {
// //*rit = 1;
// cout << *rit << " ";
// ++rit;
// }
// cout << endl;
//
// return 0;
//}

2.stack和queue练习拓展-计算器实现

2.1. 后缀表达式概念

• 我们日常写的计算表达式都是中缀表达式,也就是运算符在中间,运算数在两边,但是中缀表达式直接读取无法马上进行运算,因为一个计算表达式还涉及运算符优先级问题,中缀表达式无法直接确定一个运算符优先级,必须根据相邻运算符才能确定。如: 1-2*(3-4)+5 中遇到-和*都无法运算,因为后面还有括号优先级更高。


• 所以其中一种实现思路是把中缀表达式转换为后缀表达式,也就是说分析计算表达式的优先级,将运算符放到前面,运算符放到运算数的后面,然后我们依次读取后缀表达式,遇到运算符就可以进行运算了。后缀表达式也就做逆波兰表达式(Reverse Polish Notation, RPN),这种表示法由波兰逻辑学家J·卢卡西维兹于1929年提出,后来被广泛应用于计算机科学中。

2.2. 后缀表达式运算规则

• 后缀表达式因为已经确定好优先级,运算符方式非常简单,就是遇到运算符时取前面的两个数进行运算,因为经过中缀转后缀优先级已经确定好了,因此我们根据运算特点,使用栈来实现。


• 建立一个存储运算数,读取后缀表达式,遇到运算数入栈遇到运算符出栈顶的两个数据进行运算运算后将结果作为一个运算数入栈继续参与下一次的运算。读取表达式结束后,最后栈里面的值就是运算结果。

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

class Solution {
public:int evalRPN(const vector<string>& tokens) {stack<int> s;for (size_t i = 0; i < tokens.size(); ++i){const string& str = tokens[i];// str为运算数,入栈if (!("+" == str || "-" == str || "*" == str || "/" == str)){s.push(stoi(str));}else{// str为运算符,取前两个运算数进行运算int right = s.top();s.pop();int left = s.top();s.pop();switch (str[0]){case '+':s.push(left + right);break;case '-':s.push(left - right);break;case '*':s.push(left * right);break;case '/':s.push(left / right);break;}}}return s.top();}
};

2.3. 中缀表达式转后缀表达式

2.3.1 转换思路

• 依次读取计算表达式中的值,遇到运算数直接输出


• 建立一个栈存储运算符,利用栈后进新出性质,遇到后面运算符,出栈里面存的前面运算符进行比较,确定优先级。


遇到运算符,如果栈为空或者栈不为空且当前运算符比栈顶运算符优先级高,则当前运算符入栈。因为如果栈里面存储的是前一个运算符,当前运算符比前一个优先级高,说明前一个不能运算,当前运算符也不能运算,因为后面可能还有更高优先级的运算符。


遇到运算符如果栈不为为空且当前运算符比栈顶运算符优先级低或相等,说明栈顶的运算符可以运算了,则输出栈顶运算符,当前运算符继续走前面遇到运算符的逻辑。


如果遇到(),则把括号的计算表达式当成一个子表达式进行递归,跟上思路类似处理子表达式,处理后转换出的后缀表达式加在前面表达式的后面即可


• 计算表达式或者()中子表达式结束时,输出栈中所有运算符

2.3.2 代码实现

class Solution {
public://map<char, int> _operatorPrecedence = { { '+', 1 }, { '-', 1 }, { '*', 2//}, { '/', 2 } };//因为运算符优先级与ASCII无关,这里我们使用结构体来处理运算符的优先级比较问题//如果学习过map容器,可以使用map处理int operatorPrecedence(char ch){struct opPD{char _op;int _pd;};static opPD arr[] = { {'+', 1},{'-', 1},{'*', 2},{'/', 2} };for (auto& e : arr){if (e._op == ch){return e._pd;}}assert(false);return -1;}//因为有递归的情况存在,我们这里使用i来记录当前访问位置void toRPN(const string& s, size_t& i, vector<string>& v){stack<char> st;while (i < s.size()){if (isdigit(s[i])){// 操作数输出string num;while (i < s.size() && isdigit(s[i])){num += s[i];++i;}v.push_back(num);}else{if (s[i] == '('){// 递归方式处理括号中的子表达式++i;toRPN(s, i, v);}else if (s[i] == ')'){++i;// 栈中的运算符全部输出while (!st.empty()){v.push_back(string(1, st.top()));st.pop();}// 结束递归return;}else{// 运算符// 1、如果栈为空或者栈不为空且当前运算符比栈顶运算符优先级高,则当//前运算符入栈// 2、如果栈不为为空且比栈顶运算符优先级低或相等,说明栈顶的运算符//可以运算了,// 输出栈顶运算符,当前运算符继续走前面遇到运算符的逻辑if (st.empty() || operatorPrecedence(s[i]) >operatorPrecedence(st.top())){st.push(s[i]);++i;}else{v.push_back(string(1, st.top()));st.pop();}}}}// 栈中的运算符全部输出while (!st.empty()){v.push_back(string(1, st.top()));st.pop();}}
};
int main()
{size_t i = 0;vector<string> v;//string str = "1+2-3";string str = "1+2-(3*4+5)-7";Solution().toRPN(str, i, v);for (auto& e : v){cout << e << " ";}cout << endl;return 0;
}

2.4. 计算器实现

 • 224. 基本计算器 - 力扣(LeetCode) 

• 有了上面两个部分学习之后,计算器OJ的大部分问题就解决了,但是这里还有一些问题需要处理。因为OJ中给的中缀表达式是字符串,字符串中包含空格,需要去掉空格。


• 其次就是负数和减号,要进行区分,将所有的负数-x转换为0-x,因为我们实现的代码考虑到乘除的情况,针对括号内的符号,我们不能直接变号处理。

class Solution {
public://map<char, int> _operatorPrecedence = { { '+', 1 }, { '-', 1 }, { '*', 2
}, { '/', 2 } };
int operatorPrecedence(char ch)
{struct opPD{char _op;int _pd;};static opPD arr[] = { {'+', 1},{'-', 1},{'*', 2},{'/', 2} };for (auto& e : arr){if (e._op == ch){return e._pd;}}assert(false);return -1;
}
void toRPN(const string& s, size_t& i, vector<string>& v)
{stack<char> st;while (i < s.size()){if (isdigit(s[i])){// 运算数输出string num;while (i < s.size() && isdigit(s[i])){num += s[i];++i;}v.push_back(num);}else{if (s[i] == '('){// 递归方式处理括号中的子表达式++i;toRPN(s, i, v);}else if (s[i] == ')'){++i;// 栈中的运算符全部输出while (!st.empty()){v.push_back(string(1, st.top()));st.pop();}// 结束递归return;}else{// 运算符// 1、如果栈为空或者栈不为空且当前运算符比栈顶运算符优先级高,则当//前运算符入栈// 2、如果栈不为为空且比栈顶运算符优先级低或相等,说明栈顶的运算符//可以运算了,// 输出栈顶运算符,当前运算符继续走前面遇到运算符的逻辑if (st.empty() || operatorPrecedence(s[i]) >operatorPrecedence(st.top())){st.push(s[i]);++i;}else{v.push_back(string(1, st.top()));st.pop();}}}}// 栈中的运算符全部输出while (!st.empty()){v.push_back(string(1, st.top()));st.pop();}
}
int evalRPN(const vector<string>& tokens) {stack<int> s;for (size_t i = 0; i < tokens.size(); ++i){const string& str = tokens[i];// str为数字if (!("+" == str || "-" == str || "*" == str || "/" == str)){s.push(stoi(str));}else{// str为操作符int right = s.top();s.pop();int left = s.top();s.pop();switch (str[0]){case '+':s.push(left + right);break;case '-':s.push(left - right);break;case '*':s.push(left * right);break;case '/':s.push(left / right);break;}}}return s.top();
}
int calculate(string s)
{// 1、去除所有空格,否则下面的一些逻辑没办法处理std::string news;news.reserve(s.size());for (auto ch : s){if (ch != ' ')news += ch;}s.swap(news);news.clear();// 2、将所有的负数-x转换为0-xfor (size_t i = 0; i < s.size(); ++i){//当-的前一个字符不为运算数时,我们才添加"0-",否则就是减号,不需要处理//同时因为这里是下标比较,需要注意符号在表达式第一位的情况,防止越界if (s[i] == '-' && (i == 0 || (!isdigit(s[i - 1]) && s[i - 1] !=')')))news += "0-";elsenews += s[i];}// 中缀表达式转成后缀表达式size_t i = 0;vector<string> v;toRPN(news, i, v);// 后缀表达式进行运算return evalRPN(v);
}
};

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web3与区块链如何革新网络安全——走在前沿

随着互联网技术的飞速发展&#xff0c;网络安全问题日益成为全球关注的焦点。Web3和区块链技术作为新兴的技术力量&#xff0c;正在逐步改变网络安全的格局。本文将探讨Web3和区块链技术如何革新网络安全&#xff0c;走在技术前沿。 1. Web3技术概述 Web3&#xff0c;即第三代互…

网络初级安全第三次作业

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>用户登录</title><style>* {margin:…

CSS中用display实现元素的显示/隐藏切换

** 通过display中的none和block ** 在前端开发中&#xff0c;display: none 和 display: block 是两种常用的 CSS 显示模式&#xff0c;核心区别在于&#xff1a;是否在页面中保留元素的占位空间 1. 核心区别属性display: nonedisplay: block占位空间元素完全从渲染树中移除&am…

因果图方法设计测试用例的价值与使用范围

一、因果图方法的核心原理 因果图方法通过分析软件规格说明中的输入条件&#xff08;因&#xff09;和输出结果&#xff08;果&#xff09;之间的逻辑关系&#xff0c;利用图形化方式将这些关系清晰展现。它使用特定的符号表示因果关系&#xff08;如恒等、非、或、与&#xff…

智慧农服数字化平台-数字科技赋能农业,开启智慧三农新篇章

智慧农服数字化平台数字科技赋能农业&#xff0c;开启智慧三农新篇章平台概览在乡村振兴和农业现代化的时代背景下&#xff0c;我们推出了创新的农业服务数字化平台——一个专为农业生产者打造的综合性SaaS服务平台。平台以"科技助农、数据兴农"为使命&#xff0c;通…

在线教育培训课程视频如何防下载、防盗录?

在数字化学习日益普及的今天&#xff0c;高质量的在线课程已成为教育机构、知识付费平台和讲师的核心竞争力。如何在不影响学员正常学习体验的前提下&#xff0c;有效防止课程视频被恶意盗取&#xff1f;今天介绍在线教育课程防下载、防盗录的10种视频加密方法&#xff0c;看看…

图像分析学习笔记(2):图像处理基础

图像分析学习笔记&#xff1a;图像处理基础图像增强方法图像复原方法图像分割方法形态学处理图像增强方法 目的&#xff1a;改善视觉效果&#xff0c;例如增强对比度定义&#xff1a;为了改善视觉效果、便于人或计算机对图像的分析理解&#xff0c;针对图像的特点或存在的问题…

生存分析机器学习问题

研究目标&#xff1a; 开发一个机器学习模型&#xff0c;用于个性化预测XXX的总体生存期。 模型输入&#xff1a;结合生存时间、治疗方案、人口统计学特征和实验室测试结果等多种特征。 模型输出&#xff1a;预测二元结果&#xff08;活着 vs. 死亡&#xff09;。 应用场景&…

【华为机试】547. 省份数量

文章目录547. 省份数量描述示例 1示例 2提示解题思路核心分析问题转化算法选择策略1. 深度优先搜索 (DFS)2. 广度优先搜索 (BFS)3. 并查集 (Union-Find)算法实现详解方法一&#xff1a;深度优先搜索 (DFS)方法二&#xff1a;广度优先搜索 (BFS)方法三&#xff1a;并查集 (Union…

09_Spring Boot 整合 Freemarker 模板引擎的坑

09_Spring Boot 整合 Freemarker 模板引擎的坑 1.背景&#xff1a; springboot 版本&#xff1a;3.0.2 2. 引入依赖 在 pom.xml 中添加&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web<…

十七、【Linux系统yum仓库管理】替换阿里源、搭建本地yum源

替换阿里源、搭建本地yum源本章学习目标内容简介阿里外网源核心功能本地yum核心功能操作演示替换阿里外网源备份原有yum源清理冲突配置下载阿里源配置文件添加EPEL扩展源清理缓存重建索引验证源状态测试安装软件使用镜像搭建本地仓库准备ISO镜像创建挂载点目录挂载iso文件验证挂…

家庭网络怎么进行公网IP获取,及内网端口映射外网访问配置,附无公网IP提供互联网连接方案

在家庭网络中&#xff0c;我们常常需要通过公网IP来访问内网中的设备&#xff0c;比如家庭NAS、Web服务器或监控摄像头。要实现这个目标&#xff0c;首先要确保你的网络具有一个可用的公网IP&#xff0c;然后通过路由器配置端口映射&#xff08;Port Forwarding&#xff09;。如…

(LeetCode 面试经典 150 题 ) 128. 最长连续序列 (哈希表)

题目&#xff1a;128. 最长连续序列 思路&#xff1a;哈希表&#xff0c;时间复杂度0(n)。 用集合set来实现哈希表的功能&#xff0c;记录所有出现的元素。然后遍历元素&#xff0c;细节看注释。 C版本&#xff1a; class Solution { public:int longestConsecutive(vector&…

Altera Quartus:BAT批处理实现一键sof文件转换为jic文件

sof文件是Quartus编译默认生成的程序文件&#xff0c;用于通过JTAG口下载到FPGA内部RAM&#xff0c;断电程序会丢失&#xff0c;jic文件是用于固化到外部Flash中的程序文件&#xff0c;断电程序不会丢失。本文介绍如何通过批处理文件实现sof到jic的一键自动化转换。 Quartus工程…

基于单片机婴儿床/婴儿摇篮/婴儿车设计/婴儿监护系统

传送门 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目速选一览表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目功能速览 概述 本设计实现了一种基于单片机的多功能智能婴儿监护系统&#xff0c;集成于婴儿床、摇篮或婴儿车中…

Typora + 七牛云图床终极配置教程

本文是一份超详细的 Typora 七牛云图床配置指南&#xff0c;旨在帮助你实现图片“即插即用”的顺滑写作体验。我们将一步步完成所有配置&#xff0c;并特别针对配置过程中最常见的三个错误&#xff1a;ENOTFOUND (找不到服务器)、401 (无权访问) 和 Document not found (文件不…

高性能熔断限流实现:Spring Cloud Gateway 在电商系统的实战优化

一、为什么需要高性能熔断限流&#xff1f; 在电商系统中&#xff0c;尤其是大促期间&#xff0c;系统面临的流量可能是平时的数十倍甚至上百倍。 这样的场景下&#xff0c;熔断限流不再是可选功能&#xff0c;而是保障系统稳定的生命线。传统方案的问题&#xff1a; 限流精度不…

计算机网络1.1:计算机网络在信息时代的作用

计算机网络已由一种通信基础设施发展成为一种重要的信息服务基础设施。计算机网络已经像水、电、煤气这些基础设施一样&#xff0c;成为我们生活中不可或缺的一部分。

Component cannot be used as a JSX component

今天在使用 React Ts&#xff0c;使用 react-icons 这个库的时候&#xff0c;遇到了这个问题&#xff1a;原因用一句话概括就是 Ts 的版本太低了&#xff01; 我的 package.json&#xff1a; {"name": "frontend","version": "0.1.0"…

Centos安装最新docker以及ubuntu安装docker

Centos安装最新版本docker1.更新阿里源,更新之前先做备份mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup更新阿里源wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo2.运行 yum makecache 生成缓存…