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 }