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 }
  • 相关阅读:
    linux驱动开发学习一:创建一个字符设备
    如何高效的对有序数组去重
    找到缺失的第一个正整数
    .NET不可变集合已经正式发布
    中国人唯一不认可的成功——就是家庭的和睦,人生的平淡【转】
    自己动手搭建 MongoDB 环境,并建立一个 .NET HelloWorld 程序测试
    ASP.NET MVC 中如何用自定义 Handler 来处理来自 AJAX 请求的 HttpRequestValidationException 错误
    自己动手搭建 Redis 环境,并建立一个 .NET HelloWorld 程序测试
    ServiceStack 介绍
    一步一步实战扩展 ASP.NET Route,实现小写 URL、个性化 URL
  • 原文地址:https://www.cnblogs.com/ERFishing/p/11372588.html
Copyright © 2011-2022 走看看