• 【c++】搜索二叉树的模拟实现


    搜索二叉树的模拟实现

    k模型完整代码

    1. #pragma once
    2. namespace hqj1
    3. {
    4.  template<class K>
    5.  struct SBTreeNode
    6.  {
    7.  public:
    8.   //这里直接用匿名对象作为缺省参数
    9.   SBTreeNode(const K& key = K())
    10.    :_key(key)
    11.    , _cleft(nullptr)
    12.    , _cright(nullptr)
    13.   {}
    14.  public:
    15.   K _key;
    16.   SBTreeNode* _cleft;
    17.   SBTreeNode* _cright;
    18.  };
    19.  template<class K>
    20.  class SBTree
    21.  {
    22.   typedef SBTreeNode<K> Node;
    23.  public:
    24.   SBTree()
    25.    :_root(nullptr)
    26.   {}
    27.   bool Insert(const K& key)
    28.   {
    29.    if (_root == nullptr)
    30.     _root = new Node(key);
    31.    else
    32.    {
    33.     Node* cur = _root;
    34.     Node* parent = nullptr;
    35.     //找到要插入的位置
    36.     while (cur)
    37.     {
    38.      parent = cur;
    39.      if (cur->_key < key)
    40.       cur = cur->_cright;
    41.      else if (cur->_key > key)
    42.       cur = cur->_cleft;
    43.      else
    44.       return false;
    45.     }
    46.     //连接
    47.     cur = new Node(key);
    48.     if (parent->_key < key)
    49.      parent->_cright = cur;
    50.     else
    51.      parent->_cleft = cur;
    52.    }
    53.    return true;
    54.   }
    55.   Node* Find(const K& key)
    56.   {
    57.    Node* cur = _root;
    58.    while (cur)
    59.    {
    60.     if (key > cur->_key)
    61.      cur = cur->_cright;
    62.     else if (key < cur->_key)
    63.      cur = cur->_cleft;
    64.     else
    65.      break;
    66.    }
    67.    return cur;
    68.   }
    69.   bool Erase(const K& key)
    70.   {
    71.    if (_root == nullptr)
    72.     return false;
    73.    else
    74.    {
    75.     //找出要删除元素的位置,复用查找函数也行
    76.     Node* cur = _root;
    77.     Node* parent = nullptr;
    78.     while (cur)
    79.     {
    80.      if (cur->_key == key)
    81.       break;
    82.      parent = cur;
    83.      if (key > cur->_key)
    84.       cur = cur->_cright;
    85.      else if (key < cur->_key)
    86.       cur = cur->_cleft;
    87.     }
    88.     //对根进行特判
    89.     if (parent == nullptr)
    90.     {
    91.      if (cur->_cleft == nullptr && cur->_cright == nullptr)
    92.      {
    93.       delete _root;
    94.       _root = nullptr;
    95.      }
    96.      else if (cur->_cleft == nullptr)
    97.       _root = _root->_cright;
    98.      else
    99.       _root = _root->_cleft;
    100.      return true;
    101.     }
    102.     //对不同情况进行处理
    103.     //第一种是要删除的元素不在树内
    104.     if (cur == nullptr)
    105.      return false;
    106.     else if (cur->_cleft == nullptr && cur->_cleft == cur->_cright)
    107.     {
    108.      //要删除的元素是叶子节点,直接删
    109.      if (cur == parent->_cleft)
    110.       parent->_cleft = nullptr;
    111.      else
    112.       parent->_cright = nullptr;
    113.      delete cur;
    114.     }
    115.     else if (cur->_cleft == nullptr)
    116.     {
    117.      //有右子树但没有左子树
    118.      if (cur == parent->_cleft)
    119.       parent->_cleft = cur->_cright;
    120.      else
    121.       parent->_cright = cur->_cright;
    122.      delete cur;
    123.     }
    124.     else if (cur->_cright == nullptr)
    125.     {
    126.      //有左子树但没有右子树
    127.      if (cur == parent->_cleft)
    128.      {
    129.       parent->_cleft = cur->_cleft;
    130.      }
    131.      else
    132.      {
    133.       parent->_cright = cur->_cleft;
    134.      }
    135.      delete cur;
    136.     }
    137.     else
    138.     {
    139.      //既有左子树又有右子树
    140.      //找左子树的最右,或者找右子树的最左节点来替换掉当前要删除的节点
    141.      Node* curRL = cur->_cright;
    142.      Node* parentRL = cur;
    143.      while (curRL->_cleft)
    144.      {
    145.       parentRL = curRL;
    146.       curRL = curRL->_cleft;
    147.      }
    148.      //交换要删除的值和要删除节点的右树最左节点的值
    149.      swap(cur->_key, curRL->_key);
    150.      //判断要删除的节点在其父节点的位置
    151.      //操控父节点指针
    152.      //有一个性质:右子树中的最左节点一定没有左子树,我们让父节点连接要删除节点的右子树就行
    153.      if (curRL == parentRL->_cleft)
    154.       parentRL->_cleft = curRL->_cright;
    155.      else
    156.       parentRL->_cright = curRL->_cright;
    157.      delete curRL;
    158.      curRL = nullptr;
    159.     }
    160.     return true;
    161.    }
    162.   }
    163.   void InOrder()
    164.   {
    165.    _InOrder(_root);
    166.   }
    167.  private:
    168.   void _InOrder(const Node* root)
    169.   {
    170.    if (root == nullptr)
    171.     return;
    172.    _InOrder(root->_cleft);
    173.    cout << root->_key << ' ';
    174.    _InOrder(root->_cright);
    175.   }
    176.   Node* _root;
    177.  };
    178. }

    k模型节点的定义

    • 这是一个模板类,模板类型为K,代表着关键词

    • 成员为:关键词、左子树指针、右子树指针

    • 构造函数的参数为K类型的对象,缺省参数为匿名对象(K()),使我们代码的通用性增强

    1. template<class K>
    2.  struct SBTreeNode
    3.  {
    4.  public:
    5.   //这里直接用匿名对象作为缺省参数
    6.   SBTreeNode(const K& key = K())
    7.    :_key(key)
    8.    , _cleft(nullptr)
    9.    , _cright(nullptr)
    10.   {}
    11.  public:
    12.   K _key;
    13.   SBTreeNode* _cleft;
    14.   SBTreeNode* _cright;
    15.  };

    k模型二叉搜索树类的实现

    • 首先将节点类类型重定义为Node方便我们后续的使用

    • 成员函数为插入、删除、查找、中序遍历

    • 私有成员为节点指针_root

    1. template<class K>
    2.  class SBTree
    3.  {
    4.   typedef SBTreeNode<K> Node;
    5.  public:
    6.   SBTree()
    7.    :_root(nullptr)
    8.   {}
    9.   bool Insert(const K& key)
    10.   {
    11.    if (_root == nullptr)
    12.     _root = new Node(key);
    13.    else
    14.    {
    15.     Node* cur = _root;
    16.     Node* parent = nullptr;
    17.     //找到要插入的位置
    18.     while (cur)
    19.     {
    20.      parent = cur;
    21.      if (cur->_key < key)
    22.       cur = cur->_cright;
    23.      else if (cur->_key > key)
    24.       cur = cur->_cleft;
    25.      else
    26.       return false;
    27.     }
    28.     //连接
    29.     cur = new Node(key);
    30.     if (parent->_key < key)
    31.      parent->_cright = cur;
    32.     else
    33.      parent->_cleft = cur;
    34.    }
    35.    return true;
    36.   }
    37.   Node* Find(const K& key)
    38.   {
    39.    Node* cur = _root;
    40.    while (cur)
    41.    {
    42.     if (key > cur->_key)
    43.      cur = cur->_cright;
    44.     else if (key < cur->_key)
    45.      cur = cur->_cleft;
    46.     else
    47.      break;
    48.    }
    49.    return cur;
    50.   }
    51.   bool Erase(const K& key)
    52.   {
    53.    if (_root == nullptr)
    54.     return false;
    55.    else
    56.    {
    57.     //找出要删除元素的位置,复用查找函数也行
    58.     Node* cur = _root;
    59.     Node* parent = nullptr;
    60.     while (cur)
    61.     {
    62.      if (cur->_key == key)
    63.       break;
    64.      parent = cur;
    65.      if (key > cur->_key)
    66.       cur = cur->_cright;
    67.      else if (key < cur->_key)
    68.       cur = cur->_cleft;
    69.     }
    70.     //对根进行特判
    71.     if (parent == nullptr)
    72.     {
    73.      if (cur->_cleft == nullptr && cur->_cright == nullptr)
    74.      {
    75.       delete _root;
    76.       _root = nullptr;
    77.      }
    78.      else if (cur->_cleft == nullptr)
    79.       _root = _root->_cright;
    80.      else
    81.       _root = _root->_cleft;
    82.      return true;
    83.     }
    84.     //对不同情况进行处理
    85.     //第一种是要删除的元素不在树内
    86.     if (cur == nullptr)
    87.      return false;
    88.     else if (cur->_cleft == nullptr && cur->_cleft == cur->_cright)
    89.     {
    90.      //要删除的元素是叶子节点,直接删
    91.      if (cur == parent->_cleft)
    92.       parent->_cleft = nullptr;
    93.      else
    94.       parent->_cright = nullptr;
    95.      delete cur;
    96.     }
    97.     else if (cur->_cleft == nullptr)
    98.     {
    99.      //有右子树但没有左子树
    100.      if (cur == parent->_cleft)
    101.       parent->_cleft = cur->_cright;
    102.      else
    103.       parent->_cright = cur->_cright;
    104.      delete cur;
    105.     }
    106.     else if (cur->_cright == nullptr)
    107.     {
    108.      //有左子树但没有右子树
    109.      if (cur == parent->_cleft)
    110.      {
    111.       parent->_cleft = cur->_cleft;
    112.      }
    113.      else
    114.      {
    115.       parent->_cright = cur->_cleft;
    116.      }
    117.      delete cur;
    118.     }
    119.     else
    120.     {
    121.      //既有左子树又有右子树
    122.      //找左子树的最右,或者找右子树的最左节点来替换掉当前要删除的节点
    123.      Node* curRL = cur->_cright;
    124.      Node* parentRL = cur;
    125.      while (curRL->_cleft)
    126.      {
    127.       parentRL = curRL;
    128.       curRL = curRL->_cleft;
    129.      }
    130.      //交换要删除的值和要删除节点的右树最左节点的值
    131.      swap(cur->_key, curRL->_key);
    132.      //判断要删除的节点在其父节点的位置
    133.      //操控父节点指针
    134.      //有一个性质:右子树中的最左节点一定没有左子树,我们让父节点连接要删除节点的右子树就行
    135.      if (curRL == parentRL->_cleft)
    136.       parentRL->_cleft = curRL->_cright;
    137.      else
    138.       parentRL->_cright = curRL->_cright;
    139.      delete curRL;
    140.      curRL = nullptr;
    141.     }
    142.     return true;
    143.    }
    144.   }
    145.   void InOrder()
    146.   {
    147.    _InOrder(_root);
    148.   }
    149.  private:
    150.   void _InOrder(const Node* root)
    151.   {
    152.    if (root == nullptr)
    153.     return;
    154.    _InOrder(root->_cleft);
    155.    cout << root->_key << ' ';
    156.    _InOrder(root->_cright);
    157.   }
    158.   Node* _root;
    159.  };

    构造函数

    • 将_root指针初始化为空指针即可

    1. SBTree()
    2.    :_root(nullptr)
    3.   {}

    Insert函数

    • Insert函数的参数为要插入的关键字

    • 首先进行判空,如果_root为空,说明此时还没有节点,我们直接给_root赋值就行

    • 如果不为空,那么就需要先找到要插入的位置,我们定义cur和parent两个节点指针,cur负责寻找要插入的位置,parent负责记录cur的父亲节点,由于搜索二叉树的特性,当key值大于cur所指向节点的_key值说明要插入的位置再cur节点的右子树中,反之则在cur的左子树中,通过循环来达到目的,更新cur的同时要更新parent

    • 如果遇到cur的_key和key相等的情况说明插入失败,其余情况皆为插入成功

    1. bool Insert(const K& key)
    2.   {
    3.    if (_root == nullptr)
    4.     _root = new Node(key);
    5.    else
    6.    {
    7.     Node* cur = _root;
    8.     Node* parent = nullptr;
    9.     //找到要插入的位置
    10.     while (cur)
    11.     {
    12.      if (cur->_key == key)
    13.       return false;
    14.      parent = cur;
    15.      if (cur->_key < key)
    16.       cur = cur->_cright;
    17.      else if (cur->_key > key)
    18.       cur = cur->_cleft;
    19.     }
    20.     //连接
    21.     cur = new Node(key);
    22.     if (parent->_key < key)
    23.      parent->_cright = cur;
    24.     else
    25.      parent->_cleft = cur;
    26.    }
    27.    return true;
    28.   }

    Find函数

    • Find的参数为要查找的关键字

    • 我们定义cur指针来找到目标节点位置,当key > cur->_key时cur要往其右子树寻找,反之则去其左子树寻找,当相等时或者cur指向空(意味着没找到)结束循环,返回cur

    1.   Node* Find(const K& key)
    2.   {
    3.    Node* cur = _root;
    4.    while (cur)
    5.    {
    6.     if (key > cur->_key)
    7.      cur = cur->_cright;
    8.     else if (key < cur->_key)
    9.      cur = cur->_cleft;
    10.     else
    11.      break;
    12.    }
    13.    return cur;
    14.   }

    Erase函数

    • 该函数的参数为要删除的关键字

    • 当要操作的树为空树时,直接返回失败

    • 不是空树则首先找出要删除节点的位置,同样是定义cur和parent节点指针,cur负责找出要删除节点的位置,parent负责记录cur节点的父节点。利用循环结构实现,循环的结束条件为cur为空指针或者找到对应位置,若为空则说明要删除节点不在树内,直接返回失败

    • 找到之后首先判断是否要操作_root指针,当parent为空时说明要操作根节点,对于根节点的不同类型进行对应的操作1. 如果整棵树只有一个节点,直接删除根节点,并将根节点置为空。2. 如果根节点没有左子树,则用右子树的根节点作为新的整棵树的根节点。3. 如果根节点没有右子树,则用左子树的根节点作为新的整棵树的根节点。4. 如果根节点既有左子树又有右子树,则当作普通节点处理(见下一点的第4小点)

    • 处理完根节点问题后就改判断要删除的节点是哪种类型:1. 删除节点是叶子结点,那么我们直接删除该节点并更新其父亲节点的指针(判断要删除节点是其父情节点的左子树还是右子树,操作对应的指针)2. 有右子树但没有左子树,让其父亲的对应指针指向其右子树,并删除当前节点。3. 有左子树但没有右子树,让其父亲的对应指针指向其左子树,并删除该节点4. 既有左子树又有右子树,定义curRL负责寻找其右子树的最左节点(也就是右子树的最小节点)或者定义curLR左子树的最右节点(也就是左子树的最大节点),定义parentRL记录其父亲节点,与当前节点(cur)的值进行交换,交换完后令parentRL的对应指针指向curRL的右子树,并删除curRL所指向的节点。

    • 所有过程走完后返回状态(成功或者失败)

    1. bool Erase(const K& key)
    2.   {
    3.    if (_root == nullptr)
    4.     return false;
    5.    else
    6.    {
    7.     //找出要删除元素的位置,复用查找函数也行
    8.     Node* cur = _root;
    9.     Node* parent = nullptr;
    10.     while (cur)
    11.     {
    12.      if (cur->_key == key)
    13.       break;
    14.      parent = cur;
    15.      if (key > cur->_key)
    16.       cur = cur->_cright;
    17.      else if (key < cur->_key)
    18.       cur = cur->_cleft;
    19.     }
    20.     //对根进行特判
    21.     if (parent == nullptr)
    22.     {
    23.      if (cur->_cleft == nullptr && cur->_cright == nullptr)
    24.      {
    25.       delete _root;
    26.       _root = nullptr;
    27.      }
    28.      else if (cur->_cleft == nullptr)
    29.       _root = _root->_cright;
    30.      else
    31.       _root = _root->_cleft;
    32.      return true;
    33.     }
    34.     //对不同情况进行处理
    35.     //第一种是要删除的元素不在树内
    36.     if (cur == nullptr)
    37.      return false;
    38.     else if (cur->_cleft == nullptr && cur->_cleft == cur->_cright)
    39.     {
    40.      //要删除的元素是叶子节点,直接删
    41.      if (cur == parent->_cleft)
    42.       parent->_cleft = nullptr;
    43.      else
    44.       parent->_cright = nullptr;
    45.      delete cur;
    46.     }
    47.     else if (cur->_cleft == nullptr)
    48.     {
    49.      //有右子树但没有左子树
    50.      if (cur == parent->_cleft)
    51.       parent->_cleft = cur->_cright;
    52.      else
    53.       parent->_cright = cur->_cright;
    54.      delete cur;
    55.     }
    56.     else if (cur->_cright == nullptr)
    57.     {
    58.      //有左子树但没有右子树
    59.      if (cur == parent->_cleft)
    60.      {
    61.       parent->_cleft = cur->_cleft;
    62.      }
    63.      else
    64.      {
    65.       parent->_cright = cur->_cleft;
    66.      }
    67.      delete cur;
    68.     }
    69.     else
    70.     {
    71.      //既有左子树又有右子树
    72.      //找左子树的最右,或者找右子树的最左节点来替换掉当前要删除的节点
    73.      Node* curRL = cur->_cright;
    74.      Node* parentRL = cur;
    75.      while (curRL->_cleft)
    76.      {
    77.       parentRL = curRL;
    78.       curRL = curRL->_cleft;
    79.      }
    80.      //交换要删除的值和要删除节点的右树最左节点的值
    81.      swap(cur->_key, curRL->_key);
    82.      //判断要删除的节点在其父节点的位置
    83.      //操控父节点指针
    84.      //有一个性质:右子树中的最左节点一定没有左子树,我们让父节点连接要删除节点的右子树就行
    85.      if (curRL == parentRL->_cleft)
    86.       parentRL->_cleft = curRL->_cright;
    87.      else
    88.       parentRL->_cright = curRL->_cright;
    89.      delete curRL;
    90.      curRL = nullptr;
    91.     }
    92.     return true;
    93.    }
    94.   }

    kv模型完整代码

    1. #pragma once
    2. namespace hqj2
    3. {
    4.  template<class K, class V>
    5.  struct SBTreeNode
    6.  {
    7.  public:
    8.   SBTreeNode(const K& key = K(), const V& value = V())
    9.    :_cleft(nullptr), _cright(nullptr)
    10.    , _key(key)
    11.    , _value(value)
    12.   {}
    13.  public:
    14.   SBTreeNode* _cleft;
    15.   SBTreeNode* _cright;
    16.   K _key;
    17.   V _value;
    18.  };
    19.  template<class K, class V>
    20.  class SBTree
    21.  {
    22.   typedef SBTreeNode<K, V> Node;
    23.  public:
    24.   SBTree()
    25.    :_root(nullptr)
    26.   {}
    27.  public:
    28.   bool Insert(const K& key, const V& value)
    29.   {
    30.    if (_root == nullptr)
    31.     _root = new Node(keyvalue);
    32.    else
    33.    {
    34.     Node* cur = _root;
    35.     Node* parent = nullptr;
    36.     while (cur)
    37.     {
    38.      if (cur->_key == key)
    39.       return false;
    40.      parent = cur;
    41.      if (key > cur->_key)
    42.       cur = cur->_cright;
    43.      else if (key < cur->_key)
    44.       cur = cur->_cleft;
    45.     }
    46.     cur = new Node(keyvalue);
    47.     if (cur == parent->_cleft)
    48.      parent->_cleft = cur;
    49.     else
    50.      parent->_cright = cur;
    51.    }
    52.    return true;
    53.   }
    54.   void InOrder()
    55.   {
    56.    _Inorder(_root);
    57.   }
    58.   Node*& Find(const K& key)
    59.   {
    60.    Node* cur = _root;
    61.    while (cur)
    62.    {
    63.     if (key > cur->_key)
    64.      cur = cur->_cright;
    65.     else if (key < cur->_key)
    66.      cur = cur->_cleft;
    67.     else
    68.      break;
    69.    }
    70.    return cur;
    71.   }
    72.   bool Erase(const K& key)
    73.   {
    74.    if (_root == nullptr)
    75.     return false;
    76.    Node* cur = _root;
    77.    Node* parent = nullptr;
    78.    while (cur)
    79.    {
    80.     if (cur->_key == key)
    81.      break;
    82.     parent = cur;
    83.     if (key > cur->_key)
    84.      cur = cur->_cright;
    85.     else if (key < cur->_key)
    86.      cur = cur->_cleft;
    87.    }
    88.    if (parent == nullptr)
    89.    {
    90.     if (cur->_cleft == nullptr && cur->_cright == nullptr)
    91.     {
    92.      delete _root;
    93.      _root = nullptr;
    94.     }
    95.     else if (cur->_cleft == nullptr)
    96.      _root = _root->_cright;
    97.     else
    98.      _root = _root->_cleft;
    99.     return true;
    100.    }
    101.    if (cur->_cleft == nullptr && cur->_cright == nullptr)
    102.    {
    103.     if (cur == parent->_cleft)
    104.      parent->_cleft = nullptr;
    105.     else
    106.      parent->_cright = nullptr;
    107.     delete cur;
    108.    }
    109.    else if (cur->_cleft == nullptr)
    110.    {
    111.     if (cur == parent->_cleft)
    112.      parent->_cleft = cur->_cright;
    113.     else
    114.      parent->_cright = cur->_cright;
    115.     delete cur;
    116.    }
    117.    else if (cur->_cright == nullptr)
    118.    {
    119.     if (cur == parent->_cleft)
    120.      parent->_cleft = cur->_cleft;
    121.     else
    122.      parent->_cright = cur->_cleft;
    123.    }
    124.    else
    125.    {
    126.     Node* parntRL = nullptr;
    127.     Node* curRL = cur->_cright;
    128.     while (curRL->_cleft != nullptr)
    129.     {
    130.      parntRL = curRL;
    131.      curRL = curRL->_cleft;
    132.     }
    133.     swap(curRL->_key, cur->_key);
    134.     if (curRL == parntRL->_cleft)
    135.      parntRL->_cleft = curRL->_cright;
    136.     else
    137.      parntRL->_cright = curRL->_cright;
    138.     delete curRL;
    139.    }
    140.    return true;
    141.   }
    142.  private:
    143.   void _Inorder(const Node* root)
    144.   {
    145.    if (root == nullptr)
    146.     return;
    147.    _Inorder(root->_cleft);
    148.    cout << root->_key << ' ' << root->_value << ' ' << endl;
    149.    _Inorder(root->_cright);
    150.   }
    151.   Node* _root;
    152.  };
    153. }

    kv模型搜索二叉树的定义

    • 是模板类,模板参数是K和V

    • 成员函数和k模型一模一样

    1. template<class K, class V>
    2.  class SBTree
    3.  {
    4.   typedef SBTreeNode<K, V> Node;
    5.  public:
    6.   SBTree()
    7.    :_root(nullptr)
    8.   {}
    9.  public:
    10.   bool Insert(const K& key, const V& value)
    11.   {
    12.    if (_root == nullptr)
    13.     _root = new Node(keyvalue);
    14.    else
    15.    {
    16.     Node* cur = _root;
    17.     Node* parent = nullptr;
    18.     while (cur)
    19.     {
    20.      if (cur->_key == key)
    21.       return false;
    22.      parent = cur;
    23.      if (key > cur->_key)
    24.       cur = cur->_cright;
    25.      else if (key < cur->_key)
    26.       cur = cur->_cleft;
    27.     }
    28.     cur = new Node(keyvalue);
    29.     if (cur == parent->_cleft)
    30.      parent->_cleft = cur;
    31.     else
    32.      parent->_cright = cur;
    33.    }
    34.    return true;
    35.   }
    36.   void InOrder()
    37.   {
    38.    _Inorder(_root);
    39.   }
    40.   Node*& Find(const K& key)
    41.   {
    42.    Node* cur = _root;
    43.    while (cur)
    44.    {
    45.     if (key > cur->_key)
    46.      cur = cur->_cright;
    47.     else if (key < cur->_key)
    48.      cur = cur->_cleft;
    49.     else
    50.      break;
    51.    }
    52.    return cur;
    53.   }
    54.   bool Erase(const K& key)
    55.   {
    56.    if (_root == nullptr)
    57.     return false;
    58.    Node* cur = _root;
    59.    Node* parent = nullptr;
    60.    while (cur)
    61.    {
    62.     if (cur->_key == key)
    63.      break;
    64.     parent = cur;
    65.     if (key > cur->_key)
    66.      cur = cur->_cright;
    67.     else if (key < cur->_key)
    68.      cur = cur->_cleft;
    69.    }
    70.    if (parent == nullptr)
    71.    {
    72.     if (cur->_cleft == nullptr && cur->_cright == nullptr)
    73.     {
    74.      delete _root;
    75.      _root = nullptr;
    76.     }
    77.     else if (cur->_cleft == nullptr)
    78.      _root = _root->_cright;
    79.     else
    80.      _root = _root->_cleft;
    81.     return true;
    82.    }
    83.    if (cur->_cleft == nullptr && cur->_cright == nullptr)
    84.    {
    85.     if (cur == parent->_cleft)
    86.      parent->_cleft = nullptr;
    87.     else
    88.      parent->_cright = nullptr;
    89.     delete cur;
    90.    }
    91.    else if (cur->_cleft == nullptr)
    92.    {
    93.     if (cur == parent->_cleft)
    94.      parent->_cleft = cur->_cright;
    95.     else
    96.      parent->_cright = cur->_cright;
    97.     delete cur;
    98.    }
    99.    else if (cur->_cright == nullptr)
    100.    {
    101.     if (cur == parent->_cleft)
    102.      parent->_cleft = cur->_cleft;
    103.     else
    104.      parent->_cright = cur->_cleft;
    105.    }
    106.    else
    107.    {
    108.     Node* parntRL = nullptr;
    109.     Node* curRL = cur->_cright;
    110.     while (curRL->_cleft != nullptr)
    111.     {
    112.      parntRL = curRL;
    113.      curRL = curRL->_cleft;
    114.     }
    115.     swap(curRL->_key, cur->_key);
    116.     if (curRL == parntRL->_cleft)
    117.      parntRL->_cleft = curRL->_cright;
    118.     else
    119.      parntRL->_cright = curRL->_cright;
    120.     delete curRL;
    121.    }
    122.    return true;
    123.   }
    124.  private:
    125.   void _Inorder(const Node* root)
    126.   {
    127.    if (root == nullptr)
    128.     return;
    129.    _Inorder(root->_cleft);
    130.    cout << root->_key << ' ' << root->_value << ' ' << endl;
    131.    _Inorder(root->_cright);
    132.   }
    133.   Node* _root;
    134.  };

    kv模型节点的定义

    • 节点是模板类,模板参数为K和V

    • 成员为左子树指针、右子树指针、关键字、所对应的值

    • 依然以匿名对象作为缺省参数,使得我们程序更加通用

    1. template<class K, class V>
    2.  struct SBTreeNode
    3.  {
    4.  public:
    5.   SBTreeNode(const K& key = K(), const V& value = V())
    6.    :_cleft(nullptr), _cright(nullptr)
    7.    , _key(key)
    8.    , _value(value)
    9.   {}
    10.  public:
    11.   SBTreeNode* _cleft;
    12.   SBTreeNode* _cright;
    13.   K _key;
    14.   V _value;
    15.  };

    Insert函数

    • 该函数参数为关键字、值

    • 首先判断该树有无节点,无节点则直接给_root赋值,有节点则先找要插入的位置,插入的同时改变其父亲节点所对应的指针

    • 返回值为插入状态

    1. bool Insert(const K& key, const V& value)
    2.   {
    3.    if (_root == nullptr)
    4.     _root = new Node(keyvalue);
    5.    else
    6.    {
    7.     Node* cur = _root;
    8.     Node* parent = nullptr;
    9.     while (cur)
    10.     {
    11.      if (cur->_key == key)
    12.       return false;
    13.      parent = cur;
    14.      if (key > cur->_key)
    15.       cur = cur->_cright;
    16.      else if (key < cur->_key)
    17.       cur = cur->_cleft;
    18.     }
    19.     cur = new Node(keyvalue);
    20.     if (cur == parent->_cleft)
    21.      parent->_cleft = cur;
    22.     else
    23.      parent->_cright = cur;
    24.    }
    25.    return true;
    26.   }

    Find函数

    • 和k模型的一模一样,不做赘述

    1. Node*& Find(const K& key)
    2.   {
    3.    Node* cur = _root;
    4.    while (cur)
    5.    {
    6.     if (key > cur->_key)
    7.      cur = cur->_cright;
    8.     else if (key < cur->_key)
    9.      cur = cur->_cleft;
    10.     else
    11.      break;
    12.    }
    13.    return cur;
    14.   }

    Erase函数

    • 和k模型的一模一样,不做赘述

    1.  bool Erase(const K& key)
    2.   {
    3.    if (_root == nullptr)
    4.     return false;
    5.    Node* cur = _root;
    6.    Node* parent = nullptr;
    7.    while (cur)
    8.    {
    9.     if (cur->_key == key)
    10.      break;
    11.     parent = cur;
    12.     if (key > cur->_key)
    13.      cur = cur->_cright;
    14.     else if (key < cur->_key)
    15.      cur = cur->_cleft;
    16.    }
    17.    if (parent == nullptr)
    18.    {
    19.     if (cur->_cleft == nullptr && cur->_cright == nullptr)
    20.     {
    21.      delete _root;
    22.      _root = nullptr;
    23.     }
    24.     else if (cur->_cleft == nullptr)
    25.      _root = _root->_cright;
    26.     else
    27.      _root = _root->_cleft;
    28.     return true;
    29.    }
    30.    if (cur->_cleft == nullptr && cur->_cright == nullptr)
    31.    {
    32.     if (cur == parent->_cleft)
    33.      parent->_cleft = nullptr;
    34.     else
    35.      parent->_cright = nullptr;
    36.     delete cur;
    37.    }
    38.    else if (cur->_cleft == nullptr)
    39.    {
    40.     if (cur == parent->_cleft)
    41.      parent->_cleft = cur->_cright;
    42.     else
    43.      parent->_cright = cur->_cright;
    44.     delete cur;
    45.    }
    46.    else if (cur->_cright == nullptr)
    47.    {
    48.     if (cur == parent->_cleft)
    49.      parent->_cleft = cur->_cleft;
    50.     else
    51.      parent->_cright = cur->_cleft;
    52.    }
    53.    else
    54.    {
    55.     Node* parntRL = nullptr;
    56.     Node* curRL = cur->_cright;
    57.     while (curRL->_cleft != nullptr)
    58.     {
    59.      parntRL = curRL;
    60.      curRL = curRL->_cleft;
    61.     }
    62.     swap(curRL->_key, cur->_key);
    63.     if (curRL == parntRL->_cleft)
    64.      parntRL->_cleft = curRL->_cright;
    65.     else
    66.      parntRL->_cright = curRL->_cright;
    67.     delete curRL;
    68.    }
    69.    return true;
    70.   }
  • 相关阅读:
    Pytorch编程基础
    公司实战 ElasticSearch+Kafka+Redis+MySQL
    systemverilog学习 --- 随机化(1)
    15-JavaSE基础巩固练习:多态、接口、抽象类的综合练习
    vscode使用ssh连接远程Ubuntu服务器(记录)
    辅助知识-第2 章 项目合同管理
    基于springboot停车位管理系统【附源码】开源项目
    【含2023java面试题】深入解析JVM调优:解决OutOfMemoryError、内存泄露、线程死锁、锁争用和高CPU消耗问题
    解决win11更新后,文件夹打不开的bug
    Spring Boot集成Minio插件快速入门
  • 原文地址:https://blog.csdn.net/ZHENGZJM/article/details/134278789