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 }