28.C++进阶:map和set封装|insert|迭代器|[]

封装红⿊树实现mymap和myset

源码及框架分析

SGI-STL30版本源代码,map和set的源代码在map/set/stl_map.h/stl_set.h/stl_tree.h等⼏个头⽂件中。
map和set的实现结构框架核⼼部分截取出来如下:

// set #ifndef __SGI_STL_INTERNAL_TREE_H #include <stl_tree.h> #endif #include <stl_set.h> #include <stl_multiset.h> // map #ifndef __SGI_STL_INTERNAL_TREE_H #include <stl_tree.h> #endif #include <stl_map.h> #include <stl_multimap.h> // stl_set.h template <class Key, class Compare = less<Key>, class Alloc = alloc> class set { public: // typedefs: typedef Key key_type; typedef Key value_type; private: typedef rb_tree<key_type, value_type, identity<value_type>, key_compare, Alloc> rep_type; rep_type t; // red-black tree representing set }; // stl_map.h template <class Key, class T, class Compare = less<Key>, class Alloc = alloc> class map { public: // typedefs: typedef Key key_type; typedef T mapped_type; typedef pair<const Key, T> value_type; private: typedef rb_tree<key_type, value_type, select1st<value_type>, key_compare, Alloc> rep_type; rep_type t; // red-black tree representing map }; // stl_tree.h struct __rb_tree_node_base { typedef __rb_tree_color_type color_type; typedef __rb_tree_node_base* base_ptr; color_type color; base_ptr parent; base_ptr left; base_ptr right; }; // stl_tree.h template <class Key, class Value, class KeyOfValue, class Compare, class Alloc = alloc> class rb_tree { protected: typedef void* void_pointer; typedef __rb_tree_node_base* base_ptr; typedef __rb_tree_node<Value> rb_tree_node; typedef rb_tree_node* link_type; typedef Key key_type; typedef Value value_type; public: // insert⽤的是第⼆个模板参数左形参 pair<iterator,bool> insert_unique(const value_type& x); // erase和find⽤第⼀个模板参数做形参 size_type erase(const key_type& x); iterator find(const key_type& x); protected: size_type node_count; // keeps track of size of tree link_type header; }; template <class Value> struct __rb_tree_node : public __rb_tree_node_base { typedef __rb_tree_node<Value>* link_type; Value value_field; };
  • 通过下图对框架的分析,我们可以看到源码中rb_tree⽤了⼀个巧妙的泛型思想实现,rb_tree是实现key的搜索场景,还是key/value的搜索场景不是直接写死的,⽽是由第⼆个模板参数Value决定_rb_tree_node中存储的数据类型。
  • set实例化rb_tree时第⼆个模板参数给的是key,map实例化rb_tree时第⼆个模板参数给的是pair<const key,T>,这样⼀颗红⿊树既可以实现key搜索场景的set,也可以实现key/value搜索场景的map。
  • 要注意⼀下,源码⾥⾯模板参数是⽤T代表value,⽽内部写的value_type不是我们我们⽇常key/value场景中说的value,源码中的value_type反⽽是红⿊树结点中存储的真实的数据的类型。
  • rb_tree第⼆个模板参数Value已经控制了红⿊树结点中存储的数据类型,为什么还要传第⼀个模板参数Key呢?尤其是set,两个模板参数是⼀样的,这是很多同学这时的⼀个疑问。要注意的是对于map和set,find/erase时的函数参数都是Key,所以第⼀个模板参数是传给find/erase等函数做形参的类型的。对于set⽽⾔两个参数是⼀样的,但是对于map⽽⾔就完全不⼀样了,map insert的是pair对象,但是find和ease的是Key对象。
  • 源码命名⻛格⽐较乱,set模板参数⽤的Key命名,map⽤的是Key和T命名,⽽rb_tree⽤的⼜是Key和Value

模拟实现map和set

实现出复⽤红⿊树的框架,并⽀持insert
  • 参考源码框架,map和set复⽤之前我们实现的红⿊树。
  • 相⽐源码调整⼀下,key参数就⽤K,value参数就⽤V,红⿊树中的数据类型,我们使⽤T。
  • 其次因为RBTree实现了泛型不知道T参数导致是K,还是pair<K,V>,那么insert内部进⾏插⼊逻辑⽐较时,就没办法进⾏⽐较,因为pair的默认⽀持的是key和value⼀起参与⽐较,我们需要时的任何时候只⽐较key,所以我们在map和set层分别实现⼀个MapKeyOfT和SetKeyOfT的仿函数传给RBTree的KeyOfT,然后RBTree中通过KeyOfT仿函数取出T类型对象中的key,再进⾏⽐较,具体细节参考如下代码实现。
// 源码中pair⽀持的<重载实现 template <class T1, class T2> bool operator< (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs) { return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second); } // Mymap.h namespace bit { template<class K, class V> class map { struct MapKeyOfT { const K& operator()(const pair<K, V>& kv) { return kv.first; } }; public: bool insert(const pair<K, V>& kv) { return _t.Insert(kv); } private: RBTree<K, pair<K, V>, MapKeyOfT> _t; }; } // Myset.h namespace bit { template<class K> class set { struct SetKeyOfT { const K& operator()(const K& key) { return key; } }; public: bool insert(const K& key) { return _t.Insert(key); } private: RBTree<K, K, SetKeyOfT> _t; }; } // RBTree.h enum Colour { RED, BLACK }; template<class T> struct RBTreeNode { T _data; RBTreeNode<T>* _left; RBTreeNode<T>* _right; RBTreeNode<T>* _parent; Colour _col; RBTreeNode(const T& data) : _data(data) , _left(nullptr) , _right(nullptr) , _parent(nullptr) {} }; // 实现步骤: // 1、实现红⿊树 // 2、封装map和set框架,解决KeyOfT // 3、iterator // 4、const_iterator // 5、key不⽀持修改的问题 // 6、operator[] // KeyOfT仿函数 取出T对象中的key template<class K, class T, class KeyOfT> class RBTree { private: typedef RBTreeNode<T> Node; Node* _root = nullptr; public: bool Insert(const T& data) { if (_root == nullptr) { _root = new Node(data); _root->_col = BLACK; return true; } KeyOfT kot; Node* parent = nullptr; Node* cur = _root; while (cur) { if (kot(cur->_data) < kot(data)) { parent = cur; cur = cur->_right; } else if (kot(cur->_data) > kot(data)) { parent = cur; cur = cur->_left; } else { return false; } } cur = new Node(data); Node* newnode = cur; // 新增结点。颜⾊给红⾊ cur->_col = RED; if (kot(parent->_data) < kot(data)) { parent->_right = cur; } else { parent->_left = cur; } cur->_parent = parent; //... return true; } }
⽀持iterator的实现
struct __rb_tree_base_iterator { typedef __rb_tree_node_base::base_ptr base_ptr; base_ptr node; void increment() { if (node->right != 0) { node = node->right; while (node->left != 0) node = node->left; } else { base_ptr y = node->parent; while (node == y->right) { node = y; y = y->parent; } if (node->right != y) node = y; } } void decrement() { if (node->color == __rb_tree_red && node->parent->parent == node) node = node->right; else if (node->left != 0) { base_ptr y = node->left; while (y->right != 0) y = y->right; node = y; } else { base_ptr y = node->parent; while (node == y->left) { node = y; y = y->parent; } node = y; } } }; template <class Value, class Ref, class Ptr> struct __rb_tree_iterator : public __rb_tree_base_iterator { typedef Value value_type; typedef Ref reference; typedef Ptr pointer; typedef __rb_tree_iterator<Value, Value&, Value*> iterator; __rb_tree_iterator() {} __rb_tree_iterator(link_type x) { node = x; } __rb_tree_iterator(const iterator& it) { node = it.node; } reference operator*() const { return link_type(node)->value_field; } #ifndef __SGI_STL_NO_ARROW_OPERATOR pointer operator->() const { return &(operator*()); } #endif /* __SGI_STL_NO_ARROW_OPERATOR */ self& operator++() { increment(); return *this; } self& operator--() { decrement(); return *this; } inline bool operator==(const __rb_tree_base_iterator& x, const __rb_tree_base_iterator& y) { return x.node == y.node; } inline bool operator!=(const __rb_tree_base_iterator& x, const __rb_tree_base_iterator& y) { return x.node != y.node; }

iterator实现思路分析

  • iterator实现的⼤框架跟list的iterator思路是⼀致的,⽤⼀个类型封装结点的指针,再通过重载运算符实现,迭代器像指针⼀样访问的⾏为。
  • 这⾥的难点是operator++和operator–的实现。之前使⽤部分,我们分析了,map和set的迭代器⾛的是中序遍历,左⼦树->根结点->右⼦树,那么begin()会返回中序第⼀个结点的iterator也就是10所在结点的迭代器。
  • 迭代器++的核⼼逻辑就是不看全局,只看局部,只考虑当前中序局部要访问的下⼀个结点。
  • 迭代器++时,如果it指向的结点的右⼦树不为空,代表当前结点已经访问完了,要访问下⼀个结点是右⼦树的中序第⼀个,⼀棵树中序第⼀个是最左结点,所以直接找右⼦树的最左结点即可。
  • 迭代器++时,如果it指向的结点的右⼦树空,代表当前结点已经访问完了且当前结点所在的⼦树也访问完了,要访问的下⼀个结点在当前结点的祖先⾥⾯,所以要沿着当前结点到根的祖先路径向上找。
  • 如果当前结点是⽗亲的左,根据中序左⼦树->根结点->右⼦树,那么下⼀个访问的结点就是当前结点的⽗亲;如下图:it指向25,25右为空,25是30的左,所以下⼀个访问的结点就是30。
  • 如果当前结点是⽗亲的右,根据中序左⼦树->根结点->右⼦树,当前当前结点所在的⼦树访问完了,当前结点所在⽗亲的⼦树也访问完了,那么下⼀个访问的需要继续往根的祖先中去找,直到找到孩⼦是⽗亲左的那个祖先就是中序要问题的下⼀个结点。如下图:it指向15,15右为空,15是10的右,15所在⼦树话访问完了,10所在⼦树也访问完了,继续往上找,10是18的左,那么下⼀个访问的结点就是18。
  • end()如何表⽰呢?如下图:当it指向50时,++it时,50是40的右,40是30的右,30是18的右,18到根没有⽗亲,没有找到孩⼦是⽗亲左的那个祖先,这是⽗亲为空了,那我们就把it中的结点指针置为nullptr,我们⽤nullptr去充当end。需要注意的是stl源码空,红⿊树增加了⼀个哨兵位头结点做为end(),这哨兵位头结点和根互为⽗亲,左指向最左结点,右指向最右结点。相⽐我们⽤nullptr作为end(),差别不⼤,他能实现的,我们也能实现。只是–end()判断到结点时空,特殊处理⼀下,让迭代器结点指向最右结点。具体参考迭代器–实现。
  • 迭代器–的实现跟++的思路完全类似,逻辑正好反过来即可,因为他访问顺序是右⼦树->根结点->左⼦树,具体参考下⾯代码实现。
  • set的iterator也不⽀持修改,我们把set的第⼆个模板参数改成const K即可,RBTree<K, const K, SetKeyOfT> _t;
  • map的iterator不⽀持修改key但是可以修改value,我们把map的第⼆个模板参数pair的第⼀个参数改成const K即可,RBTree<K, pair<const K, V>, MapKeyOfT> _t;
  • ⽀持完整的迭代器还有很多细节需要修改,具体参考下⾯题的代码。








map⽀持[]
  • map要⽀持[]主要需要修改insert返回值⽀持,修改RBtree中的insert返回值为
    pair<Iterator, bool> Insert(const T& data)
bit::map和bit::set代码实现
// Myset.h #include"RBTree.h" namespace bit { template<class K> class set { struct SetKeyOfT { const K& operator()(const K& key) { return key; } }; public: typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator; typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator const_iterator; iterator begin() { return _t.Begin(); } iterator end() { return _t.End(); } const_iterator begin() const { return _t.Begin(); } const_iterator end() const { return _t.End(); } pair<iterator, bool> insert(const K& key) { return _t.Insert(key); } iterator find(const K& key) { return _t.Find(key); } private: RBTree<K, const K, SetKeyOfT> _t; }; void Print(const set<int>& s) { set<int>::const_iterator it = s.end(); while (it != s.begin()) { --it; // 不⽀持修改 //*it += 2; cout << *it << " "; } cout << endl; } void test_set() { set<int> s; int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; for (auto e : a) { s.insert(e); } for (auto e : s) { cout << e << " "; } cout << endl; Print(s); } void test_set1() { set<int> s; int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; for (auto e : a) { s.insert(e); } set<int>::iterator it = s.begin(); while (it != s.end()) { //if(*it % 2 == 0) // *it += 100; cout << *it << " "; ++it; } cout << endl; } } // Mymap.h #include"RBTree.h" namespace bit { template<class K, class V> class map { struct MapKeyOfT { const K& operator()(const pair<K, V>& kv) { return kv.first; } }; public: typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::Iterator iterator; typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::ConstIterator const_iterator; iterator begin() { return _t.Begin(); } iterator end() { return _t.End(); } const_iterator begin() const { return _t.Begin(); } const_iterator end() const { return _t.End(); } pair<iterator, bool> insert(const pair<K, V>& kv) { return _t.Insert(kv); } iterator find(const K& key) { return _t.Find(key); } V& operator[](const K& key) { pair<iterator, bool> ret = insert(make_pair(key, V())); return ret.first->second; } private: RBTree<K, pair<const K, V>, MapKeyOfT> _t; }; void test_map() { map<string, string> dict; dict.insert({ "sort", "排序" }); dict.insert({ "left", "左边" }); dict.insert({ "right", "右边" }); dict["left"] = "左边,剩余"; dict["insert"] = "插⼊"; dict["string"]; map<string, string>::iterator it = dict.begin(); while (it != dict.end()) { // 不能修改first,可以修改second //it->first += 'x'; it->second += 'x'; cout << it->first << ":" << it->second << endl; ++it; } cout << endl; } void test_map1() { map<int, int> m; int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; for (auto e : a) { m.insert(make_pair(e, e)); } map<int, int>::iterator it = m.begin(); while (it != m.end()) { //it->first += 100; it->second += 100; cout << it->first << ":" << it->second << endl; ++it; } cout << endl; } } // RBtree.h enum Colour { RED, BLACK }; template<class T> struct RBTreeNode { T _data; RBTreeNode<T>* _left; RBTreeNode<T>* _right; RBTreeNode<T>* _parent; Colour _col; RBTreeNode(const T& data) : _data(data) , _left(nullptr) , _right(nullptr) , _parent(nullptr) {} }; template<class T, class Ref, class Ptr> struct RBTreeIterator { typedef RBTreeNode<T> Node; typedef RBTreeIterator<T, Ref, Ptr> Self; Node* _node; Node* _root; RBTreeIterator(Node* node, Node* root) :_node(node) ,_root(root) {} Self& operator++() { if (_node->_right) { // 右不为空,右⼦树最左结点就是中序第⼀个 Node* leftMost = _node->_right; while (leftMost->_left) { leftMost = leftMost->_left; } _node = leftMost; } else { // 孩⼦是⽗亲左的那个祖先 Node* cur = _node; Node* parent = cur->_parent; while (parent && cur == parent->_right) { cur = parent; parent = cur->_parent; } _node = parent; } return *this; } Self& operator--() { if (_node == nullptr) // end() { // --end(),特殊处理,⾛到中序最后⼀个结点,整棵树的最右结点 Node* rightMost = _root; while (rightMost && rightMost->_right) { rightMost = rightMost->_right; } _node = rightMost; } else if (_node->_left) { // 左⼦树不为空,中序左⼦树最后⼀个 Node* rightMost = _node->_left; while (rightMost->_right) { rightMost = rightMost->_right; } _node = rightMost; } else { // 孩⼦是⽗亲右的那个祖先 Node* cur = _node; Node* parent = cur->_parent; while (parent && cur == parent->_left) { cur = parent; parent = cur->_parent; } _node = parent; } return *this; } Ref operator*() { return _node->_data; } Ptr operator->() { return &_node->_data; } bool operator!= (const Self& s) const { return _node != s._node; } bool operator== (const Self& s) const { return _node == s._node; } }; template<class K, class T, class KeyOfT> class RBTree { typedef RBTreeNode<T> Node; public: typedef RBTreeIterator<T, T&, T*> Iterator; typedef RBTreeIterator<T, const T&, const T*> ConstIterator; Iterator Begin() { Node* leftMost = _root; while (leftMost && leftMost->_left) { leftMost = leftMost->_left; } return Iterator(leftMost, _root); } Iterator End() { return Iterator(nullptr, _root); } ConstIterator Begin() const { Node* leftMost = _root; while (leftMost && leftMost->_left) { leftMost = leftMost->_left; } return ConstIterator(leftMost, _root); } ConstIterator End() const { return ConstIterator(nullptr, _root); } RBTree() = default; ~RBTree() { Destroy(_root); _root = nullptr; } pair<Iterator, bool> Insert(const T& data) { if (_root == nullptr) { _root = new Node(data); _root->_col = BLACK; return make_pair(Iterator(_root, _root), true); } KeyOfT kot; Node* parent = nullptr; Node* cur = _root; while (cur) { if (kot(cur->_data) < kot(data)) { parent = cur; cur = cur->_right; } else if (kot(cur->_data) > kot(data)) { parent = cur; cur = cur->_left; } else { return make_pair(Iterator(cur, _root), false); } } cur = new Node(data); Node* newnode = cur; // 新增结点。颜⾊红⾊给红⾊ cur->_col = RED; if (kot(parent->_data) < kot(data)) { parent->_right = cur; } else { parent->_left = cur; } cur->_parent = parent; while (parent && parent->_col == RED) { Node* grandfather = parent->_parent; // g // p u if (parent == grandfather->_left) { Node* uncle = grandfather->_right; if (uncle && uncle->_col == RED) { // u存在且为红 -》变⾊再继续往上处理 parent->_col = uncle->_col = BLACK; grandfather->_col = RED; cur = grandfather; parent = cur->_parent; } else { // u存在且为⿊或不存在 -》旋转+变⾊ if (cur == parent->_left) { // g // p u //c //单旋 RotateR(grandfather); parent->_col = BLACK; grandfather->_col = RED; } else { // g // p u // c //双旋 RotateL(parent); RotateR(grandfather); cur->_col = BLACK; grandfather->_col = RED; } break; } } else { // g // u p Node* uncle = grandfather->_left; // 叔叔存在且为红,-》变⾊即可 if (uncle && uncle->_col == RED) { parent->_col = uncle->_col = BLACK; grandfather->_col = RED; // 继续往上处理 cur = grandfather; parent = cur->_parent; } else // 叔叔不存在,或者存在且为⿊ { // 情况⼆:叔叔不存在或者存在且为⿊ // 旋转+变⾊ // g //u p // c if (cur == parent->_right) { RotateL(grandfather); parent->_col = BLACK; grandfather->_col = RED; } else { // g //u p //c RotateR(parent); RotateL(grandfather); cur->_col = BLACK; grandfather->_col = RED; } break; } } } _root->_col = BLACK; return make_pair(Iterator(newnode, _root), true); } Iterator Find(const K& key) { Node* cur = _root; while (cur) { if (cur->_kv.first < key) { cur = cur->_right; } else if (cur->_kv.first > key) { cur = cur->_left; } else { return Iterator(cur, _root); } } return End(); } private: void RotateL(Node* parent) { Node* subR = parent->_right; Node* subRL = subR->_left; parent->_right = subRL; if (subRL) subRL->_parent = parent; Node* parentParent = parent->_parent; subR->_left = parent; parent->_parent = subR; if (parentParent == nullptr) { _root = subR; subR->_parent = nullptr; } else { if (parent == parentParent->_left) { parentParent->_left = subR; } else { parentParent->_right = subR; } subR->_parent = parentParent; } } void RotateR(Node* parent) { Node* subL = parent->_left; Node* subLR = subL->_right; parent->_left = subLR; if (subLR) subLR->_parent = parent; Node* parentParent = parent->_parent; subL->_right = parent; parent->_parent = subL; if (parentParent == nullptr) { _root = subL; subL->_parent = nullptr; } else { if (parent == parentParent->_left) { parentParent->_left = subL; } else { parentParent->_right = subL; } subL->_parent = parentParent; } } void Destroy(Node* root) { if (root == nullptr) return; Destroy(root->_left); Destroy(root->_right); delete root; } private: Node* _root = nullptr; };

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

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

相关文章

大数据时代,Power BI 成为数据洞察的关键工具

大数据时代&#xff0c;Power BI 成为数据洞察的关键工具&#xff1a;从零到一的实战指南 1. 标题 (Title) 以下是 5 个吸引人的标题选项&#xff0c;涵盖核心关键词“大数据”“Power BI”“数据洞察”&#xff1a; 《大数据浪潮下&#xff0c;Power BI 如何让你的数据“会…

vivado2021.1安装教程:满足工控高可靠性要求的方法

如何在工控场景下构建稳定可靠的 Vivado 2021.1 开发环境 工业控制系统的开发&#xff0c;从来不只是写代码和烧录 FPGA。当你面对的是运行在高温车间、连续工作十年不能宕机的 PLC 控制器&#xff0c;或是驱动精密机械臂的运动控制系统时&#xff0c;每一个环节都必须经得起时…

计算机毕业设计springboot易耗品管理系统 基于SpringBoot的企业低值易耗品智能管理平台 SpringBoot驱动的办公耗材全流程管控系统

计算机毕业设计springboot易耗品管理系统pwg9y9un &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。在数字化办公与精益生产双重推动下&#xff0c;小到一支笔、大到一桶墨&#x…

基于MAX3232的RS232接口引脚定义调试技巧

从MCU到PC&#xff1a;一文吃透MAX3232串口通信的引脚连接与调试实战你有没有遇到过这样的场景&#xff1f;单片机代码写得没问题&#xff0c;UART初始化也正确&#xff0c;但就是收不到PC发来的数据&#xff1b;或者串口助手显示乱码、偶尔丢包&#xff0c;查了一圈软件逻辑却…

计算机毕业设计springboot飞机票预定系统 基于SpringBoot的航空客运订票平台设计与实现 融合Vue+SpringBoot的在线航班座位预约系统

计算机毕业设计springboot飞机票预定系统yr7f205a &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。当“说走就走”成为年轻人出行的默认节奏&#xff0c;传统柜台与电话订票早已跟…

Pspice安装教程:从下载到运行的全面讲解

从零开始搭建Pspice仿真环境&#xff1a;一次搞定安装、配置与首个电路验证 你是不是也曾在准备做课程设计或自学模拟电路时&#xff0c;被“ Pspice怎么装不上&#xff1f; ”这个问题卡住过&#xff1f; 明明下载了安装包&#xff0c;点击 setup.exe 却弹出一堆错误&am…

教学思考(3)

一、 背景与政策梳理(国家层面) 汇报首先梳理了人工智能教育在国家政策层面的演进脉络,强调了从“模块化”到“体系化”的转变。课程标准演进:高中(2017/2020修订版):人工智能作为必修一的章节内容及选择性必修…

计算机毕业设计springboot乡镇人口信息管理系统 基于SpringBoot的乡镇居民信息综合管理平台 面向基层治理的SpringBoot人口大数据服务系统

计算机毕业设计springboot乡镇人口信息管理系统tjvav0jl &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。在城乡融合不断提速的今天&#xff0c;乡镇级人口数据呈爆炸式增长&…

打造智能化 ECS 故障分析 Agent:从创建到实战

前言 在微服务架构中,ECS 服务故障排查往往需要在多个 AWS 控制台之间切换,查看日志、指标、事件,耗时且容易遗漏关键信息。本文将介绍如何使用 Kiro CLI 创建一个专业的 ECS 故障分析 Agent,实现一键自动化诊断。 一、Agent 设计理念 1.1 核心目标 自动化:输入服务名称…

数字频率计设计:FPGA开发环境配置指南

从零开始搭建数字频率计&#xff1a;FPGA开发环境实战配置全记录 你有没有遇到过这样的场景&#xff1f;手头有一个高频信号需要测量&#xff0c;万用表不够准&#xff0c;示波器又太贵&#xff0c;而市面上的频率计要么精度不够、要么功能单一。于是你决定自己动手做一个——…

Altium原理图与FPGA引脚规划协同设计实践

从原理图到FPGA引脚&#xff1a;如何在Altium中实现高效协同设计你有没有遇到过这样的场景&#xff1f;FPGA工程师说&#xff1a;“这个DDR信号我只能放Bank 15&#xff0c;不然时序不收敛。”而PCB工程师回&#xff1a;“可你在Bank 15用了1.8V&#xff0c;但我们的DDR3要求1.…

emuelec固件升级注意事项:安全更新操作指南

emuelec固件升级实战指南&#xff1a;从备份到恢复的全链路避坑手册 你有没有经历过这样的时刻&#xff1f;兴致勃勃地下载了新版emuelec固件&#xff0c;想着终于能用上最新的PS2模拟优化和蓝牙手柄支持&#xff0c;结果一通操作后——屏幕黑了、WiFi连不上、存档全没了。重启…

组合逻辑电路设计入门必看:基本概念与实例解析

组合逻辑电路设计入门必看&#xff1a;从门电路到功能模块的实战解析你有没有遇到过这样的情况&#xff1a;明明代码写得没问题&#xff0c;烧录进FPGA后却发现输出“飘忽不定”&#xff1f;或者仿真时一切正常&#xff0c;上板测试却频频出错&#xff1f;很多初学者在学习数字…

SkyWalking 接口超时监控告警完整指南

目录 一、SkyWalking 简介 二、安装部署 三、告警配置 四、管理维护 五、最佳实践 六、故障排查 一、SkyWalking 简介 1.1 什么是 SkyWalking SkyWalking 是一个开源的 APM(应用性能监控)系统,专为微服务、云原生和容器化架构设计。 核心功能: 📊 分布式追踪:完整的调…

图解说明三极管开关电路:基础结构与信号流向

三极管开关电路全解析&#xff1a;从零搞懂驱动设计的底层逻辑你有没有遇到过这种情况&#xff1f;想用单片机控制一个继电器&#xff0c;结果发现IO口输出电流太小&#xff0c;直接带不动&#xff1b;或者调试LED调光时&#xff0c;亮度总不稳定&#xff0c;怀疑是驱动出了问题…

汇编语言全接触-99.检测内存中的 Soft-Ice

概述&#xff1a;检测内存中的 Soft-Ice 又一法&#xff0c;不过这次用的是在全部内存搜索 Soft-Ice 的特征码来实现的。汇编编程示例&#xff1a;; 加密方法: 检测 s-ice; 用 scas,cmps 等指令, s-ice 无法用; bpm 等断点检测到, 因此可用比较关键…

Prim 最小生成树算法(MST)

Prim算法是贪婪算法&#xff0c;类似于Kruskal算法。该算法始终从单个节点出发&#xff0c;经过多个相邻节点&#xff0c;以探索沿途所有连接的边。 该算法从一个空生成树开始。 其理念是维持两组顶点。第一组包含已包含在MST中的顶点&#xff0c;另一组包含尚未包含的顶点。 …

全球物流业进入“退货季“,女士连衣裙退货率接近90%

、美通社消息&#xff1a;随着年终购物旺季的结束&#xff0c;全球物流业已进入"退货季"。当前&#xff0c;电商供应链中的退货环节正扮演着日益关键的角色。过去几年间&#xff0c;退货已从后台的成本中心转变为一线的战略差异化因素。基于DHL《2025电子商务趋势报告…

vivado2023.2安装步骤详解:FPGA开发环境从零搭建

以下是对您提供的博文内容进行深度润色与结构重构后的技术文章。本次优化严格遵循您的全部要求&#xff1a;✅ 彻底去除AI痕迹&#xff0c;语言自然、专业、有“人味”&#xff1b;✅ 摒弃模板化标题&#xff08;如“引言”“总结”&#xff09;&#xff0c;代之以逻辑递进、场…

超详细版MOSFET开关时序分析及其工作原理

深入MOSFET的“心跳”&#xff1a;开关时序与动态行为全解析你有没有想过&#xff0c;一个看似简单的“开”和“关”&#xff0c;背后竟藏着如此复杂的物理过程&#xff1f;在现代电源设计中&#xff0c;MOSFET早已不是那个教科书里一句话就能讲完的“电压控制开关”。当我们把…