zoukankan      html  css  js  c++  java
  • D12-二叉排序树[Java数据结构和算法]

    1.二叉排序树(BST;Binary Sort(Search)Tree)

      1.1对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大;当有两个相同的值时,可以放在左子节点或右子节点;

    2.二叉排序树删除节点

      2.1删除叶子节点

      (1)找到要删除的节点targetNode;

      (2)找到targetNode的父节点parent;

      (3)确定targetNode是parent的左子节点还是右子节点;

      (4)根据步骤(3)的情况对应删除节点;

      2.2 删除只有一颗子树的节点

      (1)找到要删除的节点targetNode;

      (2)找到targetNode的父节点parent;

      (3)确定targetNode的子节点是左子节点还是右子节点;

      (4)确定targetNode是parent的左子节点还是右子节点;

      (5)如果targerNode有左子节点  

        (5.1)targetNode是parent的左子节点:parent.left=targetNode.left;

        (5.2)targetNode是parent的右子节点:parent.right=targetNode.left;

      (6)如果targerNode有右子节点 

        (6.1)targetNode是parent的左子节点:parent.left=targetNode.right;

        (6.2)targetNode是parent的右子节点:parent.right=targetNode.right;

      2.3 删除有两颗子树的节点

      (1)找到要删除的节点targetNode;

       (2)找到targetNode的父节点parent;

      (3)从targetNode的右子树找到最小的节点;

      (4)用一个临时遍历,将最小节点的值保存temp;

      (5)删除这个最小节点;

      (6)targetNode.value=temp;

      2.4 源代码

      1 package cn.atguigu.binarySortTree;
      2 
      3 import java.lang.annotation.Target;
      4 
      5 public class BinarySortTreeDemo {
      6 
      7     public static void main(String[] args) {
      8         int[] arr = { 7, 3, 10, 12, 5, 1, 9,2 };
      9         BinarySortTree b = new BinarySortTree();
     10         // 循环的添加节点到二叉排序树
     11         for (int i = 0; i < arr.length; i++) {
     12             b.add(new Node(arr[i]));
     13         }
     14         System.out.println("中序遍历二叉排序树");
     15         b.infixOrder();// 1,3,5,7,10,12
     16         
     17         System.out.println("删除叶子节点2");//2,5,9,12
     18         //删除叶子节点
     19         b.delNode(2);
     20         b.infixOrder();
     21         
     22         //删除只有一颗子树的节点
     23         System.out.println("删除子节点1");
     24         b.delNode(1);
     25         b.infixOrder();
     26         
     27         //删除有两颗子树的节点
     28         System.out.println("删除子节点7");
     29         b.delNode(7);
     30         b.infixOrder();
     31     }
     32 
     33 }
     34 
     35 class BinarySortTree {
     36     private Node root;
     37 
     38     public Node getRoot() {
     39         return root;
     40     }
     41 
     42     // 查找要删除的节点
     43     public Node search(int value) {
     44         if (root == null) {
     45             return null;
     46         } else {
     47             return root.search(value);
     48         }
     49     }
     50 
     51     // 查找要删除节点的父节点
     52     public Node searchParent(int value) {
     53         if (root == null) {
     54             return root;
     55         } else {
     56             return root.searchParent(value);
     57         }
     58     }
     59     /**
     60      * 1.返回以node为根节点的二叉排序树的最小节点的值
     61      * 2.删除以node为根节点的二叉排序树的最小节点的值
     62      * @param node 传入的节点,当作二叉排序树的根节点
     63      * @return 返回以node为根节点的二叉排序树的最小节点的值
     64      */
     65     public int delRightTreeMin(Node node) {
     66         Node target=node;
     67         //循环查找的左节点,会找到最小值
     68         while(target.left!=null){
     69             target=target.left;
     70         }
     71         //这是target指向了最小节点
     72         //删除最小节点
     73         delNode(target.value);
     74         return target.value;
     75     }
     76     // 删除节点
     77     public void delNode(int value) {
     78         if (root == null) {
     79             return;
     80         } else {
     81             //找到要删除的节点targetNode;
     82             Node targetNode = root.search(value);
     83             if(targetNode==null) return;//如果没有找到该接待你
     84             //如果当前这颗二叉排序树只有一个节点
     85             if(root.left==null&&root.right==null) {
     86                 root=null;
     87                 return;
     88             }
     89             //找到targetNode的父节点
     90             Node parent = root.searchParent(value);
     91             //如果删除的节点是叶子节点
     92             if(targetNode.left==null&&targetNode.right==null) {
     93                 if (parent.left!= null&&parent.left.value==value) {//判断targetNode是父节点的左子节点还是右子节点
     94                     parent.left = null;
     95                 } else if(parent.right!=null&&parent.right.value==value){//是右子节点
     96                     parent.right = null;
     97                 }
     98             }else if(targetNode.left!=null&&targetNode.right!=null) {//targetNode有左子树和右子树
     99                 int minVal=delRightTreeMin(targetNode.right);
    100                 targetNode.value=minVal;
    101             }else {//删除只有一颗子树的节点
    102                 //如果要删除的节点有左子节点
    103                 if(targetNode.left!=null) {
    104                     if(parent!=null) {
    105                         if (parent.left.value == value) {// targetNode是parent的左子节点
    106                             parent.left = targetNode.left;
    107                         } else {// targetNode是parent的右子节点
    108                             parent.right = targetNode.left;
    109                         }
    110                     }else {
    111                         root=targetNode.left;
    112                     }    
    113                 }else {
    114                     if(parent!=null) {
    115                         // 如果要删除的节点有右子节点
    116                         if (parent.left.value == value) {// targetNode是parent的左子节点
    117                             parent.left = targetNode.right;
    118                         } else {// targetNode是parent的右子节点
    119                             parent.right = targetNode.right;
    120                         }
    121                     }else {
    122                         root=targetNode.right;
    123                     }
    124                     
    125                 }
    126             }    
    127         }
    128     }
    129 
    130     // 添加节点的方法
    131     public void add(Node node) {
    132         if (root == null) {
    133             root = node;// 如果root为空,直接让root指向node
    134         } else {
    135             root.add(node);
    136         }
    137     }
    138 
    139     // 重载
    140     public void infixOrder() {
    141         this.infixOrder(root);
    142     }
    143 
    144     // 中序遍历方法
    145     public void infixOrder(Node root) {
    146         if (root == null) {
    147             System.out.println("树为空,无法遍历");
    148         } else {
    149             root.infixOrder();
    150         }
    151     }
    152 }
    153 
    154 class Node {
    155     int value;
    156     Node left;
    157     Node right;
    158     public Node(int value) {
    159         this.value = value;
    160     }
    161 
    162     @Override
    163     public String toString() {
    164         return "Node [value=" + value + "]";
    165     }
    166 
    167     // 查找要删除的节点
    168     /**
    169      * 
    170      * @param value 希望删除的节点的值
    171      * @return 找到返回,没有返回null
    172      */
    173     public Node search(int value) {
    174         if (value == this.value) {
    175             return this;
    176         } else if (value < this.value) {// 如果查找的值小于当前节点,向左子树递归查找
    177             if (this.left == null) {
    178                 return null;
    179             }
    180             return this.left.search(value);
    181         } else {// 如果查找的值不小于当前节点,向右子树递归查找
    182             if (this.right == null) {
    183                 return null;
    184             }
    185             return this.right.search(value);
    186         }
    187     }
    188 
    189     // 查找要删除节点的父节点
    190     /**
    191      * 
    192      * @param value 要找到的节点的值
    193      * @return 找到返回的是要删除节点的父节点的值,否则返回null
    194      */
    195     public Node searchParent(int value) {
    196         // 如果当前节点是要删除节点的父节点,就返回
    197         if ((this.left != null && this.left.value == value) || (this.right != null && this.right.value == value)) {
    198             return this;
    199         } else {
    200             // 如果查找的值小于当前节点的值,并且当前节点的左子节点不为空
    201             if (value < this.value && this.left != null) {
    202                 return this.left.searchParent(value);// 向左子树递归查找
    203             } else if (value >= this.value && this.right != null) {
    204                 return this.right.searchParent(value);// 向右子树递归查找
    205             } else {
    206                 return null;// 没有找到父节点
    207             }
    208         }
    209     }
    210 
    211     // 添加节点的方法
    212     // 递归的形式添加节点,注意需要满足二叉排序树的要求
    213     public void add(Node node) {
    214         if (node == null) {
    215             return;
    216         }
    217         // 判断传入的节点的值,和当前子树的根节点的值关系
    218         if (node.value < this.value) {
    219             // 如果当前节点的左子节点为null
    220             if (this.left == null) {
    221                 this.left = node;
    222             } else {// 递归向左子树添加
    223                 this.left.add(node);
    224             }
    225         } else {
    226             // 如果当前节点的右子节点为null
    227             if (this.right == null) {
    228                 this.right = node;
    229             } else {// 递归向右子树添加
    230                 this.right.add(node);
    231             }
    232         }
    233     }
    234 
    235     // 中序遍历二叉树
    236     public void infixOrder() {
    237         if (this.left != null) {
    238             this.left.infixOrder();
    239         }
    240         System.out.println(this);
    241         if (this.right != null) {
    242             this.right.infixOrder();
    243         }
    244     }
    245 }
  • 相关阅读:
    React 组件
    React JSX
    React基础
    equals和hashCode详解
    Hibernate 二级缓存配置
    如何正确地停止一个线程?
    常见的异常以及常用的包,类,及其接口。
    5.水果
    Java -- Web前端面试题及答案(需更深入了解)
    微信access_token请求之简单缓存方法封装
  • 原文地址:https://www.cnblogs.com/ERFishing/p/11372588.html
Copyright © 2011-2022 走看看