C++ 模擬實現 map 和 set:掌握核心數據結構

C++ 模擬實現 map 和 set:掌握核心數據結構


文章目錄

  • C++ 模擬實現 map 和 set:掌握核心數據結構
  • 一、set 和 map 的結構
    • 1.1 set的結構
    • 1.2 map的結構
  • 二、對紅黑樹的改造
    • 2.1 改造紅黑樹的節點
    • 2.2 改造紅黑樹
      • 2.2.1 仿函數的使用
      • 2.2.2 插入函數的改造
      • 2.2.3 刪除函數的改造
  • 三、對迭代器的改造
    • 3.1 *、->、!=、==
    • 3.2 begin和end
    • 3.3 ++ 和 --
    • 3.4 const迭代器
    • 3.5 復用紅黑樹接口實現set/map中的成員函數
      • 3.5.1 set成員函數
      • 3.5.2 map成員函數
  • 四、源代碼總結
    • 4.1 Myset.h
    • 4.2 Mymap.h
    • 4.3 RBTree.h


一、set 和 map 的結構

STL中set和map底層是一顆紅黑樹,模擬set和map需要一顆紅黑樹作為我們的成員變量
點擊這里了解紅黑樹


1.1 set的結構

set結構就是 K模型,所以set容器對紅黑樹的封裝如下:
在這里插入圖片描述


1.2 map的結構

map結構就是 KV模型,所以map容器對紅黑樹的封裝如下
在這里插入圖片描述


二、對紅黑樹的改造

在這里插入圖片描述


2.1 改造紅黑樹的節點

其中紅黑樹的節點類型就是模版參數T
在這里插入圖片描述


2.2 改造紅黑樹

2.2.1 仿函數的使用

在這里插入圖片描述
在這里插入圖片描述


然后我們將所有需要比較key的函數利用仿函數進行替換,我們以Find為例
在這里插入圖片描述


2.2.2 插入函數的改造

在這里插入圖片描述

代碼如下(示例):

pair<iterator, bool> Insert(const T& data)
{//情況一:如果是根節點if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return make_pair(iterator(_root),true);}KeyOfT kot;Node* parent = nullptr;Node* cur = _root;while (cur){if (kot(cur->_value) < kot(data)){parent = cur;cur = cur->_right;}else if (kot(cur->_value) > kot(data)){parent = cur;cur = cur->_left;}else{return make_pair(iterator(cur), false);}}//找到插入位置cur = new Node(data);Node* newnode = cur;if (kot(parent->_value) < kot(data)){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;while (parent && parent->_col == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;//情況三:如果叔叔存在且為紅if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else{//情況四:叔叔不存在/存在且為黑,且cur在parent的左側if (cur == parent->_left){//     g  //   p   u// c RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else//情況五:叔叔不存在 / 存在且為黑,cur在parent的右側{//     g//   p   u//     cRotateLR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}//這時該子樹的根節點變為黑色,不需要繼續調整break;}}else{Node* uncle = grandfather->_left;//情況三:如果叔叔存在且為紅if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//繼續調整cur = grandfather;parent = cur->_parent;}else{//情況四:叔叔不存在/存在且為黑,且cur在parent的左側if (cur == parent->_right){//    g//  u   p//        cRotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else // 情況五:叔叔不存在 / 存在且為黑,cur在parent的右側{//    g//  u   p//    cRotateRL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}//這時該子樹的根節點變為黑色,不需要繼續調整break;}}}//防止情況三改到根節點變為紅色_root->_col = BLACK;return make_pair(iterator(newnode), true);
}

2.2.3 刪除函數的改造

在這里插入圖片描述

代碼如下(示例):

else //待刪除結點的左右子樹均不為空
{//替換法刪除//尋找待刪除結點右子樹當中key值最小的結點作為實際刪除結點Node* minParent = cur;Node* minRight = cur->_right;while (minRight->_left){minParent = minRight;minRight = minRight->_left;}// 原本直接可以賦值// cur->_value = minRight->_value //將待刪除結點的鍵值改為minRight的鍵值Node* newnode = new Node(minRight->_value,cur->_col);Node* parent = cur->_parent;//重新鏈接祖父孫三代節點關系cur->_left->_parent = newnode;cur->_right->_parent = newnode;if (parent){if (parent->_left == cur){parent->_left = newnode;}else{parent->_right = newnode;}}else{//如果是根節點_root = newnode;}newnode->_parent = parent;newnode->_left = cur->_left;newnode->_right = cur->_right;//如果minParent是curif (minParent == cur){minParent = newnode;}delete cur;delParent = minParent; //標記實際刪除的父節點delCur = minRight; //標記實際刪除的結點
}

三、對迭代器的改造

3.1 *、->、!=、==

在這里插入圖片描述

代碼如下(示例):

template<class T, class Ref, class Ptr>
struct __RBTreeIterator
{typedef RBNode<T> Node;typedef __RBTreeIterator<T, Ref, Ptr> Self;Node* _node;//構造__RBTreeIterator(Node* node):_node(node){}Ref operator*(){return _node->_value;}Ptr operator->(){return &_node->_value;}//判斷兩個正向迭代器是否不同bool operator!=(const Self& s) const{return _node != s._node;}//判斷兩個正向迭代器是否相同bool operator==(const Self& s) const{return _node == s._node;}Node* getNode(){return _node;}
};

3.2 begin和end

在這里插入圖片描述

代碼如下(示例):

typedef __RBTreeIterator<T, T&, T*> iterator;//普通迭代器
typedef __RBTreeIterator<T, const T&, const T*> const_iterator;//const迭代器
//最左節點
iterator begin()
{Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return iterator(cur);
}
iterator end()
{return iterator(nullptr);
}
//const版本begin和end
const_iterator begin()const
{Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return const_iterator(cur);
}const_iterator end()const
{return const_iterator(nullptr);
}

3.3 ++ 和 –

在這里插入圖片描述

代碼如下(示例):

 //前置++Self& operator++(){//如果右子樹不為空if (_node->_right){//尋找該結點右子樹當中的最左結點Node* left = _node->_right;while (left->_left){left = left->_left;}_node = left;}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->_left) //結點的左子樹不為空{//尋找該結點左子樹當中的最右結點Node* right = _node->_left;while (right->_right){right = right->_right;}_node = right;}else{//尋找孩子不在父親左的祖先Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_left){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}

3.4 const迭代器

在這里插入圖片描述

代碼如下(示例):

//普通迭代器構造const迭代器
__RBTreeIterator(const __RBTreeIterator<T,T&,T*>& it):_node(it._node)
{}

3.5 復用紅黑樹接口實現set/map中的成員函數

3.5.1 set成員函數

代碼如下(示例):

template<class K>
class set
{struct SetKeyOfT{const K& operator()(const K& key){return key;}};
public://typename聲明是一個類型而不是靜態變量typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;typedef typename RBTree<K, K, SetKeyOfT>::const_iterator 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);}//刪除函數void erase(const K& key){_t.Erase(key);}//查找函數iterator find(const K& key){return _t.Find(key);}
private:RBTree<K, K, SetKeyOfT> _t;
};

3.5.2 map成員函數

代碼如下(示例):

template<class K, class V>
class map
{//仿函數struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};
public://typename聲明是一個類型而不是靜態變量typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator; typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator 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>& key){return _t.Insert(key);}//刪除函數void erase(const K& key){_t.Erase(key);}//查找函數iterator find(const K& key){return _t.Find(key);}//[]運算符重載V& operator[](const K& key){pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));return ret.first->second;}
private:RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};

在這里插入圖片描述


四、源代碼總結

4.1 Myset.h

代碼如下(示例):

#pragma once
// 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>::ConstIteratorconst_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);}
}

4.2 Mymap.h

代碼如下(示例):

#pragma once
#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>::Iteratoriterator;typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::ConstIteratorconst_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;}
}

4.3 RBTree.h

代碼如下(示例):

#pragma once
#include<iostream>
using namespace std;// 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 uif (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 pNode* 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// cif (cur == parent->_right){RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{// g// u p// cRotateR(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.pswp.cn/web/92418.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/92418.shtml
英文地址,請注明出處:http://en.pswp.cn/web/92418.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

根據ASTM D4169-23e1標準,如何選擇合適的流通周期進行測試?

根據ASTM D4169-23e1標準及行業實踐&#xff0c;選擇流通周期&#xff08;DC&#xff09;需綜合以下因素&#xff1a;一、核心選擇依據?產品屬性與包裝形式??重量體積?&#xff1a;輕小包裹&#xff08;<4.53kg且<0.056m&#xff09;適用DC2/3/4/6/9/13-17等周期&…

MySQL的觸發器:

目錄 觸發器的概念&#xff1a; 創建觸發器&#xff1a; 查看觸發器&#xff1a; 查看當前數據庫的所有觸發器的定義&#xff1a; 查看當前數據中某個觸發器的定義&#xff1a; 從系統information_schema的TRIGGERS表中查詢"salary_check_trigger"觸發器的信息…

基于ubuntu搭建gitlab

原文地址&#xff1a;基于ubuntu搭建gitlab – 無敵牛 歡迎參觀我的網站&#xff1a;無敵牛 – 技術/著作/典籍/分享等 之前介紹了一個使用 git openssh-server 搭建一個極簡 git 庫的方法&#xff0c;感興趣可以查看往期文章&#xff1a;手搓一個極簡遠端git庫 – 無敵牛 。…

測試GO前沿實驗室:為水系電池研究提供多維度表征解決方案

測試GO前沿實驗室&#xff1a;為水系電池研究提供多維度表征解決方案隨著全球能源轉型加速&#xff0c;水系電池因其高安全性、低成本和環境友好特性&#xff0c;成為下一代儲能技術的重要發展方向。測試狗前沿實驗室針對水系電池研發中的關鍵科學問題&#xff0c;整合先進表征…

Spring Boot 中 YAML 配置文件詳解

Spring Boot 中 YAML 配置文件詳解 在 Spring Boot 項目中&#xff0c;配置文件是不可或缺的一部分&#xff0c;用于自定義應用行為、覆蓋默認設置。除了傳統的 properties 文件&#xff0c;Spring Boot 對 YAML&#xff08;YAML Ain’t Markup Language&#xff09;格式提供了…

Milvus安裝可視化工具,attu,保姆級

安裝包鏈接&#xff1a;GitHub - zilliztech/attu: Web UI for Milvus Vector Databasehttps://github.com/zilliztech/attu?tabreadme-ov-file 下滑 舉例&#xff1a;windows&#xff1a;下載安裝&#xff0c;然后就可以連接了&#xff08;安裝完打開后如果需要輸入用戶名密碼…

避免“卡脖子”!如何減少內存I/O延遲對程序的影響?

單來說&#xff0c;內存 IO 就像是計算機的 “數據高速公路”&#xff0c;負責在內存和其他設備&#xff08;如硬盤、CPU 等&#xff09;之間傳輸數據。它的速度和效率直接影響著計算機系統的整體性能。 你有沒有想過&#xff0c;當你點擊電腦上的一個應用程序&#xff0c;它是…

V4L2攝像頭采集 + WiFi實時傳輸實戰全流程

&#x1f4d6; 推薦閱讀&#xff1a;《Yocto項目實戰教程:高效定制嵌入式Linux系統》 &#x1f3a5; 更多學習視頻請關注 B 站&#xff1a;嵌入式Jerry V4L2攝像頭采集 WiFi實時傳輸實戰全流程 1. 實戰場景概述 目標&#xff1a; 嵌入式設備&#xff08;如RK3588/正點原子開發…

Java 之 設計模式

1.單例模式1. ??餓漢式&#xff08;Eager Initialization&#xff09;????核心原理??&#xff1a;類加載時立即創建實例&#xff0c;通過靜態變量直接初始化。??代碼示例??&#xff1a;public class Singleton {private static final Singleton INSTANCE new Sing…

[激光原理與應用-185]:光學器件 - BBO、LBO、CLBO晶體的全面比較

一、相同點非線性光學晶體屬性BBO、LBO、CLBO均為非中心對稱晶體&#xff0c;具備非線性光學效應&#xff0c;廣泛應用于激光頻率轉換&#xff08;如倍頻、三倍頻、和頻、差頻&#xff09;、光學參量振蕩&#xff08;OPO&#xff09;及電光調制等領域。寬透光范圍三者均覆蓋紫外…

Android APN加載耗時優化可行性分析

背景 根據Android系統底層機制和行業實踐,本文討論 APN 加載耗時從4.2s降至0.8s的數據合理性和技術可行性,需結合具體優化手段和硬件環境綜合分析。 以下是關鍵判斷依據及行業參考: ?? 一、APN加載耗時基準參考 未優化場景的典型耗時 首次開機或重置后:APN需從apns-con…

mysql進階-sql調優

概述優化索引在MySQL初階的課程中已經介紹了索引&#xff0c;我們知道InnoDB存儲引擎使?B樹作為索引默認的數據結構來組織數據&#xff0c;為頻繁查詢的列建?索引可以有效的提升查詢效率&#xff0c;那么如何利?索引編寫出?效的SQL查詢語句&#xff1f;以及如何分析某個查詢…

海量數據處理問題詳解

1.從a&#xff0c;b兩個文件各存放50億個url&#xff08;每個url大小為64B&#xff09;&#xff0c;如何在內存為4G中查找a&#xff0c;b中相同的url 計算各文件存放大小&#xff1a;50億*64B 大約為320G&#xff0c;而內存只有4G&#xff0c;顯然存放不下&#xff0c;此時我們…

AI 記憶管理系統:工程實現設計方案

本文檔為《從“健忘”到“懂我”&#xff1a;構建新一代AI記憶系統》中所述理念的詳細工程實現方案。它將聚焦于技術選型、模塊設計、數據流轉和核心算法&#xff0c;為開發團隊提供清晰的落地指引。 1. 系統架構與技術選型 為實現分層記憶與讀寫分離的設計理念&#xff0c;我們…

Linux驅動學習day26天(RS485)

一、原理通過芯片將232信號轉換成485信號&#xff0c;485表示0和1的方法&#xff1a;Va - Vb 的電壓差在2~6V時表示1&#xff0c;Va - Vb 的電壓差在-2~-6V時表示0。這樣傳輸不容易受到干擾&#xff0c;并且傳輸距離長。我們需要做的事情就是發送&#xff1a;使能DE(driver ena…

從零構建TransformerP1-了解設計

歡迎來到啾啾的博客&#x1f431;。 記錄學習點滴。分享工作思考和實用技巧&#xff0c;偶爾也分享一些雜談&#x1f4ac;。 有很多很多不足的地方&#xff0c;歡迎評論交流&#xff0c;感謝您的閱讀和評論&#x1f604;。 目錄引言1 概念回顧1.1 序列任務1.1.1 將序列變成模型…

JVM 終止機制詳解:用戶線程與守護線程

用戶線程未執行完是否會阻止 JVM 終止&#xff1f;答案是&#xff1a;取決于線程類型。讓我詳細解釋&#xff1a; 核心規則 #mermaid-svg-bg5xpyMAeRWNGGk2 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-bg5xpyMAe…

Linux Vim 常用快捷鍵

Vim中最常用的快捷鍵&#xff0c;熟練掌握它們可以大大提高編輯效率。移動光標h- 左移j- 下移k- 上移l- 右移w- 移動到下一個單詞開頭b- 移動到上一個單詞開頭e- 移動到單詞末尾0- 移動到行首$- 移動到行尾gg- 移動到文件開頭G- 移動到文件末尾:n- 跳轉到第n行插入模式i- 在光標…

【Bellman負環】Cycle Finding

題目翻譯給定一個有向圖&#xff0c;你的任務是判斷它是否包含負環&#xff0c;并給出這樣一個環的示例。輸入 第一行輸入兩個整數 n 和 m&#xff1a;分別表示節點數和邊數。節點編號為 1, 2, ..., n。 接下來 m 行描述邊&#xff0c;每行有三個整數 a, b, c&#xff1a;表示存…

數據結構(六):樹與二叉樹

一、樹的基本概念樹的定義樹&#xff08;Tree&#xff09;是由 n&#xff08;n ≥ 0&#xff09;個節點組成的有限集合&#xff0c;當 n 0 時稱為空樹。非空樹中&#xff1a;有且僅有一個根節點&#xff08;Root&#xff09;&#xff1b;其余節點可以劃分為若干個互不相交的子…