• java实现二叉搜索树


    1.前言

    二叉搜索树是一种特殊的二叉树,它的每一个节点都满足以下条件:

    1. 左子树中所有节点的值均小于该节点的值。
    2. 右子树中所有节点的值均大于该节点的值。
    3. 每个子树也都是二叉搜索树。

    通过这种特殊的结构,二叉搜索树能够实现快速的插入、查找和删除操作。在二叉搜索树中,插入一个新节点的时间复杂度为 O(log n),查找或删除一个节点的时间复杂度同样为 O(log n),其中 n 是树中节点的数量。

    因为其高效的查找和排序性质,二叉搜索树被广泛应用于各种领域,例如数据库索引、哈希表等数据结构的实现、模拟字典等应用中。

    2.原理分析

    2.1添加节点

    1. 首先,需要确定要插入的节点在树中的位置。从根节点开始,与要插入的节点进行比较。

    2. 如果要插入的节点的值小于当前节点的值,那么就将其作为当前节点的左子节点。如果当前节点的左子节点为空,直接插入;如果不为空,将当前节点指向其左子节点,并继续执行第一步。

    3. 如果要插入的节点的值大于当前节点的值,那么就将其作为当前节点的右子节点。如果当前节点的右子节点为空,直接插入;如果不为空,将当前节点指向其右子节点,并继续执行第一步。

    4. 重复执行步骤 2 和步骤 3,直到找到合适的空位置插入节点。

    2.2删除节点 

    1. 首先,我们需要找到要删除的节点。从根节点开始,比较要删除的值与当前节点的值,根据大小关系选择向左子树或右子树移动,直到找到与要删除的值相等的节点。

    2. 找到要删除的节点后,有以下几种情况:

      • 如果要删除的节点是叶节点(即没有左子树和右子树),直接将其从树中删除即可。

      • 如果要删除的节点只有左子树或只有右子树,我们需要用它的子节点来替代要删除的节点。

      • 如果要删除的节点既有左子树又有右子树,我们可以选择以下两种方式来替代要删除的节点:

        a. 在右子树中找到最小的节点,即右子树中的最左叶节点。将该节点的值复制到要删除的节点,并将该节点删除。这样可以保持二叉搜索树的性质。

        b. 在左子树中找到最大的节点,即左子树中的最右叶节点。将该节点的值复制到要删除的节点,并将该节点删除。同样,这样可以保持二叉搜索树的性质。

    3. 完成替代操作后,整个树的结构依然保持二叉搜索树的性质。

    2.3查找节点 

    1. 从根节点开始,将要查找的值与当前节点的值进行比较。

    2. 如果要查找的值等于当前节点的值,那么说明找到了目标节点,返回当前节点。

    3. 如果要查找的值小于当前节点的值,那么说明目标节点位于当前节点的左子树中。则将当前节点指向其左子节点,并继续执行第一步。

    4. 如果要查找的值大于当前节点的值,那么说明目标节点位于当前节点的右子树中。则将当前节点指向其右子节点,并继续执行第一步。

    5. 重复执行步骤 2、3 和 4,直到找到目标节点或者遍历完整个树(表示目标节点不存在)。

    3.代码实现 

    3.1准备工作

     1.创建节点类
    1. //创建节点类
    2. private static class TreeNode{
    3. T value;
    4. TreeNode left;
    5. TreeNode right;
    6. //叶节点专属构造方法
    7. public TreeNode(T value) {
    8. this.value = value;
    9. left = null;
    10. right = null;
    11. }
    12. //默认构造方法
    13. public TreeNode(T value, TreeNode left, TreeNode right) {
    14. this.value = value;
    15. this.left = left;
    16. this.right = right;
    17. }
    18. }
    2.基础属性
    1. public class TreeNodeTestextends Comparable>{
    2. private TreeNode root;//创建一个根节点
    3. public TreeNodeTest() {
    4. root = null;
    5. }
    6. //指定一个根节点创建树
    7. public TreeNodeTest(TreeNode root) {
    8. this.root = root;
    9. }

    3.2插入节点 

    1. //插入节点
    2. public void insert(T value){
    3. root = insertRecursive(root, value);
    4. }
    5. //递归实现插入节点
    6. private TreeNode insertRecursive(TreeNode root, T value) {
    7. if (root == null){
    8. return new TreeNode<>(value);
    9. }
    10. if (value.compareTo(root.value) < 0){
    11. //小于此节点往此节点后面子节点继续找
    12. root.left = insertRecursive(root.left,value);
    13. }else if (value.compareTo(root.value) > 0){
    14. root.right = insertRecursive(root.right,value);
    15. }
    16. return root;
    17. }

    3.3查找节点

    1. // 查找最小值节点
    2. private TreeNode findMin(TreeNode node) {
    3. if (node.left == null) {
    4. return node;
    5. }
    6. return findMin(node.left);
    7. }
    8. //查找节点
    9. public boolean contains(T value) {
    10. return containsRecursive(root, value);
    11. }
    12. //递归实现查找节点
    13. private boolean containsRecursive(TreeNode root, T value) {
    14. //递归的出口
    15. if (root == null){
    16. //意味着找到最后也没找到
    17. return false;
    18. }
    19. if (value.compareTo(root.value) == 0){
    20. return true;
    21. }
    22. if (value.compareTo(root.value) < 0){
    23. return containsRecursive(root.left,value);
    24. }else{
    25. return containsRecursive(root.right,value);
    26. }
    27. }

    3.4删除节点

    1. // 删除节点
    2. public void delete(T value) {
    3. root = deleteRecursive(root, value);
    4. }
    5. // 递归实现删除节点
    6. private TreeNode deleteRecursive(TreeNode root, T value) {
    7. if (root == null) {
    8. return null;
    9. }
    10. if (value.compareTo(root.value) < 0) {
    11. root.left = deleteRecursive(root.left, value);
    12. } else if (value.compareTo(root.value) > 0) {
    13. root.right = deleteRecursive(root.right, value);
    14. } else {
    15. // 找到要删除的节点
    16. if (root.left == null && root.right == null) {
    17. // 叶节点,直接删除
    18. return null;
    19. } else if (root.left == null) {
    20. // 只有右子树,用右子节点替代要删除的节点
    21. return root.right;
    22. } else if (root.right == null) {
    23. // 只有左子树,用左子节点替代要删除的节点
    24. return root.left;
    25. } else {
    26. // 左右子树都存在,找到右子树中最小的节点,替代要删除的节点
    27. TreeNode minNode = findMin(root.right);
    28. root.value = minNode.value;
    29. root.right = deleteRecursive(root.right, minNode.value);
    30. }
    31. }
    32. return root;
    33. }

    3.5前中后序遍历

    1. // 前序遍历
    2. public void preOrderTraversal() {
    3. preOrderTraversalRecursive(root);
    4. }
    5. private void preOrderTraversalRecursive(TreeNode node) {
    6. if (node != null) {
    7. System.out.print(node.value + " ");
    8. preOrderTraversalRecursive(node.left);
    9. preOrderTraversalRecursive(node.right);
    10. }
    11. }
    12. // 中序遍历
    13. public void inOrderTraversal() {
    14. inOrderTraversalRecursive(root);
    15. }
    16. private void inOrderTraversalRecursive(TreeNode node) {
    17. if (node != null) {
    18. inOrderTraversalRecursive(node.left);
    19. System.out.print(node.value + " ");
    20. inOrderTraversalRecursive(node.right);
    21. }
    22. }
    23. // 后序遍历
    24. public void postOrderTraversal() {
    25. postOrderTraversalRecursive(root);
    26. }
    27. private void postOrderTraversalRecursive(TreeNode node) {
    28. if (node != null) {
    29. postOrderTraversalRecursive(node.left);
    30. postOrderTraversalRecursive(node.right);
    31. System.out.print(node.value + " ");
    32. }
    33. }

    4.全部代码

    1. /*
    2. * 实现二叉树搜索树
    3. *
    4. * */
    5. //因为是二叉搜索树所以要引入Comparable接口要不然引用类型无法比较
    6. public class TreeNodeTestextends Comparable>{
    7. private TreeNode root;//创建一个根节点
    8. //创建节点类
    9. private static class TreeNode{
    10. T value;
    11. TreeNode left;
    12. TreeNode right;
    13. //叶节点专属构造方法
    14. public TreeNode(T value) {
    15. this.value = value;
    16. left = null;
    17. right = null;
    18. }
    19. //默认构造方法
    20. public TreeNode(T value, TreeNode left, TreeNode right) {
    21. this.value = value;
    22. this.left = left;
    23. this.right = right;
    24. }
    25. }
    26. public TreeNodeTest() {
    27. root = null;
    28. }
    29. //指定一个根节点创建树
    30. public TreeNodeTest(TreeNode root) {
    31. this.root = root;
    32. }
    33. //插入节点
    34. public void insert(T value){
    35. root = insertRecursive(root, value);
    36. }
    37. //递归实现插入节点
    38. private TreeNode insertRecursive(TreeNode root, T value) {
    39. if (root == null){
    40. return new TreeNode<>(value);
    41. }
    42. if (value.compareTo(root.value) < 0){
    43. //小于此节点往此节点后面子节点继续找
    44. root.left = insertRecursive(root.left,value);
    45. }else if (value.compareTo(root.value) > 0){
    46. root.right = insertRecursive(root.right,value);
    47. }
    48. return root;
    49. }
    50. // 删除节点
    51. public void delete(T value) {
    52. root = deleteRecursive(root, value);
    53. }
    54. // 递归实现删除节点
    55. private TreeNode deleteRecursive(TreeNode root, T value) {
    56. if (root == null) {
    57. return null;
    58. }
    59. if (value.compareTo(root.value) < 0) {
    60. root.left = deleteRecursive(root.left, value);
    61. } else if (value.compareTo(root.value) > 0) {
    62. root.right = deleteRecursive(root.right, value);
    63. } else {
    64. // 找到要删除的节点
    65. if (root.left == null && root.right == null) {
    66. // 叶节点,直接删除
    67. return null;
    68. } else if (root.left == null) {
    69. // 只有右子树,用右子节点替代要删除的节点
    70. return root.right;
    71. } else if (root.right == null) {
    72. // 只有左子树,用左子节点替代要删除的节点
    73. return root.left;
    74. } else {
    75. // 左右子树都存在,找到右子树中最小的节点,替代要删除的节点
    76. TreeNode minNode = findMin(root.right);
    77. root.value = minNode.value;
    78. root.right = deleteRecursive(root.right, minNode.value);
    79. }
    80. }
    81. return root;
    82. }
    83. // 查找最小值节点
    84. private TreeNode findMin(TreeNode node) {
    85. if (node.left == null) {
    86. return node;
    87. }
    88. return findMin(node.left);
    89. }
    90. //查找节点
    91. public boolean contains(T value) {
    92. return containsRecursive(root, value);
    93. }
    94. //递归实现查找节点
    95. private boolean containsRecursive(TreeNode root, T value) {
    96. //递归的出口
    97. if (root == null){
    98. //意味着找到最后也没找到
    99. return false;
    100. }
    101. if (value.compareTo(root.value) == 0){
    102. return true;
    103. }
    104. if (value.compareTo(root.value) < 0){
    105. return containsRecursive(root.left,value);
    106. }else{
    107. return containsRecursive(root.right,value);
    108. }
    109. }
    110. // 前序遍历
    111. public void preOrderTraversal() {
    112. preOrderTraversalRecursive(root);
    113. }
    114. private void preOrderTraversalRecursive(TreeNode node) {
    115. if (node != null) {
    116. System.out.print(node.value + " ");
    117. preOrderTraversalRecursive(node.left);
    118. preOrderTraversalRecursive(node.right);
    119. }
    120. }
    121. // 中序遍历
    122. public void inOrderTraversal() {
    123. inOrderTraversalRecursive(root);
    124. }
    125. private void inOrderTraversalRecursive(TreeNode node) {
    126. if (node != null) {
    127. inOrderTraversalRecursive(node.left);
    128. System.out.print(node.value + " ");
    129. inOrderTraversalRecursive(node.right);
    130. }
    131. }
    132. // 后序遍历
    133. public void postOrderTraversal() {
    134. postOrderTraversalRecursive(root);
    135. }
    136. private void postOrderTraversalRecursive(TreeNode node) {
    137. if (node != null) {
    138. postOrderTraversalRecursive(node.left);
    139. postOrderTraversalRecursive(node.right);
    140. System.out.print(node.value + " ");
    141. }
    142. }
    143. public static void main(String[] args) {
    144. TreeNodeTest tree = new TreeNodeTest<>();
    145. tree.insert(5);
    146. tree.insert(3);
    147. tree.insert(7);
    148. tree.insert(1);
    149. tree.insert(4);
    150. tree.insert(6);
    151. tree.insert(8);
    152. System.out.println("前序遍历结果:");
    153. tree.preOrderTraversal();
    154. System.out.println("\n中序遍历结果:");
    155. tree.inOrderTraversal();
    156. System.out.println("\n后序遍历结果:");
    157. tree.postOrderTraversal();
    158. System.out.println("\n是否包含值为 4 的节点:" + tree.contains(4));
    159. }
    160. }

  • 相关阅读:
    操作系统考研笔记
    containerd客户端比较
    docker容器中访问本地宿主机的服务
    matlab simulink 四旋翼跟拍无人机仿真
    抖音矩阵系统源码独立部署定制开发。tell me
    在 CentOS 8.2 上安装 MySQL C/C++ 客户端库 libmysqlclient.so
    java计算机毕业设计信用卡逾期数据处理分析系统源程序+mysql+系统+lw文档+远程调试
    Feign源码解析:初始化过程(二)
    springboot+rocketmq(5):实现批量消息
    新能源充电桩工业4G路由器应用,推动绿色出行,响应环保理念
  • 原文地址:https://blog.csdn.net/m0_74749208/article/details/133893726