C++進階:紅黑樹介紹及模擬實現(圖示詳解過程)

C++進階:紅黑樹介紹及模擬實現

上次介紹了AVL樹:C++進階:AVL樹詳解及模擬實現(圖示講解旋轉過程)

今天就來緊接著來紅黑樹啦!!!


文章目錄

  • 1.紅黑樹介紹
    • 約束規則
  • 2.項目文件規劃
  • 3.整體框架(節點和Tree)
  • 4.RBL樹的新節點插入
    • 4.1 叔叔節點存在且為紅
    • 4.2 叔叔節點不存在
    • 4.3叔叔節點存在而且為黑(單旋情況,左子樹的左,和右子樹的右)
    • 4.4叔叔節點存在而且為黑(雙旋情況,左子樹的右,和右子樹的左)
    • 4.5完整版Insert()
  • 5.中序方便過會測試
  • 6.編寫函數看是否滿足要求
  • 7.測試
  • 8.全部代碼
    • 8.1 RBTree.h
    • 8.2 test.cpp


1.紅黑樹介紹

紅黑樹是一種自平衡的二叉搜索樹,它在每個節點上增加了一個表示顏色的存儲位,可以是紅色(Red)或黑色(Black)。 通過對任何一條從根到葉子的路徑上各個結點著色方式的限制,紅黑樹確保沒有一條路徑會比其他路徑長出倆倍,因而是接近平衡的從而保證了查找、插入和刪除操作的時間復雜度為 O ( l o g N ) O(logN) O(logN)

約束規則

  1. 每個結點是紅色或者黑色

  2. 根節點是黑色

  3. 如果一個節點是紅色的,則它的兩個孩子結點是黑色的(不能有連續的紅節點

  4. 對于每個結點,從該結點到其所有后代葉結點的簡單路徑上,均包含相同數目的黑色結點

  5. 葉子節點(NIL節點)是黑色的(此處的葉子結點指的是空結點)

RB1

2.項目文件規劃

RB2

頭文件RBTree.h:進行模擬的編寫

源文件test.cpp:進行測試,檢查代碼邏輯是否滿足期望

3.整體框架(節點和Tree)

enum Colour//使用枚舉來定義,后面模擬哈希時也會用到類似的
{RED,BLACK
};template<class K,class V>
struct RBTreeNode
{RBTreeNode<K, V>* _left;//左節點RBTreeNode<K, V>* _right;//右節點RBTreeNode<K, V>* _parent;//父親節點Colour _col;//顏色,紅和黑嘛pair<K,V> _kv;//節點里存pairRBTreeNode(const pair<K, V>& kv)//都直接在初始化列表里初始化了:_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _col(RED)//這里新插入的節點一定要是紅色,黑色的話會直接破壞規則{}
};template<class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;//名字太長了,叫Node也更好理解
public:private:Node* _root = nullptr;//給上缺省值
};

4.RBL樹的新節點插入

基本步驟:

  1. 查找插入位置: 首先,我們需要找到新節點應該插入的位置。從根節點開始,按照二叉搜索樹的性質,逐級向左或向右比較鍵值,直到找到一個合適的位置

  2. 插入新節點: 找到插入位置后,我們創建一個新的節點,顏色為紅,并將其插入到樹中。如果樹為空,則新節點成為樹的根節點。否則,將新節點插入到合適的位置,使得樹仍然保持二叉搜索樹的性質。

  3. 插入后有需要變化時情況很多,下面具體分析

因為新節點的默認顏色是紅色,因此:如果其雙親節點的顏色是黑色,沒有違反紅黑樹任何性質,則不需要調整;但當新插入節點的雙親節點顏色為紅色時,就違反了性質三不能有連在一起的紅色節點,此時需要對紅黑樹分情況來討論:

如果新插入節點的父親節點是黑,那根本不會違反規則,如果要調整只有如下情況:

RB3

bool Insert(const pair<K,V> kv){if (_root == nullptr)//如果為空,直接更換新節點{_root = new Node(kv);_root->_col = BLACK;//注意默認是紅,這里改成黑return true;}Node* parent = nullptr;//存一下,新根才能鏈接Node* cur = _root;while (cur)//開始找插入位置{if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;//不能有相等的}}cur = new Node(kv); //這是默認紅色的if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//新節點鏈接成功了while (parent != nullptr && parent->_col == RED)//父親節點存在且是紅進來,黑的直接滿足不用調整{//這里進行處理}_root->_col = BLACK;//最后直接改根節點,不用再具體考慮return true;}

4.1 叔叔節點存在且為紅

以下步驟來調整:

  1. 將父節點和叔叔節點都改為黑色。
  2. 將祖父節點改為紅色。
  3. 將當前節點指向祖父節點,并將祖父節點設為當前節點的父節點(開始向上走)。

RB4

4.2 叔叔節點不存在

如果u節點不存在,則cur一定是新插入節點,因為如果cur不是新插入節點則cur和p一定有一個節點的顏色是黑色,就不滿足性質4: 每條路徑黑色節點個數相同。

RB5

  1. p為g的左孩子,cur為p的左孩子,則進行右單旋轉

p為g的右孩子,cur為p的右孩子,則進行左單旋轉

  1. p、g變色—>p變黑,g變紅
void RotateL(Node* parent)//左旋{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;Node* ppnode = parent->_parent;parent->_parent = subR;if (parent == _root){_root = subR;subR->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = subR;}else{ppnode->_right = subR;}subR->_parent = ppnode;}}void RotateR(Node* parent)//右旋{++rotateSize;Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;subL->_right = parent;Node* ppnode = parent->_parent;parent->_parent = subL;if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = subL;}else{ppnode->_right = subL;}subL->_parent = ppnode;}}

4.3叔叔節點存在而且為黑(單旋情況,左子樹的左,和右子樹的右)

如果u節點存在,則其一定是黑色的,那么cur節點原來的顏色一定是黑色的現在看到其是紅色的原因是因為cur的子樹在調整的過程中將cur節點的顏色由黑色改成紅色

RB6

4.4叔叔節點存在而且為黑(雙旋情況,左子樹的右,和右子樹的左)

p為g的左孩子,cur為p的右孩子,左右雙旋+變色
p為g的右孩子,cur為p的左孩子,右左雙旋 +變色

4.5完整版Insert()

bool Insert(const pair<K,V> kv){if (_root == nullptr)//如果為空,直接更換新節點{_root = new Node(kv);_root->_col = BLACK;//注意默認是紅,這里改成黑return true;}Node* parent = nullptr;//存一下,新根才能鏈接Node* cur = _root;while (cur)//開始找插入位置{if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;//不能有相等的}}cur = new Node(kv); //這是默認紅色的if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//新節點鏈接成功了while (parent != nullptr && parent->_col == RED)//父親節點存在且是紅進來,黑的直接滿足不用調整{Node* grandfather = parent->_parent;//接下來分兩種:parent是grandfather左或者右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//情況二:叔叔不存在或者存在且為黑{if (cur == parent->_left)//cur在parent左,單旋{//       g//    p    u// cRotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else//cur在parent右,雙旋{//       g//    p     u//      cRotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}//情況二一旦旋轉完了,不用向上了break;}else//parent是grandfather右{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//            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 true;}

5.中序方便過會測試

	void InOrder(){_InOrder(_root);}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_kv.first<< endl;_InOrder(root->_right);}

6.編寫函數看是否滿足要求

就從規定出發:

  1. 根節點不是黑的不滿足
  2. 不是每條路徑的黑色節點數量都相同
  3. 存在連續的紅節點了

這些都是不滿足要求

	bool IsBalance(){if (_root->_col == RED){return false;}//這里我們先算一條路徑的黑色節點數量,作為參考int ref = 0;Node* cur = _root;while (cur){if(cur->_col==BLACK)ref++;cur = cur->_left;//就求最左路徑}return Check(_root, 0, ref);}bool Check(Node* cur, int blackNum, int ref){if (cur == nullptr)//==nullptr 說明一條路徑走完了{if (blackNum != ref){cout << "黑色節點的數量不相等" << endl;return false;}return true;}//這里開始檢查沒有連續的紅,就看每個cur節點和他的父親就行if (cur->_col == RED && cur->_parent->_col == RED){cout << cur->_kv.first << "存在連續的紅色節點" << endl;return false;}if (cur->_col == BLACK){blackNum++;}return Check(cur->_left, blackNum, refBlackNum)&& Check(cur->_right, blackNum, refBlackNum);//遞歸進去找}

IsBalance() 函數首先檢查根節點的顏色是否為紅色,如果是,則不滿足紅黑樹的性質。然后,通過調用 Check() 函數來遞歸檢查每個節點,確保在每條路徑上沒有連續的紅色節點,并統計路徑上的黑色節點數量,最后與參考值進行比較。

Check() 函數中,遞歸遍歷每個節點,并檢查其顏色。如果當前節點為紅色,并且其父節點也為紅色,則說明存在連續的紅色節點,不滿足紅黑樹的性質。如果當前節點為黑色,則增加黑色節點計數器。遞歸地對當前節點的左右子節點進行檢查,直到遍歷完整棵樹的所有路徑。

通過這樣的檢查,我們可以驗證紅黑樹是否滿足性質,從而確認樹的平衡性。


7.測試

void TestRBTree1()
{int a[] = { 4, 2, 6, 1, 3, 5, 15};RBTree<int, int> t;for (auto e : a){t.Insert(make_pair(e, e));}t.InOrder();cout << t.IsBalance() << endl;
}

RB7


8.全部代碼

8.1 RBTree.h

#pragma onceenum Colour//使用枚舉來定義,后面模擬哈希時也會用到類似的
{RED,BLACK
};template<class K,class V>
struct RBTreeNode
{RBTreeNode<K, V>* _left;//左節點RBTreeNode<K, V>* _right;//右節點RBTreeNode<K, V>* _parent;//父親節點Colour _col;//顏色,紅和黑嘛pair<K,V> _kv;//節點里存pairRBTreeNode(const pair<K, V>& kv)//都直接在初始化列表里初始化了:_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _col(RED)//這里新插入的節點一定要是紅色,黑色的話會直接破壞規則{}
};template<class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;//名字太長了,叫Node也更好理解
public:bool Insert(const pair<K,V> kv){if (_root == nullptr)//如果為空,直接更換新節點{_root = new Node(kv);_root->_col = BLACK;//注意默認是紅,這里改成黑return true;}Node* parent = nullptr;//存一下,新根才能鏈接Node* cur = _root;while (cur)//開始找插入位置{if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;//不能有相等的}}cur = new Node(kv); //這是默認紅色的if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//新節點鏈接成功了while (parent != nullptr && parent->_col == RED)//父親節點存在且是紅進來,黑的直接滿足不用調整{Node* grandfather = parent->_parent;//接下來分兩種:parent是grandfather左或者右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//情況二:叔叔不存在或者存在且為黑{if (cur == parent->_left)//cur在parent左,單旋{//       g//    p    u// cRotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else//cur在parent右,雙旋{//       g//    p     u//      cRotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}//情況二一旦旋轉完了,不用向上了break;}else//parent是grandfather右{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//            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 true;}void RotateL(Node* parent)//左旋{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;Node* ppnode = parent->_parent;parent->_parent = subR;if (parent == _root){_root = subR;subR->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = subR;}else{ppnode->_right = subR;}subR->_parent = ppnode;}}void RotateR(Node* parent)//右旋{Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;subL->_right = parent;Node* ppnode = parent->_parent;parent->_parent = subL;if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = subL;}else{ppnode->_right = subL;}subL->_parent = ppnode;}}void InOrder(){_InOrder(_root);}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_kv.first<< endl;_InOrder(root->_right);}bool IsBalance(){if (_root->_col == RED){return false;}//這里我們先算一條路徑的黑色節點數量,作為參考int ref = 0;Node* cur = _root;while (cur){if(cur->_col==BLACK)ref++;cur = cur->_left;//就求最左路徑}return Check(_root, 0, ref);}bool Check(Node* cur, int blackNum, int ref){if (cur == nullptr)//==nullptr 說明一條路徑走完了{if (blackNum != ref){cout << "黑色節點的數量不相等" << endl;return false;}return true;}//這里開始檢查沒有連續的紅,就看每個cur節點和他的父親就行if (cur->_col == RED && cur->_parent->_col == RED){cout << cur->_kv.first << "存在連續的紅色節點" << endl;return false;}if (cur->_col == BLACK){blackNum++;}return Check(cur->_left, blackNum, ref)&& Check(cur->_right, blackNum, ref);//遞歸進去找}private:Node* _root = nullptr;//給上缺省值
};void TestRBTree1()
{int a[] = { 4, 2, 6, 1, 3, 5, 15};RBTree<int, int> t;for (auto e : a){t.Insert(make_pair(e, e));}t.InOrder();cout << t.IsBalance() << endl;
}

8.2 test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;#include"RBTree.h"int main()
{TestRBTree1();return 0;
}

今天就到這里啦!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/12455.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/12455.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/12455.shtml

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

相關文章

whisper報錯:hp, ht, pid, tid = _winapi.CreateProcess [WinError 2] 系統找不到指定的文件。

in _execute_child hp&#xff0c; ht&#xff0c; pid&#xff0c; tid _winapi.CreateProcess&#xff08;executable&#xff0c; args&#xff0c; FileNotFoundError&#xff1a; [WinError 2] 系統找不到指定的文件。 原因&#xff1a; 沒裝ffmpeg 或者 ffmpeg沒添加到…

k8s pod就緒探針

Pod 可能需要時間來加載配置或數據&#xff0c;或者可能需要執行預熱過程以防止第一個用戶請求時間太長影響了用戶體驗。在這種情況下&#xff0c;不希望該 pod 立即開始接收請求&#xff0c;尤其是在運行的實例可以正確快速地處理請求的情況下。不要將請求轉發到正在啟動的 po…

YOLOv5獨家改進:backbone改進 | 微軟新作StarNet:超強輕量級Backbone | CVPR 2024

??????創新點:star operation(元素乘法)在無需加寬網絡下,將輸入映射到高維非線性特征空間的能力,這就是StarNet的核心創新,在緊湊的網絡結構和較低的能耗下展示了令人印象深刻的性能和低延遲 ??????如何跟YOLOv5結合:替代YOLOv5的backbone 收錄 YOL…

電容筆記匯總

電容 一、電容理論基礎 1、電容的本質 兩個相互靠近的導體&#xff0c;中間夾一層不導電的絕緣介質&#xff0c;這就構成了電容器。當電容器的兩個極板之間加上電壓時&#xff0c;電容器就會儲存電荷。 兩個相互靠近的金屬板中間夾一層絕緣介質組成的器件&#xff0c;當兩端…

豆漿機缺水檢測功能如何實現的

豆漿機缺水檢測功能的實現是通過光學液位傳感器來完成的。這種傳感器具有多種優勢&#xff0c;如內部所有元器件經過樹脂膠封處理&#xff0c;沒有任何機械活動部件&#xff0c;免調試、免檢驗、免維護等特點。它采用了光電液位傳感器內置的光學電子元件&#xff0c;體積小、功…

Docker常用鏡像安裝

1. mysql 1.1 安裝 獲取鏡像 docker pull mysql:8.0.30創建文件掛載目錄 創建容器并運行 docker run -p 3306:3306 --name mysql8 \ -v /home/docker/mysql8/log:/var/log/mysql \ -v /home/docker/mysql8/data:/var/lib/mysql \ -v /home/docker/mysql8/mysql-files:/va…

保研機試之【設備驅動程序】

B選項&#xff1a; 綜上&#xff0c;我認為這道題選擇D~

一些近來對內網攻防的思考

我知道我最近托更托了很久了&#xff0c;其實也不是小編懶啊 這小編也是一直在寫&#xff0c;但是遇到的問題比較多&#xff08;我太菜了&#xff09;&#xff0c;所以一直拖著。 但是總不能不更吧 那就講一下進來的一些內網攻防的思考吧 1.CrossC2上線Linux到CS(成功) …

用友網絡的危與機:2023年虧損約10億元,王文京面臨嚴肅拷問

“企業在新的產業浪潮來臨時&#xff0c;應該主動推進新階段的產品和業務創新&#xff0c;這樣才能夠在新的浪潮成為主流的時候&#xff0c;走到行業前面&#xff0c;否則就會從產業發展的潮流中掉下來”。用友網絡創始人王文京&#xff0c;曾用“沖浪理論”形容一家企業成功的…

Steam喜加一,限時免費領取《Machinika Museum》

《Machinika Museum》限時免費領取啦&#xff01;這是一款燒腦解謎游戲&#xff0c;讓你挖掘神秘外星裝置的秘密。在這個非常特別的異星裝置博物館里&#xff0c;你將扮演一名研究員&#xff0c;負責解開各種機械謎題&#xff0c;探索背后的故事。 在這個未來世界&#xff0c;外…

MLP的代替:KAN

受柯爾莫哥洛夫-阿諾德表示定理的啟發&#xff0c;作者提出柯爾莫哥洛夫-阿諾德網絡&#xff08;KAN&#xff09;作為多層感知器&#xff08;MLP&#xff09;有前途的替代品。MLP 在節點&#xff08;“神經元”&#xff09;上具有固定的激活函數&#xff0c;而 KAN 在邊&#x…

自動化中遇到的問題歸納總結

1、動態元素定位不到 解決方法&#xff1a;盡量使用固定元素定位&#xff0c;如沒有固定元素&#xff0c;則采用絕對路徑進行定位&#xff0c;因為元素路徑是唯一且不變的 2、自動化腳本執行速度較慢 盡量使用css方法定位元素&#xff0c;使用等待時&#xff0c;少用sleep方…

C#中string.format的格式和用法

C#中string.format的格式和用法 第1部分 格式化數字 string str1 string.Format("{0:N1}",56789); //result: 56,789.0string str2 string.Format("{0:N2}",56789); //result: 56,789.00string str3 string.Format("{0:…

Kubernetes 文檔 / 概念 / 容器 / 容器環境

Kubernetes 文檔 / 概念 / 容器 / 容器環境 此文檔從 Kubernetes 官網摘錄 中文地址 英文地址 容器環境 Kubernetes 的容器環境給容器提供了幾個重要的資源&#xff1a; 文件系統&#xff0c;其中包含一個鏡像 和一個或多個的卷容器自身的信息集群中其他對象的信息 容器信…

[筆記] srlua庫編譯

文章目錄 前言一、環境二、編譯過程2.1 gcc安裝2.2 編譯lua2.3 編譯srlua庫 三、測試srlua庫參考總結 前言 一、環境 centos7.9 gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) lua5.1源碼 srlua 源碼 二、編譯過程 2.1 gcc安裝 yum install gcc這里gcc安裝過程和環…

蘋果電腦卡頓反應慢怎么辦 蘋果電腦卡頓嚴重解決方法 mac電腦太卡了怎么辦

作為Mac用戶&#xff0c;你是否正在經歷或者曾經遭遇過電腦卡頓、反應慢的困擾&#xff1f;這可能是由于多種原因導致的&#xff0c;包括自啟動程序過多、系統與應用未及時更新、內存管理不當等。今天和你一起來探討下&#xff0c;蘋果電腦卡頓反應慢時怎么辦。希望能夠幫助你解…

KBPC5010-ASEMI電源控制柜專用KBPC5010

編輯&#xff1a;ll KBPC5010-ASEMI電源控制柜專用KBPC5010 型號&#xff1a;KBPC5010 品牌&#xff1a;ASEMI 封裝&#xff1a;KBPC-4 正向電流&#xff08;Id&#xff09;&#xff1a;50A 反向耐壓&#xff08;VRRM&#xff09;&#xff1a;1000V 正向浪涌電流&#x…

FreeRTOS中的動態內存管理(heap_1、heap_2、heap_3、heap_4)

FreeRTOS 提供了多種動態內存分配方案&#xff0c;這些方案通過不同的內存管理器&#xff08;heap managers&#xff09;實現&#xff0c;主要位于 FreeRTOS/Source/portable/MemMang 目錄下。以下是幾種常見的動態內存分配方案&#xff1a; heap_1 特點&#xff1a; 簡單性…

大數據可視化實驗(四):Excel數據可視化

目錄 一、實驗目的... 1 二、實驗環境... 1 三、實驗內容... 1 1&#xff09;excel函數應用.. 1 2&#xff09;數據透視圖繪制... 3 四、總結與心得體會... 5 一、實驗目的 1&#xff09;掌握函數和公式的原理 2&#xff09;掌握在單元格或編輯欄中直接輸入帶函數的公式…

kafka學習筆記04(小滴課堂)

Kafka的producer生產者發送到Broker分區策略講解 Kafka核心API模塊-producer API講解實戰 代碼&#xff1a; ProducerRecord介紹和key的作用 Kafka核心API模塊-producerAPI回調函數實戰 producer生產者發送指定分區實戰 我們設置5個分區。 我們指定分區。 重新指定一個分區&am…