【C++進階】第7課—紅黑樹

文章目錄

  • 1. 認識紅黑樹
    • 1.1 紅黑樹的規則
    • 1.2 紅黑樹如何確保最長路徑不超過最短路徑的2倍呢?
    • 1.3 紅黑樹的效率
  • 2. 實現紅黑樹
    • 2.1 紅黑樹的結構
    • 2.2 紅黑樹的插入
      • 2.2.1 第一種情況:插入節點的父節點和其uncle節點都為紅色,且uncle節點存在
      • 2.2.2 第2種情況:插入節點cur和其父節點為紅,其uncle節點不存在或者為黑色
      • 2.2.3 第3種情況:uncle節點不存在或者為黑色,且cur節點和parent節點為紅
    • 2.3 紅黑樹的查找
    • 2.4 紅黑樹的驗證
  • 3. 代碼

在這里插入圖片描述
前面我們學過了控制二叉搜索樹平衡的AVL樹,今天我們就來學習控制二叉搜索樹平衡的另一種—紅黑樹

1. 認識紅黑樹

  • 紅黑樹(Red-Black Tree)是一種自平衡的二叉查找樹(BST),通過特定的規則和旋轉操作維持樹的平衡,從而保證高效的查找、插入和刪除操作。它的核心用途是在動態數據集中提供對數時間復雜度(O(logN))的搜索、插入和刪除性能,尤其適用于需要頻繁修改且要求高效查詢的場景
  • 紅黑樹是?棵二叉搜索樹,他的每個結點增加一個存儲位來表示結點的顏色,可以是紅色或者黑色。通過對任何一條從根到葉子的路徑上各個結點的顏色進行約束,紅黑樹確保沒有一條路徑會比其他路徑長出2倍,因而是接近平衡的

1.1 紅黑樹的規則

  1. 每個節點不是紅色就是黑色
  2. 根節點是黑色的
  3. 如果一個節點是紅色的,那么它的兩個孩子節點必須是黑色的,也就是說任意一條路徑不會有連續的紅色節點
  4. 對于任意一條路徑,從該節點到其所有NULL節點的簡單路徑上,均包含相同數量的黑色節點
    在這里插入圖片描述

在這里插入圖片描述


1.2 紅黑樹如何確保最長路徑不超過最短路徑的2倍呢?

  • 由規則4可知,從根到NULL結點的每條路徑都有相同數量的黑色結點,所以極端場景下,最短路徑就就是全是黑色結點的路徑,假設最短路徑長度為bh(black height)
  • 由規則2和規則3可知,任意一條路徑不會有連續的紅色結點,所以極端場景下,最長的路徑就是一黑一紅間隔組成,那么最長路徑的長度為2*bh
  • 綜合紅黑樹的4點規則而言,理論上的全黑最短路徑和一黑一紅的最長路徑并不是在每棵紅黑樹都存在的。假設任意一條從根到NULL結點路徑的長度為x,那么bh <= x <= 2*bh

1.3 紅黑樹的效率

在這里插入圖片描述


  • 假設N是紅黑樹樹中結點數量,h最短路徑的長度,那么 , 由此推出h ≈ logN,也就是意味著紅黑樹增刪查改最壞也就是走最長路徑 ,那么時間復雜度還是O(logN)
  • 紅黑樹的表達相對AVL樹要抽象?些,AVL樹通過高度差直觀的控制了平衡。紅黑樹通過4條規則的顏色約束,間接的實現了近似平衡,他們效率都是同?檔次,但是相對而言,插入相同數量的節點,紅黑樹的旋轉次數是更少的,因為他對平衡的控制沒那么嚴格
  • 最差全黑

在這里插入圖片描述


2. 實現紅黑樹

2.1 紅黑樹的結構

在這里插入圖片描述


2.2 紅黑樹的插入

  • 1. 紅黑樹插入一個值按照二叉搜索樹的方式插入,插入后只需要觀察是否滿足紅黑樹的4條規則
  • 2. 如果是空樹插入,那么新插入的節點要給黑色。但如果是非空樹插入,那么新插入的節點則必須是紅色,因為如果是黑色,就破壞了紅黑樹任意路徑黑色節點相同的規則
  • 3.非空樹插入紅色節點后,如果它的父節點是黑色的,那么滿足4條規則,插入結束
  • 4.如果非空樹插入紅色節點后,其父節點是紅色的,則違反了紅黑樹任意一條路徑中不能出現連續紅色節點的規則,得進一步分析

在這里插入圖片描述


在這里插入圖片描述


2.2.1 第一種情況:插入節點的父節點和其uncle節點都為紅色,且uncle節點存在

在這里插入圖片描述


  • 注意:上述圖中只是最簡單的一種,無非就是將cur的父節點parent和uncle節點變色(紅→黑),再將grandfather節點變色(黑→紅)
  • 另外cur節點無論插在parent的左邊還是右邊,都滿足上述的變色邏輯
  • 當然上圖中這顆樹可能也只是棵子樹,需要繼續向上更新,那什么時候向上更新呢?
  • 向上更新的條件: g節點的父節點是紅色時,p、u、g節點變色后需繼續向上更新
  • 為什么說g節點的父節點是紅色就得繼續更新呢?因為g節點變完色后是紅色,紅黑樹不允許出現連續的紅色節點
  • 向上更新步驟:p、u、g節點變完色后,直接讓cur等于g節點,然后p、u、g節點隨著cur節點更新而更新,直到g節點的父節點為黑,插入結束
  • 當然,如果grandfather就是根節點,那么p、u、g節點變完色后,直接讓g節點重新變為黑色,插入結束

在這里插入圖片描述


在這里插入圖片描述


  • 代碼實現

在這里插入圖片描述


2.2.2 第2種情況:插入節點cur和其父節點為紅,其uncle節點不存在或者為黑色

  • 這種情況一般是:如果parent是grandfather左子樹節點,cur節點也是p左孩子的情況;或者parent是grandfather右子樹節點,cur節點也是p右孩子的情況
  • 因此第2種情況就是:cur節點和parent節點是它們的父節點的左孩子/右孩子方向是保持一致的
  • 對于uncle節點不存在的情況,則是直接以節點g為旋轉點進行右單旋,然后分別讓p節點變紅,g節點變黑

在這里插入圖片描述


  • 對于uncle節點存在且為黑色的情況,處理情況相同,同樣是以g節點為旋轉點進行右單旋,然后p節點為紅,g節點為黑

在這里插入圖片描述


  • 代碼實現

在這里插入圖片描述


2.2.3 第3種情況:uncle節點不存在或者為黑色,且cur節點和parent節點為紅

  • 這種情況一般是:如果parent是grandfather左子樹節點,cur節點是p右孩子的情況;或者parent是grandfather右子樹節點,cur節點是p左孩子的情況
  • 因此第2種情況就是:cur節點和parent節點是它們的父節點的左孩子/右孩子方向不保持一致
  • 第3種情況和第2種情況類似,只是單純一次單旋滿足不了紅黑樹的要求,需要雙旋+變色

在這里插入圖片描述


在這里插入圖片描述


  • 同樣和第2種情況類似,情景1:uncle節點不存在

在這里插入圖片描述


  • 情景2:uncle節點存在且為黑色

在這里插入圖片描述


  • 代碼實現

在這里插入圖片描述


  • 當然,對于左右單旋的代碼在上一節AVL樹有詳細講解,這里不過多贅述

2.3 紅黑樹的查找

  • 紅黑樹的查找按照二叉搜索樹的方式查找就行,效率O(logN)
//查找
Node* Find(const K& key)
{Node* cur = _root;if (key > cur->_kv.first)cur = cur->_right;else if (key < cur->_kv.first)cur = cur->_left;elsereturn cur;return nullptr;
}

2.4 紅黑樹的驗證

  • 這里獲取最長路徑和最短路徑,檢查最長路徑不超過最短路徑的2倍是不可行的,因為就算滿足這個條件,紅黑樹也可能顏色不滿足規則,當前暫時沒出問題,后續繼續插入還是會出問題的。所以我們還是去檢查4點規則,滿足這4點規則,一定能保證最長路徑不超過最短路徑的2倍
  • 1. 規則1枚舉顏色類型,天然實現保證了顏色不是黑色就是紅色
  • 2. 規則2直接檢查根即可
  • 3. 規則3前序遍歷檢查,遇到紅色結點查孩子不太方便,因為孩子有兩個,且不一定存在,反過來檢查父親的顏色就方便多了
  • 4. 規則4前序遍歷,遍歷過程中用形參記錄跟到當前結點的blackNum(黑色結點數量),前序遍歷遇到黑色結點就++blackNum,走到空就計算出了一條路徑的黑色結點數量。再任意一條路徑黑色結點數量作為參考值,依次比較即可

在這里插入圖片描述


  • 代碼實現

在這里插入圖片描述


3. 代碼

  • RBTree.h代碼
#pragma once
#include <iostream>
using namespace std;//枚舉常量
enum Colour
{RED,BLACK
};//紅黑樹節點
template <class K,class V>
struct RBTreeNode
{pair<K, V> _kv;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Colour _col;RBTreeNode(const pair<K,V> kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr),_col(RED){}
};//紅黑樹
template<class K,class V>
class RBTree
{typedef RBTreeNode<K, V> 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){//插入值比cur節點值大if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}//插入值比cur節點值小else if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}elsereturn false;}//插入節點cur = new Node(kv);cur->_col = RED;//如果插入值大于parent值if (kv.first > parent->_kv.first)parent->_right = cur;//如果插入值小于parent值else if (kv.first < parent->_kv.first)parent->_left = cur;//存儲cur節點的父節點cur->_parent = parent;//定義cur節點的p、u、g節點 ---> 更新while (parent && parent->_col == RED){Node* grandfather = parent->_parent;//如果parent為grandfather的左孩子if (parent == grandfather->_left){Node* uncle = grandfather->_right;//第一種情況:父親、叔叔都為紅,爺爺為黑if (uncle && uncle->_col == RED){uncle->_col = parent->_col = BLACK;grandfather->_col = RED;//繼續向上處理cur = grandfather;parent = cur->_parent;}//第2、3種情況else{//第2種情況 ---> uncle節點不存在或者為黑色//      g//   p     u//c 右單旋if(cur == parent->_left){RotateR(grandfather);grandfather->_col = RED;parent->_col = BLACK;}//第3種情況 ---> uncle節點不存在或者為黑色//      g//   p     u//      c  左單旋 + 右單旋else{RotateL(parent);RotateR(grandfather);grandfather->_col = RED;cur->_col = BLACK;}break;}}//如果parent為grandfather的右孩子else{Node* uncle = grandfather->_left;//第一種情況:父親、叔叔都為紅,爺爺為黑if (uncle && uncle->_col == RED){uncle->_col = parent->_col = BLACK;grandfather->_col = RED;//繼續向上處理cur = grandfather;parent = cur->_parent;}//第2、3種情況else{//第2種情況 ---> uncle節點不存在或者為黑色//      g//   u     p//左單旋       cif (cur == parent->_right){RotateL(grandfather);grandfather->_col = RED;parent->_col = BLACK;}//第3種情況 ---> uncle節點不存在或者為黑色//      g//   u     p//      c  右單旋 + 左單旋else{RotateR(parent);RotateL(grandfather);grandfather->_col = RED;cur->_col = BLACK;}break;}}}//直接賦予根節點黑色_root->_col = BLACK;return true;}//左單旋void RotateL(Node* parent){//定義兩個節點指針Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;subR->_left = parent;if (subRL)subRL->_parent = parent;Node* parent_Parent = parent->_parent;parent->_parent = subR;//如果parent為根節點if (parent_Parent == nullptr){_root = subR;subR->_parent = nullptr;}//如果parent不是根節點else{//如果旋轉之前parent所在的整個子樹為根節點的左子樹if (parent_Parent->_left == parent)parent_Parent->_left = subR;elseparent_Parent->_right = subR;subR->_parent = parent_Parent;}}//右單旋void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;subL->_right = parent;if (subLR)subLR->_parent = parent;Node* parent_Parent = parent->_parent;parent->_parent = subL;//如果parent為根節點if (parent == _root){_root = subL;subL->_parent = nullptr;}//如果parent不是根節點else{if (parent_Parent->_left == parent)parent_Parent->_left = subL;elseparent_Parent->_right = subL;subL->_parent = parent_Parent;}}//中序遍歷輸出AVL樹數據void Inorder(){_Inorder(_root);cout << endl;}void _Inorder(Node* root){if (root == nullptr)return;_Inorder(root->_left);cout << root->_kv.first << "-" << root->_kv.second << " ";_Inorder(root->_right);}//紅黑樹節點個數size_t Size(){return _Size(_root);}size_t _Size(Node* root){return root == nullptr ? 0 : _Size(root->_left) + _Size(root->_right) + 1;}//查找Node* Find(const K& key){Node* cur = _root;while(cur){if (key > cur->_kv.first)cur = cur->_right;else if (key < cur->_kv.first)cur = cur->_left;elsereturn cur;}return nullptr;}//前序遍歷查找每條路徑黑色節點個數bool Check(Node* root, int Count_BlackNode, int retNum){if (root == nullptr){if (Count_BlackNode != retNum){cout << "存在黑色節點數量不等的路徑" << endl;return false;}return true;}//root節點非空 ---> 檢查兩個孩子節點不方便,可能還有孩子不存在,直接檢查其父節點if (root->_col == RED && root->_parent->_col == RED){cout << root->_kv.first << "存在連續的紅色節點" << endl;return false;}//如果節點為黑色if (root->_col == BLACK){++Count_BlackNode;}return Check(root->_left, Count_BlackNode, retNum) && Check(root->_right, Count_BlackNode, retNum);}//檢查是否滿足平衡bool IsBalance(){if (_root == nullptr)return true;if (_root->_col == RED){cout << "根節點為紅色!" << endl;return false;}//記錄一條路徑上黑色節點數量int retNum = 0;Node* cur = _root;while (cur){if (cur->_col == BLACK){++retNum;}cur = cur->_left;}return Check(_root, 0, retNum);}private:Node* _root = nullptr;
};
  • 測試代碼test.cpp
#include"RBTree.h"
#include<vector>
//AVL樹的平衡測試
void RBTreetest1()
{RBTree<int, int> rb1;//常規測試//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };//for (auto& e : a)//{//	rb1.insert({ e,e });//}//帶有雙旋的測試用例int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };for (auto& e : a){rb1.insert({ e,e });}rb1.Inorder();cout << "Size:" << rb1.Size() << endl;
}void RBTreetest2()
{const int N = 1000000;vector<int> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; i++){v.push_back(i + rand());}size_t begin2 = clock();RBTree<int, int> t;for (size_t i = 0; i < v.size(); ++i){t.insert(make_pair(v[i], v[i]));}size_t end2 = clock();cout << "Insert:" << end2 - begin2 << endl;cout << "Size:" << t.Size() << endl;t.insert({ 20,20 });cout << t.Find(20) << endl;if (t.IsBalance())cout << "該二叉樹是紅黑樹!" << endl;elsecout << "該二叉樹不是紅黑樹!" << endl;}int main()
{//RBTreetest1();RBTreetest2();return 0;
}

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

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

相關文章

解決 SQL 錯誤 [1055]:深入理解 only_full_group_by 模式下的查詢規范

在日常的 SQL 開發中&#xff0c;你是否遇到過這樣的報錯&#xff1a;SQL 錯誤 [1055] [42000]: Expression #N of SELECT list is not in GROUP BY clause and contains nonaggregated column...&#xff1f;尤其是在 MySQL 5.7 及以上版本中&#xff0c;這個錯誤更為常見。本…

Keepalived 原理及配置(高可用)

一、Keepalived 原理keepalived 基于 VRRP&#xff08;虛擬路由冗余協議&#xff09;實現高可用。核心原理是通過競選機制在多臺服務器&#xff08;主 / 備節點&#xff09;中選舉出一臺主節點承擔服務&#xff0c;同時備節點持續監控主節點狀態&#xff1a;主節點正常時&#…

從代碼混亂到井然有序:飛算JavaAI的智能治理之道

文章目錄一、前言二、飛算JavaAI平臺三、飛算JavaAI安裝流程3.1 Idea安裝配置3.2 官網注冊登入四、飛算JavaAI獨特魅力:合并項目場景4.1 ERP老項目精準翻新&#xff1a;保留核心邏輯的智能改造方案4.2 智能合并&#xff1a;重構ERP系統的代碼迷宮4.3 ERP接口智能導航&#xff1…

iOS打開開發者模式

啟用開發者模式的方法在iOS設備上啟用開發者模式通常需要連接Xcode或通過設置手動開啟&#xff0c;以下是具體步驟&#xff1a;通過Xcode啟用將iOS設備通過USB線連接到Mac電腦。打開Xcode&#xff08;需提前安裝&#xff09;。在Xcode的菜單欄中選擇 Window > Devices and S…

leetcode101.對稱二叉樹樹(遞歸練習題)

文章目錄一、 題目描述二、 核心思路&#xff1a;判斷左右子樹是否互為鏡像三、 遞歸的終止條件 (Base Cases)四、 代碼實現與深度解析五、 關鍵點與復雜度分析六、 總結與對比 (LC100 vs LC101)LeetCode 101. 對稱二叉樹 - 力扣【難度&#xff1a;簡單&#xff1b;通過率&…

【國內電子數據取證廠商龍信科技】誰是躲在“向日葵”后的

一、前言大家可能每天都在使用在遠控軟件&#xff0c;我們在享受遠控軟件帶來的便利同時&#xff0c;犯罪者也在使用遠控軟件進行違法犯罪活動&#xff0c;以達到隱藏自己的目的。市面上常用的遠控軟件有“向日葵”、“TeamViewer”。二、案件背景在一次電信詐騙案件支援中&…

SAP-PP-MRPLIST

MRP(物料需求計劃)分析功能,主要包含以下要點: 程序通過選擇工廠和物料/銷售訂單范圍作為輸入條件,支持兩種展示方式:ALV表格和樹形結構 核心功能包括: 物料主數據查詢(MAKT/MARA表) 銷售訂單數據查詢(VBAP表) BOM展開(CS_BOM_EXPL_MAT_V2函數) MRP數據獲取(MA…

MIT線性代數01_方程組的幾何解釋

Linear Algebra Lecture #1 W. Gilbert Strangn linear equations, n unknowns row picturecol pictureMatrix form {2x?y0?x2y3 \left\{\begin{matrix} 2x - y 0 \\ -x 2y 3 \end{matrix}\right. {2x?y0?x2y3? 1 Row Picture2 Column PictureWhat are all combination…

FreeRTOS-中斷管理

學習內容中斷概念中斷是計算機系統中一種重要的事件驅動機制&#xff0c;用于在特定條件下打斷正在執行的程序&#xff0c;并跳轉到預定義的中斷處理程序中執行特定的操作。當發生中斷時&#xff0c;處理器會立即中止當前正在執行的指令&#xff0c;保存當前的執行狀態&#xf…

圖像梯度處理與邊緣檢測

在圖像處理的世界里&#xff0c;我們常常需要從復雜的像素矩陣中提取有意義的信息 —— 比如一張照片中物體的輪廓、醫學影像中病灶的邊界、自動駕駛視野里的道路邊緣。這些 “邊界” 或 “輪廓” 在專業術語中被稱為 “邊緣”&#xff0c;而捕捉邊緣的核心技術&#xff0c;離不…

GPU服務器與PC 集群(PC農場):科技算力雙子星

在數字經濟高速發展的今天&#xff0c;算力已成為驅動科技創新與產業變革的核心引擎。GPU服務器憑借其強大的并行計算能力&#xff0c;在圖形渲染、人工智能訓練等領域展現出不可替代的優勢&#xff1b;而PC集群則通過分布式架構&#xff0c;以高性價比和靈活擴展特性&#xff…

秋招Day19 - 分布式 - 分布式鎖

單體時代&#xff0c;可以直接用本地鎖來實現對競爭資源的加鎖&#xff0c;分布式環境下就要用到分布式鎖了有哪些分布式鎖的實現方案&#xff1f;MySQL分布式鎖、Zookeeper分布式鎖、Redis分布式鎖MySQL分布式鎖如何實現&#xff1f;創建一張鎖表&#xff0c;對字段定義唯一性…

AIStarter平臺亮點解析:從ComfyUI項目上架到一鍵運行的完整指南

大家好&#xff01;今天分享一個AIStarter平臺的深度體驗&#xff0c;帶你了解如何通過這個平臺輕松上架和運行AI項目&#xff01;視頻中&#xff0c;博主在凌晨分享了AIStarter的強大功能&#xff0c;重點展示了ComfyUI 4.0和5.0整合包的上架過程&#xff0c;以及如何簡化AI項…

電腦錄屏軟件推薦:如何使用oCam錄制游戲、教程視頻

在工作、學習或游戲過程中&#xff0c;我們經常需要錄制電腦屏幕&#xff0c;比如制作教程視頻、記錄游戲操作、分享軟件使用過程等。oCam 是一款功能強大且操作簡單的屏幕錄制工具&#xff0c;支持 Windows 系統&#xff0c;深受用戶喜愛。今天簡鹿辦公就來手把手教你如何使用…

安裝cuml報錯

安裝命令 &#xff08;注意cuda的版本&#xff09; pip install --no-cache-dir --extra-index-urlhttps://pypi.nvidia.com cuml-cu11 報錯&#xff1a; 找了很多網上的教程 1.版本問題 沒解決 pip install --upgrade pip pip install --upgrade setuptools 2.參考下面博…

【ECharts?】解決Vue 中 v-show 導致組件 ECharts 樣式異常問題

解決Vue 中 v-show 導致組件 ECharts 樣式異常問題 問題概述 在使用 Vue 的 v-show 指令實現 <PageOne/>、<PageTwo/>、<PageThree/> 三個視圖的定時切換時&#xff0c;<PageTwo/> 顯示時出現了異常&#xff0c;具體表現為 ECharts 圖表渲染圖表尺寸異…

旅游管理虛擬仿真實訓室:重構實踐教學新生態

在旅游產業數字化轉型與教育信息化深度融合的背景下&#xff0c;旅游管理虛擬仿真實訓室成為連接理論教學與行業實踐的關鍵紐帶。它通過沉浸式技術還原旅游場景&#xff0c;解決傳統實訓中資源受限、風險較高、時空局限等問題&#xff0c;為旅游管理專業人才培養提供全新路徑。…

【在線五子棋對戰】十、對戰玩家匹配管理模塊

文章目錄前言Ⅰ. 匹配隊列實現Ⅱ. 匹配隊列管理類實現完整代碼前言 五子棋對戰的玩家匹配是根據自己的天梯分數進行匹配的&#xff0c;而服務器中將玩家天梯分數分為三個檔次&#xff1a; 青銅&#xff1a;天梯分數小于 2000 分白銀&#xff1a;天梯分數介于 2000~3000 分之間…

k8s之ingress定義https訪問方式

接上文&#xff1a;https://blog.csdn.net/soso678/article/details/149607069?spm1001.2014.3001.5502定義后端應用與service [rootmaster ingress]# cat my-nginx.yml apiVersion: apps/v1 kind: Deployment metadata:name: my-nginx spec:selector:matchLabels:run: my-n…

《C++ vector 完全指南:vector的模擬實現》

《C vector 完全指南&#xff1a;vector的模擬實現》 文章目錄《C vector 完全指南&#xff1a;vector的模擬實現》一、定義vector的成員變量二、用vector實現動態二維數組三、vector的接口實現1.vector的默認成員函數&#xff08;1&#xff09;構造函數實現&#xff08;2&…