删除思路
代码选择先实现情况一
package tree;
//二叉搜索树,二叉排序树
public class BinarySortTreeDemo {
public static void main(String[] args) {
int[] arr = {7,3,10,12,5,1,9};
BinarySortTree binarySortTree = new BinarySortTree();
//循环添加节点到树中
for(int i=0; i<arr.length;i++) {
binarySortTree.add(new Node(arr[i]));
}
//中序遍历二叉排序树
System.out.println("中序遍历二叉排序树");
binarySortTree.infixOrder();//1,3,5,7,9,10,12
// binarySortTree.delNode(12);
// System.out.println();
// binarySortTree.infixOrder();
}
}
class BinarySortTree{
private Node root;
//定义添加方法
public void add(Node node) {
if(root == null) {
root = node;
}else {
root.add(node);
}
}
//中序遍历方法
public void infixOrder() {
if(root != null) {
root.infixOrder();
}else {
System.out.println("二叉排序树为空");
}
}
//在定义删除方法前,先定义两个查找方法
//查找要删除的节点方法
public Node searchNode(int val) {
if(root == null) {
return null;
}else {
return root.searchNode(val);
}
}
//查找要删除的节点的父节点方法
public Node searchParent(int val) {
if(root == null) {
return null;
}else {
return root.searchParent(val);
}
}
//删除节点方法
public void delNode(int val) {
if(root == null) {
return;
}else {
//要删除的节点
Node targetNode = searchNode(val);
if(targetNode == null) {
return;
}
//如果删除的是root节点
if(root.left == null && root.right == null) {//执行这句话时,表示上面要删除的节点在树里有,那么只能是root节点。
root = null;
return;
}
//找到targetNode的父节点
Node parent = searchParent(val);
//如果要删除的节点是叶子节点
if(targetNode.left == null && targetNode.right == null) {
//判断targetNode是parent的左还是右子节点
if(parent.left.val == targetNode.val) {//左
parent.left = null;
}else if(parent.right.val == targetNode.val) {
parent.right = null;
}
}else if(targetNode.left != null && targetNode.right != null) {//删除有两颗子树的节点
//当有两个子节点时,我们可以定一个策略,比如在该节点的左子树找最大值或右子树找最小
//这里找的是右最小
int minVal = delRightTreeMin(targetNode);
targetNode.val = minVal;
}else {//删除只有一颗子树的节点
//如果要删除的节点有左节点
if(targetNode.left != null) {
if(parent != null) {
//如果targetNode 是parent的左子节点
if(val == parent.left.val) {
parent.left = targetNode.left;
}else {
parent.right = targetNode.left;
}
}else {
root = targetNode.left;
}
}else {
if(parent != null) {
if(val == parent.left.val) {
parent.left = targetNode.right;
}else {
parent.right = targetNode.right;
}
}else {
root = targetNode.right;
}
}
}
}
}
//找值,1返回以node节点为根节点的最小节点的值2,删除最小节点
public int delRightTreeMin(Node node) {
Node target = node;
while(target.left != null) {//找右子树最小,就要向左遍历
target = target.left;
}
//将之删除
delNode(target.val);
return target.val;
}
}
//定义节点
class Node{
int val;
Node left;
Node right;
public Node(int val) {
this.val = val;
}
@Override
public String toString() {
return "Node [val=" + val + "]";
}
//添加节点方法,递归添加
public void add(Node node) {
if(node == null) {
return;
}
//判断传入的值,和当前子树根节点值的关系
if(node.val < this.val) {
//如果当前节点左子节点为null
if(this.left == null) {
this.left = node;
}else {
//递归向左子树添加
this.left.add(node);
}
}else {//与上面相反
if(this.right == null) {
this.right = node;
}else {
this.right.add(node);
}
}
}
//中序遍历方法
public void infixOrder() {
if(this.left != null) {
this.left.infixOrder();
}
System.out.println(this);
if(this.right != null) {
this.right.infixOrder();
}
}
//在定义删除方法前,先定义两个查找方法,节点中就不定义删除方法了
//查找要删除的节点
public Node searchNode(int val) {
if(this.val == val) {//找到当前节点
return this;
}else if(this.val > val) {//当前节点值大于查找值,向左递归查找
if(this.left == null) {
return null;
}else {
return this.left.searchNode(val);
}
}else {
if(this.right == null) {//当前节点值小于查找值,向右递归查找
return null;
}
return this.right.searchNode(val);
}
}
//查找要删除节点的父节点
public Node searchParent(int val) {
//如果当前节点就是要删除节点的父节点
if(this.left !=null && this.left.val == val ||
this.right != null && this.right.val == val) {
return this;
}else {
if(this.left != null && this.val > val) {
return this.left.searchParent(val);
}else if(this.right != null && this.val < val) {
return this.right.searchParent(val);
}else {
return null;
}
}
}
}
,和情况三,最后解决情况二。