《電子技術應用》
您所在的位置:首頁 > 可編程邏輯 > 其他 > 講解:還沒吃透面試必問的紅黑樹?圖文并茂的讓你徹底理解紅黑樹

講解:還沒吃透面試必問的紅黑樹?圖文并茂的讓你徹底理解紅黑樹

2022-09-07
來源:電子技術應用專欄作家 一口Linux
關鍵詞: 紅黑樹

  什么是紅黑樹?本篇文章讓你徹底理解!

  1. 紅黑樹的概念

  紅黑樹,是一種二叉搜索樹,但在每個結點上增加一個存儲位表示結點的顏色,可以是Red或Black。 通過對任何一條從根到葉子的路徑上各個結點著色方式的限制,紅黑樹確保沒有一條路徑會比其他路徑長出倆倍,因而是接近平衡的。

  640 (22).png

  2. 紅黑樹的性質

  2.1. 每個結點不是紅色就是黑色

  2.2. 根節點是黑色的

  2.3. 如果一個節點是紅色的,則它的兩個孩子結點是黑色的(不會出現連在一起的紅色節點)

  2.4. 對于每個結點,從該結點到其所有后代葉結點的簡單路徑上,均包含相同數目的黑色結點(在計算一條路徑中黑色節點個數的時候要帶上葉子節點,因為葉子節點也是黑色的,也就是空節點)。

  2.5. 每個葉子結點都是黑色的(此處的葉子結點指的是空結點)(為了保證空樹也是紅黑樹)

  2.6.紅黑樹確保沒有一條路徑會比其他路徑長出倆倍(紅黑樹前面的性質保證了當前的性質)

  640 (14).png

  3. 紅黑樹的實現

  3.1. 帶頭節點的紅黑樹

  這里我們將紅黑樹的實現給為帶頭的紅黑樹,因為紅黑樹是map和set的底層數據結構這里我們實現出來紅黑樹就可以直接用當前我們實現的帶頭紅黑樹來實現map和set至于頭節點的給出是為了方便于map和set的遍歷,在STL中我們區間給出都是左閉右開區間的,既然紅黑樹作為map和set的底層數據結構那么我們就一定有位置要來放map和set的迭代器,那么就可以將begin位置的迭代器放在head的左,end位置的迭代器可以放在head位置。這里我們將紅黑樹頭節點的顏色給為紅色。

  640 (12).png

  3.2. 紅黑樹的節點

  640 (21).png

  3.3. 紅黑樹插入節點的分析(實現紅黑樹最最最關鍵的一步)

  可以看到我們上面在紅黑樹節點的構造的時候將節點的默認顏色給為紅色,那么我們在插入節點的時候就要特別考慮性質3:不可以有兩個紅色節點連在一起。這里我們可以一共可以分為兩大類,一類將節點插入當前紅黑樹的左子樹中,另一類就是將節點插入紅黑樹的右子樹當中。

  第一大類(將節點插入紅黑樹的左子樹中)

  第一種情況(叔叔節點存在而且為紅色,這里將節點插入紅黑樹的內測還是內測處理方式是一樣的)

  1.我們插入節點的parent節點為黑色:那么這種情況是不需要調整的。

  640 (16).png

  2.我們插入節點的parent節點為紅色,而且插入節點的叔叔節點也存在而且為紅色的,那么當前節點插入之后就違反了紅黑樹的性質3,就需要對當前樹進行調整。這里解決的時候我們就將當前parent節點和叔叔節點u的顏色變為黑色。

  640 (11).png

  為什么要這樣做呢?

  答案:這里我們將cur節點插入之后要解決當前parent和cur顏色都為紅色的問題,那么只能將cur和parnet其中一個節點的顏色變為黑色,但是肯定不能將cur節點變為黑色,因為這樣在包含cur的路徑中就多一個黑色節點,那么我們就要將除包含cur之外的路徑中的黑色節點全部都減少一個,又因為此時cur是新插入的節點如果將cur顏色變為黑色那么此時就只有一條路徑黑色節點個數+1,如果要調整的話,其他所有節點中黑色節點個數都要減少一個這樣肯定是不行的,那么我們只能將parent節點的顏色變為黑色,那么當parent節點變為黑色之后我們可以看到在包含parent的路徑中黑色節點增加,但是包含parent節點的路徑一定包含parent的雙親節點也就是g節點那么我們將雙親節點g顏色改為紅色,那么不就將包含parent路徑的黑色節點個數減少一個了嗎。然后我們發現又出現新的問題了,就是原本包含u節點的路徑因為g節點變為了紅色那么包含u節點的路徑中少了一個黑色節點(因為包含u節點的路徑一定包含g節點)那么我們此時只要將u節點的顏色變為黑色即可。

  上面將parent和u的節點更新為紅色之后,我們還要考慮g節點讓我們更新為紅色之后那它的雙親節點是否存在,是否是紅色節點:

  相關視頻推薦

  5種紅黑樹的場景,從Linux內核談到Nginx源碼,聽完醍醐灌頂

  5種紅黑樹的用途,從應用到內核場景的優缺點

 

  如果g的雙親不存在:

  那么此時g就是根節點那么我們此時需要將g顏色更新為黑色,因為紅黑樹的根節點必須是黑色的。

  640 (7).png

  如果g的雙親存在:

  分為兩種情況:1、g的雙親為黑色那么調整結束直接退出。2、如果g的雙親為紅色(而且g的叔叔為紅色,這里如果g的叔叔為黑色我們下面會討論)那么我們更新cur和parent繼續當前的調整過程。

  640 (9).png

  我們可以總結一下我們的第一種情況:

  640 (13).png

  第二種情況(叔叔節點存在而且一定為黑色或者叔叔節點不存在)

  640 (5).png

  當前cur節點是新插入節點,那么叔叔節點一定是不存在的

  640 (4).png

  當前cur不是新插入節點,那么就和我們第一種情況,我們更新完祖父節點后祖父節點還有叔叔節點的情況這時叔叔節點一定是黑色的,其實下面這種情況的出現就是為了解決上面第一種情況:更新完祖父節點之后祖父節點還有叔叔節點且叔叔節點為黑色。

  640 (19).png

  那么我們如何解決當前場景呢?

  我們這里一共給出三步:

  1.將parent節點改為黑色

  2.將g節點改為紅色

  3.將g節點右單旋

  640.png

  當叔叔節點不存在也是一樣的做法

  640 (8).png

  我們總結一下第二種情況:第二種情況其實就是對第一種情況其中的一種情況的分析解決。

  640 (24).png

  第三種情況:第三種情況其實就是對第二種情況的變種,cur在parent的右側。

  640.jpg

  如果你可以堅持看到這里,恭喜你你已經理解了手撕紅黑樹中基本最難的地方了,馬上就能撕碎紅黑樹!!!

  640 (9).png

  情況三的解決方案:(其實情況三就是轉化為情況二來解決的)

  

  至此我們就將紅黑樹插入的第一大類看完了,接下來就是第二大類基本就和我們的第一大類一樣,不同的地方就是第二大類將節點插入到紅黑樹的右子樹。

  第二大類(將節點插入紅黑樹的右子樹中)

  第一種情況:插入節點的parent節點為紅色而且叔叔節點存在為紅色(這里將節點插入紅黑樹的內測還是內測處理方式是一樣的)

  640 (15).png

  那么我們和第一類中一樣也分為g有雙親節點(g的叔叔為紅色,g的叔叔為黑色兩種情況)和沒有雙親節點。

  g沒有雙親節點:沒有雙親節點我們將g顏色更新為紅色直接返回即可。

  640 (23).png

  g的雙親節點如果存在:那么我們就又分為兩種情況一種是雙親節點為黑色節點那么調整結束滿足紅黑樹性質,另一種雙親節點為紅色那么,就又分為兩種情況:一種是當前叔叔節點為紅色那么我們重復當前的調整步驟,另一種就是我們下面情況二要討論的叔叔節點為黑色。

  640 (10).png

  第二情況:叔叔節點存在但顏色一定是黑色||叔叔節點不存在

  640 (3).png

  如果叔叔節點u為黑色節點當前節點一定不是新插入節點。

  640 (20).png

  那么就是我們遺留的第一種情況中未處理的情況就是下面這種情況:

  640 (1).png

  由于與第一大類中第二種情況類似我們這里直接將解決方式給出,這里的叔叔節點不存在也是同樣的做法

  640 (17).png

  第三種情況:叔叔節點存在但顏色一定是黑色||將節點插入內側

  640 (18).png

  4. 紅黑樹模擬實現

  看到這里恭喜你,你已經徹底掌握了紅黑樹的插入,接下來你可以動手試一下紅黑樹的模擬實現,這里我也給出紅黑樹的模擬實現代碼可以作為參考。

  #pragma once

  #include<iostream>

  #include<vector>

  #include<string>

  using namespace std;

  // 節點的顏色

  //我們可以使用 #define 定義常量,為什么非要使用枚舉? 枚舉的優點:

  //1. 增加代碼的可讀性和可維護性

  //2. 和#define定義的標識符比較枚舉有類型檢查,更加嚴謹。

  //3. 防止了命名污染(封裝)

  //4. 便于調試

  //5. 使用方便,一次可以定義多個常量

  //6. 這些可能取值都是有值的,默認從0開始,一次遞增1,當然在定義的時候也可以賦初值。

  enum Color{ RED, BLACK };

  // 紅黑樹節點的定義

  template<class ValueType>

  struct RBTreeNode

  {

  RBTreeNode(const ValueType& data = ValueType(), Color color = RED)

  //這里構造節點的時候顏色默認給為紅色因為如果給為黑色就有可能會破壞當前紅黑樹的性質,導致每條路徑的黑色節點個數不同

  : _Left(nullptr), _Right(nullptr), _Parent(nullptr)

  , _data(data), _color(color)

  {}

  RBTreeNode<ValueType>* _Left; // 節點的左孩子

  RBTreeNode<ValueType>* _Right; // 節點的右孩子

  RBTreeNode<ValueType>* _Parent; // 節點的雙親(紅黑樹需要旋轉,為了實現簡單給出該字段)

  ValueType _data; // 節點的值域

  Color _color; // 節點的顏色

  };

  //紅黑樹迭代器:

  template<class T, class Ref, class Ptr>

  struct RBTree_iterator

  {

  typedef RBTreeNode<T> Node;

  typedef RBTree_iterator<T, Ref, Ptr> self;

  //構造函數就將紅黑樹的節點指針傳入進來:

  RBTree_iterator(Node* node = nullptr)

  :_pnode(node)

  {}

  //迭代器解引用:

  Ref operator*()

  {

  return _pnode->_data;

  }

  Ptr operator->()

  {

  return (&operator*());

  }

  //迭代器加加:前置加加

  self operator++()

  {

  Increament();

  return *this;

  }

  self operator++(int)

  {

  self temp = *this;

  Increament();

  return temp;

  }

  self operator--()

  {

  Decreament();

  return *this;

  }

  self operator--(int)

  {

  self temp = *this;

  Decreament();

  return temp;

  }

  //將當前迭代器指針的值放到后面大的值上

  void Increament()

  {

  //如果當前迭代器存在右子樹的時候我們將_pnode更新到右子樹

  if (_pnode->_Right)

  {

  _pnode = _pnode->_Right;

  //去右子樹中找最小的節點:

  while (_pnode->_Left)

  {

  _pnode = _pnode->_Left;

  }

  }

  else

  {

  Node* parent = _pnode->_Parent;

  while (parent->_Right == _pnode)

  {

  _pnode = parent;

  parent = _pnode->_Parent;

  }

  ///----------------------------->>>>>>>>>>>一定要注意下面的情況當紅黑樹沒有右子樹,那么當前的head節點的右就指向

  //紅黑樹的根那么此時如果將_pnode放在parent處那么就相當于將while循環中的做了無用功。

  if (_pnode->_Right != parent)

  {

  _pnode = parent;

  }

  }

  }

  void Decreament()

  {

  if (_pnode->_Parent->_Parent == _pnode&&_pnode->_color == RED)

  {//當前節點是head節點的時候那么我們就要找到當最右邊節點也就是最大節點,而判斷當前節點是否是最大的節點的時候

  //不可只有一個_pnode->_Parent->_Parent因為根節點也滿足這個條件,因為我們將紅黑樹的head節點設為紅色所以我們加上_color==RED

  _pnode = _pnode->_Right;

  }

  //如果當前的pnode的左子樹存在那么我們就將節點放在左子樹

  else if (_pnode->_Left)

  {

  _pnode = _pnode->_Left;

  while (_pnode->_Right)

  {

  _pnode = _pnode->_Right;

  }

  }

  else

  {

  Node* parent = _pnode->_Parent;

  //這里如果_pnode到了begin的位置就不可以再減了

  while (_pnode == parent->_Left)

  {

  _pnode = parent;

  parent = _pnode->_Parent;

  }

  _pnode = parent;

  }

  }

  bool operator==(const self &s)const

  {

  return _pnode == s._pnode;

  }

  bool operator!=(const self &s)const

  {

  return _pnode != s._pnode;

  }

  Node* _pnode;

  };

  template<class T,class Keyofvalue>

  class RBtree{

  typedef RBTreeNode<T> Node;

  public:

  typedef RBTree_iterator<T, T&, T*> RBiterator;

  public:

  RBtree()

  :_head(new Node()), _size(0)

  {

  _head->_Left = _head;

  _head->_Right = _head;

  }

  pair<RBiterator,bool> insert(const T &val)//插入節點

  {

  Keyofvalue key;

  //先按照二叉搜索樹的方式插入

  Node* new_node=nullptr;

  Node*& _root = get_root();

  if (_root == nullptr)

  {//為空樹

  _root = new Node(val, RED);

  _root->_Parent = _head;

  new_node = _root;

  //_head->_Parent = _root;

  }

  else

  {//樹非空

  Node* cur = _root;

  Node* parent = _head;

  while (cur)

  {

  parent = cur;

  if (key(val) < key(cur->_data))

  {

  cur = cur->_Left;

  }

  else if (key(val)>key(cur->_data))

  {

  cur = cur->_Right;

  }

  else

  {//我們這里不允許插入相同值域的節點

  return make_pair(RBiterator(cur),false);

  }

  }

  cur = new Node(val);

  new_node = cur;

  if (key(val) < key(parent->_data))

  {

  parent->_Left = cur;

  }

  else

  {

  parent->_Right = cur;

  }

  cur->_Parent = parent;

  //插入成功之后我們調整當前紅黑樹的節點:

  //這里我們在插入紅黑樹中調整的時候只有當第一中情況才繼續向上更新節點,那么我們只要考慮第一中情況的終止條件即可

  //第一中情況中如果parent為紅色節點那么當前節點就需要繼續向上更新,但是我們將head節點也設為紅色那么當我們parent

  //節點更新到head節點那么當前也就不更新了

  while (parent != _head&&parent->_color == RED)

  {

  //插入節點雙親為黑色:

  if (parent->_color == BLACK)

  {

  break;

  }

  else

  {//插入節點雙親為紅色

  Node* grandparent = parent->_Parent;//這里如果雙親的節點是紅色那么雙親一定是有雙親節點的

  if (parent == grandparent->_Left)

  {//第一大類插入節點在紅黑樹的左子樹:

  Node* uncle = grandparent->_Right;//當前節點的叔叔節點

  if (uncle&&uncle->_color == RED)

  {//第一種情況:叔叔節點存在而且為紅色:

  parent->_color = BLACK;

  uncle->_color = BLACK;

  grandparent->_color = RED;

  cur = grandparent;

  parent = cur->_Parent;

  }

  //第二三種情況:

  else

  {

  //因為我們要將第三種情況轉化為第二種情況處理所以我們先寫第三種情況:cur插在內側

  if (cur == parent->_Right)

  {

  rotate_left(parent);

  std::swap(parent, cur);

  }

  //第二種情況:先將parent和grandparent顏色互換然后右旋

  parent->_color = BLACK;

  grandparent->_color = RED;

  rotate_right(grandparent);

  }

  }

  else

  {//第二大類插入節點在紅黑樹的右子樹:

  Node* uncle = grandparent->_Left;//當前節點的叔叔節點

  if (uncle&&uncle->_color == RED)

  {//第一種情況:叔叔節點存在而且為紅色:

  parent->_color = BLACK;

  uncle->_color = BLACK;

  grandparent->_color = RED;

  cur = grandparent;

  parent = cur->_Parent;

  }

  //第二三種情況:

  else

  {

  //因為我們要將第三種情況轉化為第二種情況處理所以我們先寫第三種情況:cur插在內側

  if (cur == parent->_Left)

  {

  rotate_right(parent);

  std::swap(parent, cur);

  }

  //第二種情況:先將parent和grandparent顏色互換然后右旋

  parent->_color = BLACK;

  grandparent->_color = RED;

  rotate_left(grandparent);

  }

  }

  }

  }

  }

  _root->_color = BLACK;

  _head->_Left = get_mostleftnode();

  _head->_Right = get_mostrightnode();

  return make_pair(RBiterator(new_node), true);

  }

  //這里的銷毀節點一定要傳&因為因為下面要修改root=nullptr的時候要將指針所指向的地址修改為nullptr不然如果后面再調用destroy的時候

  //其實root所指向的地址并沒有指向nullptr所以就有可能出錯。

  void Destroy(Node* &root)

  {

  if (root)

  {

  Destroy(root->_Left);

  Destroy(root->_Right);

  delete root;

  root = nullptr;

  }

  }

  void Clear()

  {

  Destroy(get_root());

  _size = 0;

  }

  ~RBtree()

  {

  Destroy(get_root());

  delete _head;

  }

  //查找方法

  RBiterator Find(T value)

  {

  Keyofvalue key;

  Node* cur = get_root();

  while (cur)

  {

  if (key(cur->_data) < key(value))

  {

  cur = cur->_Right;

  }

  else if (key(cur->_data)>key(value))

  {

  cur = cur->_Left;

  }

  else

  {

  return RBiterator(cur);

  }

  }

  return End();

  }

  RBiterator End()

  {

  return RBiterator(_head);

  }

  RBiterator Begin()

  {

  return RBiterator(_head->_Left);

  }

  size_t Size()const

  {

  return _size;

  }

  bool Empty()const

  {

  return _size == 0;

  }

  //中序遍歷//

  void inoder()

  {

  cout << "中序遍歷結果為:";

  Node* _root = get_root();

  mid(_root);

  cout << endl;

  }

  /判斷當前樹是否是紅黑樹//

  bool isRBtree()

  {

  Node* root = get_root();

  if (root == nullptr)

  {

  return true;

  }

  //判斷根節點是否是黑色節點:

  if (root->_color == RED)

  {

  return false;

  }

  //判斷每條路徑中黑色節點個數是否相同

  size_t black_count = 0;

  Node* cur = root;

  while (cur)

  {

  if (cur->_color == BLACK)

  {

  black_count++;

  }

  cur = cur->_Left;

  }

  int k = 0;

  return _isRBtree(black_count, k, root);

  }

  //判斷紅黑樹中是否滿足性質三(兩個紅色節點不挨在一起)性質四(每條路徑中黑色節點樹相同)

  bool _isRBtree(size_t black_count, int k, Node* root)

  {

  if (root == nullptr)

  {

  if (k != black_count)

  {

  cout << "當前樹不是紅黑樹,有一條路徑黑色節點個數為:" << k << "少于路徑節點:" << black_count << endl;

  return false;

  }

  return true;

  }

  if (root->_color == BLACK)

  {

  k++;

  }

  else

  {

  if (root->_Parent->_color == RED)

  {

  cout << "當前樹不是紅黑樹,有兩個紅色節點挨在一起。" << endl;

  return false;

  }

  }

  return _isRBtree(black_count, k, root->_Left) && _isRBtree(black_count, k, root->_Right);

  }

  /

  void Swap(RBtree<T,Keyofvalue> _t)

  {

  std::swap(_head, _t._head);

  }

  private:

  //中序遍歷:

  void mid(Node* root)

  {

  if (root)

  {

  mid(root->_Left);

  cout << root->_data << " ";

  mid(root->_Right);

  }

  }

  //這里因為我們紅黑樹中沒有設置根節點在代碼實現的時候不容易理解所以這里我們寫一個私有函數返回紅黑樹的根節點:

  Node* &get_root()

  {

  return _head->_Parent;

  }

  //獲取最左側節點也就是最小節點:

  Node* get_mostleftnode()

  {

  Node* _root = get_root();

  if (_root)

  {

  while (_root->_Left)

  {

  _root = _root->_Left;

  }

  }

  return _root;

  }

  //獲取最右側節點也就是最大節點:

  Node* get_mostrightnode()

  {

  Node* _root = get_root();

  if (_root)

  {

  while (_root->_Right)

  {

  _root = _root->_Right;

  }

  }

  return _root;

  }

  //左單旋

  void rotate_left(Node* parent)

  {

  Node* pparent = parent->_Parent;

  Node* subR = parent->_Right;

  Node* subRL = subR->_Left;

  parent->_Right = subRL;

  //更新subRL的雙親:

  if (subRL)

  {

  subRL->_Parent = parent;

  }

  subR->_Left = parent;

  parent->_Parent = subR;

  subR->_Parent = pparent;

  if (pparent == _head)//------------------------------------->>>>一定要注意這里的pparent如果是頭節點那么一定要將pparent的指向為subR

  {

  _head->_Parent = subR;

  }

  if (pparent)

  {

  if (pparent->_Left == parent)

  {

  pparent->_Left = subR;

  }

  else

  {

  pparent->_Right = subR;

  }

  }

  }

  //右單旋

  void rotate_right(Node* parent)

  {

  Node* subL = parent->_Left;

  Node* subLR = subL->_Right;

  Node* pparent = parent->_Parent;

  parent->_Left = subLR;

  //如果subLR存在那么將其父節點更新

  if (subLR)

  {

  subLR->_Parent = parent;

  }

  //將parent右旋下來:

  subL->_Right = parent;

  //parent旋下來就要更新parent的父節點

  parent->_Parent = subL;

  //此時subL就要更新父節點

  subL->_Parent = pparent;

  if (pparent == _head)

  {

  _head->_Parent = subL;

  }

  if (pparent)

  {

  if (parent == pparent->_Right)

  {

  pparent->_Right = subL;

  }

  else

  {

  pparent->_Left = subL;

  }

  }

  }

  private:

  size_t _size;

  Node* _head;

  };

  5. 基于紅黑樹的map的模擬實現

  #pragma once

  #include"RBtree.hpp"

  //紅黑樹里面放的鍵值對

  namespace wbx

  {

  template<class K,class V>

  class map

  {

  public:

  typedef pair<K,V> valuetype;

  //這里是因為我們紅黑樹中存放的是鍵值對,而我們紅黑樹在實現的時候只有一個模板類型參數,

  //也就是我們要存放在紅黑樹中的節點,而我們的map是用pair(鍵值對來存放節點的)但是比較

  //的時候我們是通過pair中的key值來比較的,所以我們這里就要定義一個類來返回我們map中要

  //比較的類型。

  struct Keyofvalue

  {

  const K&operator()(const valuetype &value)

  {

  return value.first;

  }

  };

  typedef RBtree<valuetype,Keyofvalue> Tree;

  typedef typename Tree::RBiterator iterator;

  map()

  :_t()

  {}

  iterator begin()

  {

  return _t.Begin();

  }

  iterator end()

  {

  return _t.End();

  }

  size_t size()const

  {

  return _t.Size();

  }

  size_t empty()const

  {

  return _t.Empty();

  }

  //這里map的operator[]我們實現的時候直接用insert來實現,這里我們在紅黑樹中實現insert的時候

  //是不允許插入相同的元素的,所以這里我們operator[]如果是一個新的key值那么我們就將其直接

  //插入了如果是一個原有的key值那么紅黑樹中的inset插入就會將它的迭代器返回那么我們這里將

  //返回的迭代器解引用得到它的value值的引用那么我就可以對其進行修改

  V& operator[](const K& key)

  {

  return (*(_t.insert(make_pair(key, V() ) ).first ) ).second;

  }

  pair<iterator, bool> insert(const valuetype& val)

  {

  return _t.insert(val);

  }

  void swap(map<K, V>& m)

  {

  _t.Swap(m._t);

  }

  void clear()

  {

  _t.Clear();

  }

  iterator find(const K& key )

  {

  return _t.Find(make_pair(key,V()));

  }

  private:

  Tree _t;

  };

  };

  6. 基于紅黑樹的set的模擬實現

  #pragma once

  #include"RBtree.hpp"

  //紅黑樹里面放的鍵值對

  namespace wbx

  {

  template<class K>

  class set

  {

  public:

  typedef K valuetype;

  struct Keyofvalue

  {

  const K&operator()(const valuetype &value)

  {

  return value;

  }

  };

  typedef RBtree<valuetype, Keyofvalue> Tree;

  typedef typename Tree::RBiterator iterator;

  set()

  :_t()

  {}

  iterator begin()

  {

  return _t.Begin();

  }

  iterator end()

  {

  return _t.End();

  }

  size_t size()const

  {

  return _t.Size();

  }

  size_t empty()const

  {

  return _t.Empty();

  }

  pair<iterator, bool> insert(const valuetype& val)

  {

  return _t.insert(val);

  }

  void swap(set<K>& s)

  {

  _t.Swap(s._t);

  }

  void clear()

  {

  _t.Clear();

  }

  iterator find(const valuetype& key)

  {

  return _t.Find(key);

  }

  private:

  Tree _t;

  };

  };

  end

  更多信息可以來這里獲取==>>電子技術應用-AET<<

微信圖片_20210517164139.jpg

微信圖片_20220701092006.jpg

電子技術應用專欄作家  一口linux

原文鏈接:https://mp.weixin.qq.com/s/MGUMK8SQLD7unuIaRegsZQ

本站內容除特別聲明的原創文章之外,轉載內容只為傳遞更多信息,并不代表本網站贊同其觀點。轉載的所有的文章、圖片、音/視頻文件等資料的版權歸版權所有權人所有。本站采用的非本站原創文章及圖片等內容無法一一聯系確認版權者。如涉及作品內容、版權和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當措施,避免給雙方造成不必要的經濟損失。聯系電話:010-82306118;郵箱:aet@chinaaet.com。
主站蜘蛛池模板: 中文字幕乱码亚洲无线三区 | 欧美精品一区二区久久婷婷 | 国产精品久久久久久久久久10秀 | 在线久| 国产99久久久国产精品潘金 | 久久精品女人天堂av免费观看 | 欧美精品与黑人又粗又长 | 精品视频一区二区三区 | 97色伦97色伦国产欧美空 | 永久免费毛片在线播放 | 免费在线看a | 97在线看免费观看视频在线观看 | 欧美伦理一区二区 | 欧美一区二区三区视频 | 久久国产劲爆∧v内射-百度 | 国产成人久久久精品免费澳门 | 亚洲欧美另类在线 | 欧美精品卡一卡二 | 日韩av一卡 | 好吊日免费视频 | 人妻熟女一区二区aⅴ图片 亚洲成a v人片在线观看 | 亚洲网站在线看 | 久久精品视频在线 | 日日碰狠狠躁久久躁2023 | 欧美老妇与zozoz0交 | 国产精品18久久久久白浆 | 欧美内射深插日本少妇 | 欧美一区二区三区不卡视频 | 国产成人无码区免费内射一片色欲 | 国产一区二区三区四区五区 | 天天躁日日躁狠狠躁免费麻豆 | 午夜欧美精品久久久久久久 | 日本国产在线播放 | 射网站| 一区二区视频免费 | 日本免费a级片 | 欧美xxxx做受欧美 | 日本亚洲综合 | 香蕉视频在线精品视频 | 久久人人爽人人爽人人片av免费 | 色欧美色 | 草色噜噜噜av在线观看香蕉 | 超碰成人av | 国产又粗又硬又大爽黄老大爷视 | 99热免费在线 | 国产无吗一区二区三区在线欢 | h肉动漫无码无修6080动漫网 | 成人午夜视频在线 | 欧美大杂乱xxxxxx | 波多野结衣av高清一区二区三区 | 国产精品久久久久久超碰 | 欧美一区二区三区在线视频观看 | 亚洲综合无码一区二区三区 | 少妇色综合 | 亚洲人成77777在线播放网站 | 日韩第一区 | 亚洲最黄视频 | 亚洲欧美日韩精品久久奇米一区 | 日本做爰高潮片免费视频 | 中文字幕日产乱码中文字幕 | 国产成人午夜高潮毛片 | 懂色av噜噜一区二区三区av88 | 波多野结衣三区 | 中文字幕精品av一区二区五区 | 成人精品视频一区二区三区 | 久久成人国产精品 | 精品国产乱子伦 | 7777奇米四色眼影国产馆 | 亚洲国产精品高潮呻吟久久 | 人妻丰满熟妇无码区免费 | 欧美最猛性xxxxx(亚洲精品) | 久久婷五月 | 精品免费久久久 | 日本另类视频 | 99超碰在线观看 | 夜夜艹 | 日日噜噜夜夜狠狠久久av小说 | 老熟妇乱子伦牲交视频 | 日本娇小侵犯hd | 国产午夜一级 | 无码一区二区三区视频 | 成人区人妻精品一区二区三区 | 永久免费观看的毛片手机视频 | 无码人妻少妇伦在线电影 | 国产裸拍裸体视频在线观看 | 老色鬼在线精品视频 | 国产精品12页 | 轻点好疼好大好爽视频 | 青春草在线视频观看 | 一区二区三区精品在线 | 小早川怜子一区二区的导演 | aaa222成人黄网 | 黄色的网站免费看 | 极品无码国模国产在线观看 | 午夜视频在线 | 91理论片 | 日本特黄 | www.com毛片| 精品少妇无码av无码专区 | 午夜免费福利小电影 | 亚洲精品久久区二区三区蜜桃臀 | 国产人成视频在线视频 | 亚洲伊人久久久 | 人妻系列av无码专区 | 国产色视频一区二区三区qq号 | 国产亚洲欧美日韩俺去了 | 欧美激情一区二区三级高清视频 | 国产精品免费久久 | 欧美日韩午夜 | 亚洲最大网 | 六月婷婷久香在线视频 | 日本aa大片 | 91一区二区在线观看 | 黄色网址www | 国 产 黄 色 大 片 | 亚洲区中文字幕 | 自拍偷在线精品自拍偷无码专区 | 青青草这里只有精品 | 欧美日韩一区在线 | 国产精品9999 | 97av.com| 国产成人av一区二区在线观看 | 99精品大学生啪啪自拍 | 国产精品毛片一区二区在线看舒淇 | 男女插插视频 | 国产一区二区三区久久久久久久 | 99久久人妻无码精品系列蜜桃 | 噜噜噜在线观看免费视频日本 | 日本在线不卡一区二区三区 | 酒店大战丝袜高跟鞋人妻 | 欧美另类色 | 500篇短篇超级乱淫的小说 | 日日碰狠狠丁香久燥 | 男人的天堂免费视频 | 国产高清一区二区三区 | 亚洲欧洲无码一区二区三区 | 欧美香蕉在线 | 精品一区久久久 | 久久国产色av | 欧美成人三级在线视频 | 国产高清视频 | 成人免费毛片内射美女-百度 | 久久99精品国产99久久6尤物 | 美女一区二区三区视频 | 国产cao| 亚洲在线观看视频 | 天码av无码一区二区三区四区 | 国产精品av99 | 伊人永久 | 日韩精品久久久肉伦网站 | 拔擦拔擦8x海外华人永久 | 国产精品一品二区三区四区18 | 少妇系列av | 狂野欧美性猛交xxxxx视频 | 国产成年免费视频 | 欧美 偷窥 清纯 综合图区 | 久久婷婷五月综合色国产香蕉 | 成年人视频网 | 五月天婷婷激情网 | 99福利在线观看 | 国产乱人伦av在线a麻豆 | 日本国产一区二区 | 丰满圆润老女人hd | 成 人 黄 色视频免费播放 | 中文字幕亚洲中文字幕无码码 | 大咪咪dvd | 调教女少妇二区三区视频 | 国产精品久久久久久久久免费桃花 | 亚洲国产成人va在线观看天堂 | 自拍偷自拍亚洲精品10p | 国产亚洲第一页 | 在线精品亚洲一区二区佐佐木明希 | 日韩亚洲欧美中文高清在线 | wwwxxx麻豆| 男人靠女人免费视频网站 | 欧美乱妇日本无乱码特黄大片 | 天天射天天干天天 | 国产亚洲系列 | 日韩精品一区二区三区免费视频观看 | 麻豆网站免费观看 | 日韩在线观看精品 | 精品国产sm最大网站 | 成人影片在线 | 亚洲日本黄色 | 中国女人内谢69xxxxⅹ视频 | 国产毛片久久久久久美女视频 | 日韩激情在线视频 | 国产女人18毛片水18精品 | 成人拍拍 | 无码骚夜夜精品 | 久久久久久久久久久免费精品 | 野花社区www高清视频 | 中日韩文字幕无线网站2013 | 日本美女一级视频 | 少妇人妻真实偷人精品视频 | 91亚色 | 一个添下面两个吃奶把腿扒开 | 亚洲国产精品午夜久久久 | 色视频在线观看 | 亚洲欧洲色图 | 四虎精品在线观看 | 丝袜 亚洲 另类 欧美 变态 | 黄色av播放 | 亚洲精品国产综合久久久久紧 | 成人毛片100部免费看 | 性视频一区 | 精二青青河边草解释正确的是 | 日本伊人精品一区二区三区 | 51福利视频 | 色呦呦视频 | 妺妺窝人体色www在线观看 | 深夜视频免费在线观看 | 成年视频在线 | 狠狠狠色| 91亚洲精品久久久蜜桃网站 | 五月网| 国产porn | 天天爽夜夜爽国产精品视频 | 日韩精品1| 中国女人内谢69xxxxxa片 | 亚洲国产欧美在线观看 | 天干天干啦夜天干天2017 | 成人av在线影视 | 色婷婷免费视频 | 国产又粗又硬又大爽黄老大爷视频 | 天堂在线免费观看视频 | avtt中文字幕 | 一本精品中文字幕在线 | 日本又色又爽又黄的a片吻戏 | 97精品超碰一区二区三区 | 亚洲视频一二三 | 日韩精品无码一区二区三区av | 寡妇高潮一级片 | 天海翼一区 | 99精品久久毛片a片 在线亚洲高清揄拍自拍一品区 | 嫩草一区二区 | www.少妇影院.com| 国产成人av一区二区三区不卡 | 国产女 | 日韩欧美一区二区三区四区五区 | 无码av最新无码av专区 | 美女视频黄免费看 | 影音先锋国产 | 日韩高清片 | 国产精品久久久久久久久久东京 | 国产欧美另类精品久久久 | 免费不卡的av | 国产精品对白刺激蜜臀av | 激情网婷婷 | 欧美成人家庭影院 | 91丨九色丨91啦蝌蚪老版 | 国产熟人av一二三区 | 亚洲自拍三区 | 特大黑人巨交性xxxx | 亚洲一区二区三区在线观看网站 | 亚洲自偷自拍熟女另类 | 亚洲色大成网站www久久九九 | 午夜av网址 | 伊人91在线| 午夜免费国产体验区免费的 | 国产精品无码一区二区三区不卡 | 亚洲精品国产自在久久 | 亚洲午夜一区二区三区 | 国产一区二区三区在线观看视频 | 成人性生交大片 | 成人午夜视频在线免费观看 | 久久99精品久久久久久按摩秒播 | 91视频www| 日韩一区二区三区久久 | 欧美精品久久天天躁 | 国产一区二区三区精品在线观看 | 久久a级片 | 97理伦| h片在线观看视频 | 在哪里可以看毛片 | 国产网站免费看 | 日本激情视频一区二区三区 | 亚洲精品精华液一区 | 97精品国产| 色一情一乱 | 国产综合久久久久 | 黄色精品一区二区 | 欧美日韩亚洲视频 | 久久aaaa片一区二区 | 亚洲欧美在线免费 | 欧美激情综合五月色丁香 | 国产精品久久777777 | 日韩av手机在线观看 | 国产精品亚洲视频 | 久久久久女人精品毛片九一 | 国产真实乱对白精彩久久小说 | 看全色黄大色黄大片 视频 欧美深度肠交惨叫 | 成人情侣激情偷拍视频 | 日韩高清中文字幕 | 国产传媒毛片精品视频第一次 | 无码高潮少妇毛多水多水 | 狠狠色狠狠色88综合日日91 | 午夜香蕉网 | 日韩av综合 | 午夜大片男女免费观看爽爽爽尤物 | 亚洲男人第一av网站 | 91精品久久久久久久久久 | a天堂资源在线 | 伊人自拍 | 亚洲色成人网一二三区 | 国精产品一区一区三区有限在线 | 妺妺窝人体色www看美女 | 亚洲欧美日韩中文高清www777 | 18岁日韩内射颜射午夜久久成人 | 野草社区在线观看 | 亚洲天堂社区 | 欧美另类z0z变态 | 亚洲精品久久午夜无码一区二区 | 无遮挡很爽很污很黄的网站 | 欧美乱轮视频 | 特级淫片裸体免费看 | 精品国产免费久久久久久桃子图片 | 午夜窝窝| 女人被男人爽到呻吟的视频 | 国产免费视频在线 | 狠狠色噜噜狠狠狠888米奇视频 | 爱情岛论坛av | 亚洲精品久久久久久一区二区 | 日韩成年视频 | 乱人伦中文无码视频在线观看 | 日韩成人av网址 | 国产成人精品网站 | 日韩裸体做爰xxxⅹ 日韩麻豆 | 国产丝袜美女一区二区三区 | 丁香五月欧美成人 | 国语啪啪 | 快色污| 亚欧中文字幕 | 欧美国产日韩久久 | 精品久久久久久中文字幕2017 | 亚洲国产天堂一区二区三区 | 精品国产免费一区二区三区五区 | 一区二区视频在线观看免费 | 亚洲色图欧美视频 | 在线免费观看黄网站 | 老司机午夜在线 | 中文字幕丰满孑伦无码专区 | 亚洲xxxx做受欧美 | 亚洲欧美综合精品另类天天更新 | www黄色| 久久少妇网 | www.亚洲视频.com| 成人毛片一区二区 | 午夜精品三级久久久有码 | 久草在线视频网 | 国产精品美女久久久久av超清 | 亚洲精品入口 | 亚洲www | 日韩激情成人 | 日本一区二区在线视频 | 手机看片国产 | 在线免费色视频 | 国产精品一区二区久久久久 | 久久久久久久久久久影院 | 又粗又硬的毛片aaaaa片 | 肉版如懿传高h | 天天看夜夜操 | 国产精品亚洲综合 | 欧美另类老妇 | 日本美女极度性诱惑卡不卡 | 国产原创一区二区 | 狠狠躁天天躁无码中文字幕 | 国产成人精品无码片区在线观看 | 国产精品久久国产三级国不卡顿 | 国产精品久久久久久福利 | 青青草久草在线 | 国产高潮久久 | 99这里| 国产98在线 | 欧美 | 久久精品国产精品亚洲38 | 免费av免费观看 | 欧洲精品码一区二区三区免费看 | 国产内射爽爽大片视频社区在线 | 天天摸天天透天天添 | 97超碰超碰| 人体内射精一区二区三区 | 7799国产精品久久99 | 日批在线观看 | 小明天天看 | 嫩模写真一区二区三区三州 | 精品国产乱码久久久久久蜜臀 | 中文字幕av亚洲精品一部二部 | 国产精品视频在线观看 | 久久精品九九 | 国产精品高清网站 | 禁断一区二区三区在线 | 国产精品区一区二区三在线播放 | 国产剧情av引诱维修工 | 色婷婷综合久久中文字幕雪峰 | 真实的国产乱ⅹxxx66小说 | 日韩欧美国产网站 | 免费美女视频网站 | 久久综合成人 | 欧美又粗大人妖一进一出 | 怡红院av人人爰人人爽 | 99青草| 欧美精品高清在线观看 | 一本在线免费视频 | av影片在线| 国产精品夜夜 | 成人激情开心 | 91精品无人区麻豆乱码1区2区介绍 | 欧美成人三级在线视频 | 无码日韩精品一区二区免费 | 久久久国产精品消防器材 | 成人黄色激情视频 | 国产成人免费9x9x | 国产日产久久久久久 | 天天爽天天爽天天爽 | 天堂在线中文资源 | 天天看片夜夜爽 | 黄色精品一区 | 亚洲视频中文字幕在线观看 | 美女屁股眼视频网站 | 中文字幕无码不卡一区二区三区 | 国产成人福利 | 亚洲精品国产一区二区精华液 | 日韩欧美在线综合网另类 | 亚洲浮力影院久久久久久 | 亚洲日本香蕉视频 | 亚洲综合网在线观看 | 97精品在线 | 久99| 在线欧美精品一区二区三区 | 超碰在线播放97 | 国精产品一区一区三区有限公司 | 国产精品yy| 欧美日韩免费 | 中文日韩亚洲欧美字幕 | 性色av一区二区咪爱 | 成人欧美一区二区三区在线 | 综合久久久久久久久 | 日产欧美一区二区三区不上 | 久久av无码精品人妻系列 | 国产视频第三页 | 国产精品久久久久久超碰 | 国产一区二区片 | 亚洲精品乱码久久久久久蜜桃不卡 | 久久久久久一级片 | 四虎成人精品永久免费av | 这里只有精品在线观看 | 日本一区二区三区在线视频 | 亚洲一区二区三区成人 | 国产真人做爰毛片视频直播 | 先锋av在线资源 | 成片免费观看视频大全 | 99re免费视频| 国产伦精品一区二区三区免费迷 | 天堂免费av| 天天弄 | 亚洲成人伊人 | 久操视频免费在线观看 | 日日爱669| 欧美国产综合欧美视频 | 成人热舞视频一区 | 偷拍亚洲视频 | 激情另类小说 | 成人免费视频一区二区 | 亚洲性视频在线 | 国产精品无码一区二区在线观一 | 97精品| 性色综合| 国产无遮挡又黄又爽对白视频 | 2023av在线 | 日日操夜夜骑 | 午夜资源网 | 亚洲午夜小视频 | 免费a级片在线观看 | 特级毛片aaa | 视频一区二区欧美 | www.蜜臀| 欧亚日韩精品一区二区在线 | 亚欧成a人无码精品va片 | 国产又粗又黄视频 | 成人做爰69片免费看网站野花 | 春色校园综合人妻av | 日本三级做爰在线播放 | 亚洲免费区 | 男人的天堂中文字幕 | 亚色在线视频 | 黄色天堂网 | 欧美日韩免费一区二区三区 | 天堂网www中文在线 伊人久久大香线蕉综合网站 | 老熟仑妇乱一区二区 | 91精品综合久久久久久五月天 | 欧美3p视频 | 99re6热在线精品视频播放 | 91精品国产91综合久久蜜臀 | 大陆性猛交xxxx乱大交 | 国产黄a三级三级三级看三级黑人 | 日本成人在线网站 | 亚洲色婷婷久久精品av蜜桃 | 亚洲色成人一区二区三区小说 | 国产精品白浆一区二小说 | 欧美一二三区在线观看 | 女女同性女同一区二区三区九色 | 玖玖精品视频 | 国精品人妻无码一区二区三区蜜柚 | 国产一区视频在线观看免费 | 免费一级欧美片在线播放 | 欧美日韩精品一区二区在线视频 | 99热热| 韩国三级a视频在线观看 | 六月丁香婷婷综合 | av在线亚洲男人的天堂 | 国产欧美久久一区二区三区 | 81av在线 | 麻豆精品久久久 | 久久99精品国产麻豆宅宅 | 天天在线综合 | 古装做爰无遮挡三级聊斋艳谭 | av自拍偷拍 | 免费人成在线观看网站 | 色视频在线观看视频 | 久久婷婷色 | 天天摸天天爽 | 成人高清网站 | 成年人天堂 | 影音先锋中文字幕在线视频 | 亚洲黄网在线 | 日韩中文字幕精品视频 | 国产精品99久久免费黑人人妻 | 亚洲黄色免费看 | 98国产精品综合一区二区三区 | 欧美视频在线一区二区三区 | 国产一线二线三线在线观看 | 婷婷综合社区 | 窝窝午夜精品一区二区 | 天堂av2021| 一边捏奶头一边高潮视频 | 国产女人高潮视频在线观看 | 依人在线观看 | 国产欧美wwwxj在线观看 | 日韩不卡高清 | 亚洲国产精品一区二区成人片国内 | 两个人看的vvv在线高清 | 色a在线| 久久久久久欧美 | 日本打白嫩屁股视频 | 国产稀缺真实呦乱在线 | 国产成人愉拍精品久久 | 国产精品自拍av | 国产精品久久久久久久久久妞妞 | 国产精品天干天干 | 国产三级日本三级在线播放 | 欧美永久视频 | 外国av网站| 亚洲熟妇色xxxxx亚洲 | 久久国产精品免费一区二区三区 | 欧美国产日韩视频 | 国产精品无码专区在线观看 | 久久福利在线 | 亚洲另类欧美综合久久图片区 | a级毛片蜜桃成熟时2在线播放 | 色撸撸在线观看 | 天天久久| 99久久久无码国产精品免费 | 伊人久久精品视频 | 波多野结衣av高清一区二区三区 | 亚洲精品日日夜夜 | 午夜夜伦鲁鲁片六度影院 | 91精品国产色综合久久不卡粉嫩 | 日韩资源在线 | 国产电影一区二区三区 | 日本三级三级三级三级 | 久久伊人色av天堂九九小黄鸭 | 日韩av午夜在线观看 | 国产女人第一次做爰毛片 | 草草视频网站 | 欧美成人自拍视频 | 91av一区| 久久亚洲国产精品五月天婷 | 天天躁日日躁狠狠躁欧美老妇小说 | 亚洲色图国产精品 | 久久免费播放 | 一色屋精品久久久久久久久久 | 久草一区| 国产麻豆成人传媒免费观看 | 久久亚洲私人国产精品va | 一级特黄少妇高清毛片 | 国产精品美女一区二区视频 | 小视频成人 | 中文字幕在线观看不卡 | 国产十区| 丰满少妇在线观看网站 | 操操网| 午夜鲁鲁 | 我要色综合天天 | 九九九九九九精品 | 成人精品网 | 欧美人狂配大交3d怪物一区 | 成人在线国产 | 超h高h肉h文教室学长男男视频 | 日韩欧美高清在线观看 | 久久69精品久久久久久国产越南 | 中文字幕丝袜一区二区 | 美日韩一区二区三区 | 成人欧美在线观看 | 国内视频一区二区三区 | 亚洲欧美日韩精品久久亚洲区 | 国产精品久久久久久久 | 老牛影视免费一区二区 | 欧美透逼视频 | 亚洲精品无码永久在线观看你懂的 | 久久夜色精品国产噜噜av | 久久久久久国产精品免费免费 | 精品久久久久久无码中文野结衣 | 干一干操一操 | 91视频亚洲 | 伊人情人色综合网站 |