二叉排序树说明:
若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
左、右子树也分别为二叉排序树;
如果有相等的值,可以放在右边或左边(经量避免相同的值);
示意图:[ 5, 8, 9, 4, 1, 3, 2 ,6, 7];
删除思路:我建议可以不看思路,我写的有点乱,最快的方法就是代码赋值粘贴,debug走一走(代码上都有注释这个很容易理解,因为是在代码中把注释拆分开了),如果不懂二叉树的同学建议先学二叉树,不然会很懵
1)删除一个叶子节点;
1.1)首先找到需要删除的节点 node;
1.2)找到 node 的父节点 parent;
1.3)然后判断 node 是 parent 的左节点还是右节点,如果是左节点直接置空 parent.left = null;如果是右节点,则置空右节点;2)删除一个带有一个节点的非叶子节点;比如(3)
2.1)首先找到需要删除的节点 node;
2.2)找到 node 的父节点 parent;
2.3)判断 node 是有左节点还是右节点;
2.4)判断 parent 的左节点如果不等于空,并且 parent 的左节点等于 node 说明需要删除的节点是parent的左节点;
2.5)如果 node 有左节点则让 parent.left = node.left;如果 node 有右节点则让 parent.left = right;
2.6)如果 node 有右节点则反之;3)删除一个二叉树;
3.1)首先找到需要删除的节点 node;
3.2)找到 node 的父节点 parent;
3.3)找到以 node 的右节点为根节点最小的节点,用示意图比较,删除8,就找到以9 为根节点最小的节点,9 没有左节点,所以 9 就是最小的节点;
3.4)将 9 赋值给node,完成删除二叉树;
代码实现二叉排序树:
public class SortTreeDemo {
public static void main(String[] args){
int arr[] = {8,9,1,6,7,5,4,3,2};
Tree tree = new Tree();
for (int i = 0; i <arr.length ; i++) {
tree.insert(new Node(arr[i]));
}
tree.inOrder();
System.out.println();
tree.findDeleteNode(6);
tree.findDeleteNode(5);
tree.findDeleteNode(8);
tree.inOrder();
}
}
class Tree{
private Node root; // 根节点
/**
* @param node 传入的节点 (当作二叉排序树的根节点)
* @return 返回以node为根节点的二叉排序树最小节点
*/
public int delRightTreeMin(Node node){
Node target = node;
// 循环找左子节点,找到最小左子节点为止;
while (target.left != null) {
target = target.left;
}
// 这是target指向最小节点
// 删除最小节点
findDeleteNode(target.value);
// 然后返回最小节点值
return target.value;
}
// 删除节点
public void findDeleteNode(int value){
if (root == null){
System.out.println("com.zhang.tree.Tree.findDeleteNode:跟节点为空");
}else{
// 需要删除的节点
Node node = root.findNode(value);
if (node == null){
System.out.println("没有需要删除的节点");
}
// 因为删除节点,可能存在没有父节点的情况
// 比如开始就要删除root
if (root.left == null && root.right == null){
root = null;
return;
}
// 需要删除节点的父节点
Node parent = root.findParent(value);
// node:需要删除的节点
// 1、node左右节点都为空,直接删除即可
if (node.left == null && node.right == null){
// 如果需要删除节点的父节点,左节点不为空,并且等于需要删除的节点,直接删除
if (parent.left != null && parent.left.value == value){
parent.left = null;
}else if (parent.right != null){
parent.right = null;
}
}else if (node.left != null && node.right != null){ // 2、node左右节点都不为空
// 找到node右子树的最小节点,然后删除掉,
// 在返回最小节点
int min = delRightTreeMin(node.right);
// min现在就是node右子树的最小节点
// 赋值给node,完成删除node
node.value = min;
}else { // 3、node左右节点有一个节点为空
if (node.left != null){ // 说明node有左子节点
// 判断node是node父节点的左子节点还是右子节点
if (parent.left != null && parent.left.value == value){
// 是左节点
parent.left = node.left;
}else{
// 是右节点
parent.right = node.left;
}
}else { // 说明node有右子节点
if (parent.left != null && parent.left.value == value){
// 是左节点
parent.right = node.right;
}else{
// 是右节点
parent.right = node.right;
}
}
}
}
}
// 插入节点
public void insert(Node node){
if (root == null){
this.root = node;
return;
}
root.insert(node);
}
// 中序遍历
public void inOrder(){
if (root != null){
root.inOrder();
}else {
System.out.println("com.zhang.tree.Tree.inOrder:二叉排序树为空");
}
}
}
class Node{
int value;
Node left;
Node right;
public Node(int value){
this.value = value;
}
// 遍历
public void inOrder(){
if (this.left != null){
this.left.inOrder();
}
System.out.println(this);
if (this.right != null){
this.right.inOrder();
}
}
/**
* 查找需要删除的节点
* @param value 希望删除节点的value
* @return 返回需要删除的节点
*/
public Node findNode(int value){
// 首先判断当前节点是否是需要删除的节点
if (this.value == value){
return this;
}else if (this.value > value){ // value小于当前节点
// 当前节点右子节点等于空,直接返回
if (this.left == null){
return null;
}
// 左递归查找
return this.left.findNode(value);
}else { // value大于当前节点
// 当前节点右子节点等于空,直接返回
if (this.right == null){
return null;
}
// 右递归查找
return this.right.findNode(value);
}
}
/**
* 查找需要删除的父节点
* @param value 希望删除的节点的value
* @return 返回需要删除的父节点
*/
public Node findParent(int value){
// 如果当前节点的左右子节点,有一个是需要删除的节点,则返回当前节点
if ((this.left != null && this.left.value == value) ||
(this.right != null && this.right.value == value)){
return this;
}else {
// 当前节点的左子节点大于需要删除节点,则左递归查找
if (this.left != null && this.value > value){
return this.left.findParent(value);
}else if (this.right != null && this.value <= value){
return this.right.findParent(value);
}
}
// 没有找到父节点
return null;
}
// 插入
public void insert(Node node){
if (node == null){
System.out.println("com.zhang.tree.Tree.insert:插入数据不可能为空");
return;
}
// 规则:value值小的放左边,大的或等于放右边
if (node.value < this.value){ // 小于
if (this.left != null){ // 如果不等于空,就左递归
this.left.insert(node);
}else{ // 为空,直接讲node赋值到当前节点的左子节点
this.left = node;
}
}else { // 大于等于
if (this.right != null){
this.right.insert(node);
}else {
this.right = node;
}
}
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
'}';
}
}
后续会发布二叉树教学,如果觉得可以请点一波赞;点赞就是对我最好的鼓励谢谢大家;