二叉排序树
binary sort tree,对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大。
这个函数写在Node类中,但是需要使用Tree的类来调用
排序树增加节点的思想:
- 如果新加入node的值比当前节点小
- 当前节点的left为空,node设置为left
- 当前节点的left不为空,使用当前节点的left递归调用
- 如果新加入node的值比当前节点大
- 当前节点的right为空,node设置为right
- 当前节点的right不为空,使用当前节点的right递归调用
排序树删除节点的思想:
删除节点有三种情况
- 删除叶子节点
- 删除只有一颗子树的节点
- 删除有两颗子树的节点
思路分析:
- 删除叶子节点
- 先找到要删除的节点
- 找到要删除节点的parent
- 确定要删除的是parent的左子节点还是右子节点,进行parent.left = null或parent.right = null
- 删除只有一颗子树的节点
- 找到要删除的节点
- 找到要删除节点的父节点
- 确定要删除的targetnode是左子节点还是右子节点
- 判断targetnode有左子节点还是有右子节点
- 如果targetnode是parent的左子节点且targetnode有左子节点,parent.left = targetnode.left
- 如果targetnode是parent的左子节点且targetnode有右子节点,parent.left = targetnode.right
- 如果targetnode是parent的右子节点且targetnode有左子节点,parent.right = targetnode.left
- 如果targetnode是parent的右子节点且targetnode有右子节点,parent.right = targetnode.right
- 删除有两颗子树的节点
- 找到要删除的点
- 找到要删除点的parent
- 从targetnode的右子树找到最小的节点
- 用一个临时temp将最小节点保存,并删除最小节点
- targetNode.value = temp;
代码思路分析:
需要添加的函数:
在Node类
-
添加search方法,返回要删除的节点
- 使用递归调用的思路,首先判断当前节点是否为目标节点
- 如果不是,就向左遍历,向右遍历
-
添加searchParent方法,返回要删除节点的父节点
- 使用递归调用的思路,首先判断是否为目标节点(左子节点不为空且左子节点的值为value 或者 右子节点不为空且右子节点的值为value)
- 如果不是,向左遍历,向右遍历,如果还找不到,返回null
在二叉排序树类
- 创建search方法,调用search方法
- 创建searchParent方法,调用searchParent方法
- 创建删除二叉排序树的最小节点的方法,并返回最小节点的值
- 使用循环查找的方法,找到最左端的子树
- 创建删除节点的方法
- 首先取出要找到的节点(如果没找到则return,如果二叉树只有一个节点,则删除后return)
- 找到targetNode的父节点
- 判断 1. 如果删除的是叶子节点——判断这个节点是左子节点还是右子节点,删除
- 判断 2. 如果删除的是有两颗子树的节点——找到要删除节点的右子树的最小子节点,并使targetNode = 删去节点的值
- 判断 3. 如果删除只有一颗子树的节点——判断targetnodeParent的左子节点是targetNode还是右子节点是targetNode
- 如果targetnode是parent的左子节点且targetnode有左子节点,parent.left = targetnode.left
- 如果targetnode是parent的左子节点且targetnode有右子节点,parent.left = targetnode.right
- 如果targetnode是parent的右子节点且targetnode有左子节点,parent.right = targetnode.left
- 如果targetnode是parent的右子节点且targetnode有右子节点,parent.right = targetnode.right
代码
package com.tree;
public class binarySortTree {
public static void main(String[] args) {
int[] arr = {7, 3, 10, 12, 5, 1, 9};
SortTree Sorttree = new SortTree();
for (int i = 0; i < arr.length; i++) {
Sorttree.add(new Node_(arr[i]));
}
Sorttree.middleOrder();
//删除测试
System.out.println("删除测试~~~");
Sorttree.del(1);
Sorttree.middleOrder();
}
//创建树
static class SortTree {
private Node_ root;
public void add(Node_ node) {
if (root == null) {
root = node;
} else {
root.add(node);
}
}
//中序遍历
public void middleOrder() {
if (root != null) {
root.middleOrder();
} else {
System.out.println("null!!!");
}
}
//调用search方法
public Node_ search(int value) {
if (root == null) {
return null;
} else {
return root.search(value);
}
}
//调用searchParent
public Node_ searchParent(int value) {
if (root == null) {
return null;
} else {
return root.searchParent(value);
}
}
//寻找并删除最小子节点,返回最小子节点的值
public int delMin(Node_ node) {
Node_ target = node;
while (target.left != null) {
target = target.left;
}
del(target.value);
return target.value;
}
//删除节点
public void del(int value) {
Node_ targetNode = search(value);
if (targetNode == null) {
return;
}
if (root.left == null && root.right == null) {
root = null;
return;
}
Node_ targetNodeParent = searchParent(value);
//判断 1. 如果删除的是叶子节点——判断这个节点是左子节点还是右子节点,删除
if (targetNode.left == null && targetNode.right == null) {
if (targetNodeParent.left != null && targetNodeParent.left.value == value) {
targetNodeParent.left = null;
} else {
targetNodeParent.right = null;
}
} else if (targetNode.left != null && targetNode.right != null) {
//判断 2. 如果删除的是有两颗子树的节点——找到要删除节点的右子树的最小子节点,并使targetNode = 删去节点的值
int min = delMin(targetNode.right);
targetNode.value = min;
} else {
//判断 3. 如果删除只有一颗子树的节点——判断targetnodeParent的左子节点是targetNode还是右子节点是targetNode
if (targetNodeParent.left.value == targetNode.value) {
//目标节点是其父节点的左子节点
if (targetNode.left != null) {
targetNodeParent.left = targetNode.left;
} else {
targetNodeParent.left = targetNode.right;
}
} else {
//目标节点是其父节点的右子节点
if (targetNode.right != null) {
targetNodeParent.right = targetNode.right;
} else {
targetNodeParent.right = targetNode.left;
}
}
}
}
}
//创建节点
static class Node_ {
int value;
Node_ left;
Node_ right;
public Node_(int value) {
this.value = value;
}
public void add(Node_ node) {
if (node.value < this.value) {
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 Node_ search(int value) {
if (this.value == value) {
return this;
} else if (value < this.value) {
if (this.left == null) {
return null;
}
return this.left.search(value);
} else {
if (this.right == null) {
return null;
}
return this.right.search(value);
}
}
//找到要删除节点的父节点
public Node_ searchParent(int value) {
if ((this.left != null && this.left.value == value) || (this.right != null && this.right.value == value)) {
return this;
} else {
if (value < this.value && this.left != null) {
return this.left.searchParent(value);
} else if (value > this.value && this.right != null) {
return this.right.searchParent(value);
} else {
return null;
}
}
}
//中序遍历
public void middleOrder() {
if (this.left != null) {
this.left.middleOrder();
}
System.out.println(this.value);
if (this.right != null) {
this.right.middleOrder();
}
}
}
}