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 }
原文地址:https://www.cnblogs.com/ERFishing/p/11372588.html