二叉排序树(java)

二叉排序树

binary sort tree,对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大。

这个函数写在Node类中,但是需要使用Tree的类来调用

排序树增加节点的思想:

  1. 如果新加入node的值比当前节点小
    1. 当前节点的left为空,node设置为left
    2. 当前节点的left不为空,使用当前节点的left递归调用
  2. 如果新加入node的值比当前节点大
    1. 当前节点的right为空,node设置为right
    2. 当前节点的right不为空,使用当前节点的right递归调用

排序树删除节点的思想:

删除节点有三种情况

  1. 删除叶子节点
  2. 删除只有一颗子树的节点
  3. 删除有两颗子树的节点

思路分析:

  1. 删除叶子节点
    1. 先找到要删除的节点
    2. 找到要删除节点的parent
    3. 确定要删除的是parent的左子节点还是右子节点,进行parent.left = null或parent.right = null
  2. 删除只有一颗子树的节点
    1. 找到要删除的节点
    2. 找到要删除节点的父节点
    3. 确定要删除的targetnode是左子节点还是右子节点
    4. 判断targetnode有左子节点还是有右子节点
      1. 如果targetnode是parent的左子节点且targetnode有左子节点,parent.left = targetnode.left
      2. 如果targetnode是parent的左子节点且targetnode有右子节点,parent.left = targetnode.right
      3. 如果targetnode是parent的右子节点且targetnode有左子节点,parent.right = targetnode.left
      4. 如果targetnode是parent的右子节点且targetnode有右子节点,parent.right = targetnode.right
  3. 删除有两颗子树的节点
    1. 找到要删除的点
    2. 找到要删除点的parent
    3. 从targetnode的右子树找到最小的节点
    4. 用一个临时temp将最小节点保存,并删除最小节点
    5. targetNode.value = temp;

代码思路分析:

需要添加的函数:

在Node类

  • 添加search方法,返回要删除的节点

    • 使用递归调用的思路,首先判断当前节点是否为目标节点
    • 如果不是,就向左遍历,向右遍历
  • 添加searchParent方法,返回要删除节点的父节点

    • 使用递归调用的思路,首先判断是否为目标节点(左子节点不为空且左子节点的值为value 或者 右子节点不为空且右子节点的值为value)
    • 如果不是,向左遍历,向右遍历,如果还找不到,返回null

在二叉排序树类

  • 创建search方法,调用search方法
  • 创建searchParent方法,调用searchParent方法
  • 创建删除二叉排序树的最小节点的方法,并返回最小节点的值
    • 使用循环查找的方法,找到最左端的子树
  • 创建删除节点的方法
    • 首先取出要找到的节点(如果没找到则return,如果二叉树只有一个节点,则删除后return)
    • 找到targetNode的父节点
    • 判断 1. 如果删除的是叶子节点——判断这个节点是左子节点还是右子节点,删除
    • 判断 2. 如果删除的是有两颗子树的节点——找到要删除节点的右子树的最小子节点,并使targetNode = 删去节点的值
    • 判断 3. 如果删除只有一颗子树的节点——判断targetnodeParent的左子节点是targetNode还是右子节点是targetNode
      1. 如果targetnode是parent的左子节点且targetnode有左子节点,parent.left = targetnode.left
      2. 如果targetnode是parent的左子节点且targetnode有右子节点,parent.left = targetnode.right
      3. 如果targetnode是parent的右子节点且targetnode有左子节点,parent.right = targetnode.left
      4. 如果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();
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值