• 数据结构:二叉搜索树


    目录

    1、二叉搜索树概念

    2、 二叉搜索树的插入

    3、二叉搜索树的查找

    4、二叉搜索树的删除

    5、二叉搜索树的中序遍历

    实现


    1、二叉搜索树概念

    二叉搜索树又称二叉排序树,它或者是一棵空树 ,或者是具有以下性质的二叉树 :
    • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
    • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
    • 它的左右子树也分别为二叉搜索树

     定义一个二叉搜索树类

    1. template<class K>
    2. struct BSTreeNode
    3. {
    4. BSTreeNode<K>* _left;
    5. BSTreeNode<K>* _right;
    6. K _key;
    7. BSTreeNode(const K& key)
    8. :_left(nullptr)
    9. , _right(nullptr)
    10. , _key(key)
    11. {}
    12. };
    13. template<class K>
    14. class BSTree
    15. {
    16. typedef BSTreeNode<K> Node;
    17. private:
    18. Node* _root = nullptr;
    19. public:
    20. bool Insert(const K& key); //插入
    21. bool Find(const K& key); //查找
    22. bool Erase(const K& key); //删除
    23. void InOrder(); //中序遍历
    24. void _InOrder(Node* root);
    25. };

    2、 二叉搜索树的插入

    • 树为空,则直接新增节点,赋值给root指针
    • 树不空,按二叉搜索树性质查找插入位置,插入新节点

    1. template<class K>
    2. bool BSTree<K>::Insert(const K& key)
    3. {
    4. if (_root == nullptr)
    5. {
    6. _root = new Node(key);
    7. return true;
    8. }
    9. Node* parent = nullptr;
    10. Node* cur = _root;
    11. while (cur != nullptr)
    12. {
    13. parent = cur;
    14. if (cur->_key < key)
    15. {
    16. cur = cur->_right;
    17. }
    18. else if (cur->_key > key)
    19. {
    20. cur = cur->_left;
    21. }
    22. else
    23. {
    24. return false; //cur->_key == key
    25. }
    26. }
    27. cur = new Node(key);
    28. if (parent->_key < key)
    29. {
    30. parent->_right = cur;
    31. }
    32. else
    33. {
    34. parent->_left = cur;
    35. }
    36. return true;
    37. }

    3、二叉搜索树的查找

    • 从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
    • 最多查找高度次,走到到空,还没找到,这个值不存在。
    1. template<class K>
    2. bool BSTree<K>::Find(const K& key)
    3. {
    4. Node* cur = _root;
    5. while (cur != nullptr)
    6. {
    7. if (key < cur->_key) //key小于cur->_key,cur向左走
    8. {
    9. cur = cur->_left;
    10. }
    11. else if (key > cur->_key) //key大于于cur->_key,cur向右走
    12. {
    13. cur = cur->_right;
    14. }
    15. else //key等于于cur->_key,返回true
    16. {
    17. return true;
    18. }
    19. }
    20. return false; //不存在返回false
    21. }

    4、二叉搜索树的删除

    首先查找元素是否在二叉搜索树中,如果不存在,则返回 , 否则要删除的结点可能分下面四种情
    况:
    • 要删除的结点无孩子结点
    • 要删除的结点只有左孩子结点
    • 要删除的结点只有右孩子结点
    • 要删除的结点有左、右孩子结点
    看起来有待删除节点有 4 中情况,实际情况 a 可以与情况 b 或者 c 合并起来,因此真正的删除过程
    如下:
    • 删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除
    • 删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除
    • 在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题--替换法删除

     替换法删除:我们可以使用被删的节点的左子树的最大节点或者右子树的最小节点,来替代被删的节点的值

    1. template<class K>
    2. bool BSTree::Erase(const K& key)
    3. {
    4. Node* parent = nullptr;
    5. Node* cur = _root;
    6. while (cur != nullptr)
    7. {
    8. if (cur->_key < key)
    9. {
    10. parent = cur;
    11. cur = cur->_right;
    12. }
    13. else if (cur->_key > key)
    14. {
    15. parent = cur;
    16. cur = cur->_left;
    17. }
    18. else //找到要删除的数
    19. {
    20. // 准备删除
    21. //分为三种情况
    22. //1、左为空
    23. //2、右为空
    24. //3、左右都不为空
    25. if (cur->_left == nullptr) //左为空
    26. {
    27. if (cur == _root) //1、要删除的点为根节点
    28. {
    29. _root = cur->_right;
    30. }
    31. else
    32. {
    33. if (cur == parent->_left)
    34. {
    35. parent->_left = cur->_right;
    36. }
    37. else
    38. {
    39. parent->_right = cur->_right;
    40. }
    41. }
    42. }
    43. else if (cur->_right == nullptr) //右为空
    44. {
    45. if (cur == _root) //1、要删除的点为根节点
    46. {
    47. _root = cur->_left;
    48. }
    49. else
    50. {
    51. if (cur == parent->_left)
    52. {
    53. parent->_left = cur->_left;
    54. }
    55. else
    56. {
    57. parent->_right = cur->_left;
    58. }
    59. }
    60. }
    61. else //左右都不为空
    62. {
    63. //我们可以使用被删的节点的左子树的最大节点或者右子树的最小节点,
    64. //来替代被删的节点的值
    65. Node* parent = cur;
    66. Node* subLeft = cur->_right;
    67. while (subLeft->_left)
    68. {
    69. parent = subLeft;
    70. subLeft = subLeft->_left; // 右子树的最小节点(最左节点)
    71. }
    72. swap(cur->_key, subLeft->_key); //右子树的最小节点与被删节点的值交换
    73. if (subLeft == parent->_left)
    74. {
    75. parent->_left = subLeft->_right;
    76. }
    77. else
    78. {
    79. parent->_right = subLeft->_right;
    80. }
    81. }
    82. return true;
    83. }
    84. }
    85. return false; //没有找到要删除的数
    86. }

    5、二叉搜索树的中序遍历

    根据二叉搜索树的特性,我们可以推出二叉搜索树的中序遍历是一个有序的数据

    我们可以采用递归的方法去遍历

    1. template<class K>
    2. void BSTree<K>::InOrder()
    3. {
    4. _InOrder(_root);
    5. cout << endl;
    6. }
    7. template<class K>
    8. void BSTree<K>::_InOrder(Node* root)
    9. {
    10. if (root == nullptr)
    11. return;
    12. _InOrder(root->_left);
    13. cout << root->_key << " ";
    14. _InOrder(root->_right);
    15. }

    实现

    1. template<class K>
    2. struct BSTreeNode
    3. {
    4. BSTreeNode<K>* _left;
    5. BSTreeNode<K>* _right;
    6. K _key;
    7. BSTreeNode(const K& key)
    8. :_left(nullptr)
    9. , _right(nullptr)
    10. , _key(key)
    11. {}
    12. };
    13. template<class K>
    14. class BSTree
    15. {
    16. typedef BSTreeNode<K> Node;
    17. private:
    18. Node* _root = nullptr;
    19. public:
    20. bool Insert(const K& key); //插入
    21. bool Find(const K& key); //查找
    22. bool Erase(const K& key); //删除
    23. void InOrder(); //中序遍历
    24. void _InOrder(Node* root);
    25. };
    26. template<class K>
    27. bool BSTree<K>::Insert(const K& key)
    28. {
    29. if (_root == nullptr)
    30. {
    31. _root = new Node(key);
    32. return true;
    33. }
    34. Node* parent = nullptr;
    35. Node* cur = _root;
    36. while (cur != nullptr)
    37. {
    38. parent = cur;
    39. if (cur->_key < key)
    40. {
    41. cur = cur->_right;
    42. }
    43. else if (cur->_key > key)
    44. {
    45. cur = cur->_left;
    46. }
    47. else
    48. {
    49. return false; //cur->_key == key
    50. }
    51. }
    52. cur = new Node(key);
    53. if (parent->_key < key)
    54. {
    55. parent->_right = cur;
    56. }
    57. else
    58. {
    59. parent->_left = cur;
    60. }
    61. return true;
    62. }
    63. template<class K>
    64. bool BSTree<K>::Find(const K& key)
    65. {
    66. Node* cur = _root;
    67. while (cur != nullptr)
    68. {
    69. if (key < cur->_key) //key小于cur->_key,cur向左走
    70. {
    71. cur = cur->_left;
    72. }
    73. else if (key > cur->_key) //key大于于cur->_key,cur向右走
    74. {
    75. cur = cur->_right;
    76. }
    77. else //key等于于cur->_key,返回true
    78. {
    79. return true;
    80. }
    81. }
    82. return false; //不存在返回false
    83. }
    84. template<class K>
    85. bool BSTree<K>::Erase(const K& key)
    86. {
    87. Node* parent = nullptr;
    88. Node* cur = _root;
    89. while (cur != nullptr)
    90. {
    91. if (cur->_key < key)
    92. {
    93. parent = cur;
    94. cur = cur->_right;
    95. }
    96. else if (cur->_key > key)
    97. {
    98. parent = cur;
    99. cur = cur->_left;
    100. }
    101. else
    102. {
    103. // 准备删除
    104. if (cur->_left == nullptr) //左为空
    105. {
    106. if (cur == _root)
    107. {
    108. _root = cur->_right;
    109. }
    110. else
    111. {
    112. if (cur == parent->_left)
    113. {
    114. parent->_left = cur->_right;
    115. }
    116. else
    117. {
    118. parent->_right = cur->_right;
    119. }
    120. }
    121. }
    122. else if (cur->_right == nullptr) //右为空
    123. {
    124. if (cur == _root)
    125. {
    126. _root = cur->_left;
    127. }
    128. else
    129. {
    130. if (cur == parent->_left)
    131. {
    132. parent->_left = cur->_left;
    133. }
    134. else
    135. {
    136. parent->_right = cur->_left;
    137. }
    138. }
    139. }
    140. else
    141. {//左右都不为空
    142. // 右树的最小节点(最左节点)
    143. Node* parent = cur;
    144. Node* subLeft = cur->_right;
    145. while (subLeft->_left)
    146. {
    147. parent = subLeft;
    148. subLeft = subLeft->_left;
    149. }
    150. swap(cur->_key, subLeft->_key);
    151. if (subLeft == parent->_left)
    152. parent->_left = subLeft->_right;
    153. else
    154. parent->_right = subLeft->_right;
    155. }
    156. return true;
    157. }
    158. }
    159. return false;
    160. }
    161. template<class K>
    162. void BSTree<K>::InOrder()
    163. {
    164. _InOrder(_root);
    165. cout << endl;
    166. }
    167. template<class K>
    168. void BSTree<K>::_InOrder(Node* root)
    169. {
    170. if (root == nullptr)
    171. return;
    172. _InOrder(root->_left);
    173. cout << root->_key << " ";
    174. _InOrder(root->_right);
    175. }

  • 相关阅读:
    Idea中运行sparkSQL
    45.120.101.X 如何找出网站建设中弱点和漏洞
    AMBA总线相关知识记录
    Windows OpenGL ES 图像灰度图
    跟李沐学AI之现代卷积神经网络
    MySQL入门第六天——函数与条件查询
    C#中List、Dictionary、HashSet用法以及区别
    java图片处理
    Mysql 自带分页异常
    为期一周的数据分析与Excel,继续加油,多练习
  • 原文地址:https://blog.csdn.net/weixin_74268082/article/details/134022226