package dataStruct.二叉排序树;
public class 二叉排序树 {
public static void main(String[] args) {
Tree tree = new Tree();
int[] arr = {7,3,10,12,5,1,9,0};
for (int i = 0; i <arr.length ; i++) {
//循环创建对象
tree.add(new Node(arr[i]));
}
tree.delNode(7);
tree.delNode(3);
tree.delNode(5);
System.out.println(tree.getRoot());
// tree.midOrder();
tree.delNode(9);
tree.midOrder();
// tree.delNode(1);
// tree.delNode(10);
// tree.delNode(0);
// tree.midOrder();
}
}
class Tree {
Node root;
public Node getRoot(){
return root;
}
public Tree(Node root) {
this.root = root;
}
public Tree() {
}
public void add(Node node){
if (root == null){
root = node;
}else {
root.add(node);
}
}
public void midOrder(){
if (root != null){
root.midOrder();
}else {
System.out.println("树为空");
}
}
//查找要删除的节点
public Node search(int val){
if (this.root == null){
return null;
}else {
return root.search(val);
}
}
//查找父节点
public Node searchParent(Node node){
if (root == null){
return null;
}else {
return root.searchParent(node);
}
}
/**
* 功能:
* 当删除的节点有两课子树时,将要删除的节点当作根节点
* 找到子树的最小值,删除最小值,并返回最小值的值
* @param node 要删除的节点(传入后当作根节点)
* @return 返回子树的最小值
*/
public int delRightTreeMin(Node node){
Node target = node;
//循环的查找左节点,就会找到最小值
while (target.left != null){
target = target.left;
}
//此时,target就时最小节点,此时删除最小节点的值
delNode(target.val);
return target.val;
}
//删除节点
public void delNode(int val){
if (root == null){
return;
}else {
Node targetnode = root.search(val);
if (targetnode == null ){
return;
}
if (targetnode == root && targetnode.left == null && targetnode.right == null){
root = null;
return;
}
Node parent = searchParent(targetnode);
//要删除的节点是叶子节点
if (targetnode.left == null && targetnode.right == null){
if (targetnode == parent.left && parent.left != null){
parent.left = null;
}else if (parent.right != null && parent.right == targetnode ){
parent.right = null;
}
}
//删除右两棵子树的节点
else if (targetnode.left != null && targetnode.right != null){
int rightTreeMinVal = delRightTreeMin(targetnode.right);//在右子树中找最小值,用来顶替替要删除的节点
targetnode.val = rightTreeMinVal;//此时将右子树的最小值付给了要删除的节点
}
//删除you一棵子树的节点
else {
//如果要删除的节点有左子节点
if (targetnode.left != null) {
if(parent != null) {
//如果要删除的节点是parent的左子节点
if (parent.left.val == targetnode.val) {
parent.left = targetnode.left;
} else {
parent.right = targetnode.left;
}
}else {
root = targetnode.left;
}
}
//如果眼删除的节点有右子节点
else {//如果要删除的节点是parent的右子节点
if (parent != null){
if (parent.left.val == targetnode.val){
parent.left = targetnode.right;
}else {
parent.right = targetnode.right;
}
}else {
root = parent.right;
}
}
}
}
}
}
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){
if (this.right == null){
this.right = node;
}else {//右递归
this.right.add(node);
}
}else {
if (this.left == null){
this.left = node;
}else {
this.left.add(node);
}
}
}
//中序遍历
public void midOrder(){
if (this.left != null){
this.left.midOrder();
}
System.out.println(this.val);
if (this.right != null){
this.right.midOrder();
}
}
//查找要删除的节点
public Node search(int val){
if (this.val == val){
return this;
}else if (this.val > val){
//如果左子节点但为空
if (this.left != null) {
return this.left.search(val);
}
return null;
}else {
// 如果右子节点为空,return null;
if (this.right != null) {
return this.right.search(val);
}
return null;
}
}
//查找要删除的叶子节点的父节点
public Node searchParent(Node node){
//如果当前节点是眼删除节点的父节点,直接返回
if ((this.left != null && this.left.val == node.val) ||
(this.right != null && this.right.val == node.val)){
return this;
}else {
//如果this的左子节点不为空,并且左子节点的值比node的值大,就this.left.searchParent()向左递归
if(this.left != null && this.val >= node.val){
return this.left.searchParent(node);
}
//如果this的右子节点不为空,并且右子节点的值比node的值小,就this.right.searchParent()向右递归
else if (this.right != null && this.val <= node.val){
return this.right.searchParent(node);
}else {
return null;
}
}
}
//删除节点
/*
1.删除的叶子节点
(1).找到要删除节点targetNode和他的父节点parentNode(考虑是否存在父节点)
(2).判断targetNOde是父节点的左子节点还是右子节点
a.左子节点:parentNode.left = null;
b.左子节点:parent.right = null;
2.删除非叶子节点
(1).找到targetNode节点
A.如果targetNode只有左子树
a.在targetNode的左子树中找到最右叶子节点
b.最右叶子节点记作rightNode,找到rightNode的父节点parent
c.定义临时变量temp,temp = rightNode;
d.parent.right = null;将最右叶子节点删除
e.将temp节点赋给targetNOde,targetNode = temp;
B.如果targetNode只有右子树
a.在targetNode的右子树中找到最左叶子节点
b.最右叶子节点记作leftNode,找到leftNode的父节点parent
c.定义临时变量temp,temp = leftNode;
d.parent.right = null;将最右叶子节点删除
e.将temp节点赋给targetNOde,targetNode = temp;
C.如果targetNode有两个子树,重复B,在右子树中照最左叶子节点。
*/
}
运行结果: