数据结构与算法 18 二叉排序树 创建、变量、删除

二叉排序树

Binary Search Tree

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

如果有相同的值,可以将该节点放在左子节点或右子节点


二叉排序树的创建和遍历

中序遍历二叉排序树

package tree.binarysearchtree;

public class BinarySearchTreeDemo01 {
    public static void main(String[] args) {
        int[] arr = {7,3,10,12,5,1,9};
        BinarySortTree binarySortTree = new BinarySortTree();
        // cyclical addition
        for (int i = 0; i < arr.length; i++) {
            binarySortTree.add(new Node(arr[i]));
        }
        System.out.println("infix order ");
        binarySortTree.infixOrder();

    }
}

// create binary search tree
class BinarySortTree{
    private Node root;
    // add
    public void add(Node node){
        if(root==null){
            root = node;
        } else{
            root.add(node);
        }
    }
    // traversal
    public void infixOrder(){
        if(root!=null){
            root.infixOrder();
        } else{
            System.out.println("can not traverse");
        }
    }
}


// create Node
class Node{
    int value;
    Node left;
    Node right;

    public Node(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }

    // add Node recursively
    public void add(Node node ){
        if(node == null){
            return;
        }
        // determine the relationship of node's value and
        // the value of the root node of the current subtree
        if(node.value<this.value){
            if(this.left==null){
                this.left = node;
            }else{ // 如果当前节点的左子树不为空,则向左递归添加node
                this.left.add(node);
            }
        } else{ // 添加的节点的值大于当前节点的值
            if(this.right==null){
                this.right = node;
            } else{
                this.right.add(node);
            }
        }
    }

    // infix order traversal
    public void infixOrder(){
        if(this.left!=null){
            this.left.infixOrder();
        }
        System.out.println(this.value);
        if(this.right!=null){
            this.right.infixOrder();
        }
    }
}

二叉树的删除

  1. 删除叶子节点

    • 先找到需要删除的节点 targetNode
    • 找到 targetNode 的父节点 parent(是否存在父节点)
    • 判断 targetNode 是 parent的左子节点还是右子节点
    • 根据前面的情况进行删除
    • 左子节点 parent.left = null;
    • 右子节点 parent.right = null;
  2. 删除只有一颗子树的节点

    • 先找到需要删除的节点 targetNode

    • 找到 targetNode 的父节点 parent(是否存在父节点)

    • 确定 targetNode 的子节点是左子节点还是右子节点

    • targetNode 是parent 的左子节点还是右子节点

    • 如果targetNode 的子节点是左子节点

      • 如果 targetNode 是parent 的左子节点

        parent.left = targetNode.left

      • 如果 targetNode 是parent 的右子节点

        Parent.right = targetNode.left

    • 如果targetNode 的子节点是左子节点

      • 如果 targetNode 是parent 的左子节点

        parent.left = targetNode.right

      • 如果 targetNode 是parent 的右子节点

        Parent.right = targetNode.right

  3. 删除有两颗子树的节点

    • 需要先找到要删除的节点 targetNode
    • 找到 targetNode 的父节点 parent
    • 从 targetNode 的右子树找到最小的节点(或左子树最大的值)
    • 用一个临时变量,保存最小节点的值
    • 删除该最小节点
    • targetNode.value = temp

  1. 找待删除的节点
// class Node
// find node wait for deleting

    /**
     *
     * @param value The value of node you wish to delete
     * @return if find it, return this node, or return null
     */
    public Node search(int value){
        if(value==this.value){ // find it
            return this;
        } else if(value<this.value){
            // if value smaller than current node, find it recursively to left side
            // if left node is null, return null
            if(this.left==null){
                return null;
            }
            return this.left.search(value);
        } else{
            // recursively search to right side
            if(this.right==null){
                return null;
            }
            return this.right.search(value);
        }
    }
  1. 找待删除节点的父节点
// class Node
// find the parent node of the node to be deleted

    /**
     *
     * @param value the value of node you want to find
     * @return the parent node of the node to be deleted, if not found, return null
     */
    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 is smaller than current value and left node of current node is not null
            // recursively find left side
            if(value<this.value && this.left!=null){
                this.left.searchParent(value);
            } else if(value >= this.value && this.right!=null){
                this.right.searchParent(value);
            } else{
                return null;
            }
        }
    }
  1. 封装查找节点和父节点的方法
// class BinarySortTree
// find node to be deleted
    public Node search(int value){
        if(root==null){
            return null;
        } else{
            return root.search(value);
        }
    }

    // find parent node
    public Node searchParent(int value){
        if(root==null){
            return null;
        } else{
            return root.searchParent(value);
        }
    }
  1. 删除节点
    • 根节点是否为空
    • 找到待删除节点(判断是否为空 以及 树是否只有根节点一个节点)
    • 找待删除节点的父节点
    • 删除叶子节点
    • 删除有一颗子树的节点
    • 删除有两颗子树的节点
      • 找该节点右子树的最小值 或 左子树的最大值
      • 找到以node为根节点的子树的最小值 public int delRightTreeMin(Node node){} 删除该最小值的节点并返回该最小值
// class BinarySortTree
// 1. return the min value of BST with node as the root
    // 2. delete the smallest node of BST with node as the root

    /**
     *
     * @param node Incoming node ( as root node of BST)
     * @return the min value of BST with node as the root
     */
    public int delRightTreeMin(Node node){
        Node target = node;
        // cyclic search left node to find the minimum node
        while(target.left!=null){
            target = target.left;
        }
        // now target is the minimum value
        delete(target.value);
        return target.value;
    }
 // delete node
    public void delete(int value){
        if (root==null){
            return;
        } else{
            // 1. find targetNode (node to be deleted)
            Node targetNode = search(value);
            if(targetNode==null){
                return;
            }
            // if this tree only have one node
            if(root.left==null && root.right==null){
                root = null;
                return;
            }
            // find parent node of targetNode
            Node parent = searchParent(value);

            // if node to be deleted is leaf node
            if(targetNode.left == null && targetNode.right == null){
                // determine target node is right or left node of parent node
                if(parent.left!=null && parent.left.value == value){
                    parent.left = null;
                } else if(parent.right != null && parent.right.value == value){
                    parent.right = null;
                }
            } else if(targetNode.left != null && targetNode.right != null){
                // delete node who has two subtrees
                // find the min value of right tree
                int min = delRightTreeMin(targetNode.right);
                targetNode.value = min;

            } else{ // delete node only with one subtree
                // if node to be deleted has left node
                if(targetNode.left!=null){
                    // if targetNode is left node of parent node
                    if(parent.left.value == value){
                        parent.left = targetNode.left;
                    } else{ // target node is right node of parent node
                        parent.right = targetNode.left;
                    }
                } else{ // node to be deleted has right node
                    // if target node is left node of parent node
                    if(parent.left.value == value){
                        parent.left = targetNode.right;
                    } else{
                        parent.right = targetNode.right;
                    }
                }

            }
        }
    }

test

public static void main(String[] args) {
        int[] arr = {7,3,10,12,5,1,9,2};
        BinarySortTree binarySortTree = new BinarySortTree();
        // cyclical addition
        for (int i = 0; i < arr.length; i++) {
            binarySortTree.add(new Node(arr[i]));
        }
        System.out.println("infix order ");
        binarySortTree.infixOrder();

        System.out.println("\nafter deletion");
        // test delete leaf node
        binarySortTree.delete(7);
        binarySortTree.infixOrder();

output

infix order 
1 2 3 5 7 9 10 12 
after deletion
1 2 3 5 9 10 12 

完整代码

package tree.binarysearchtree;

import java.util.function.Predicate;

public class BinarySearchTreeDemo01 {
    public static void main(String[] args) {
        int[] arr = {7,3,10,12,5,1,9,2};
        BinarySortTree binarySortTree = new BinarySortTree();
        // cyclical addition
        for (int i = 0; i < arr.length; i++) {
            binarySortTree.add(new Node(arr[i]));
        }
        System.out.println("infix order ");
        binarySortTree.infixOrder();

        System.out.println("\nafter deletion");
        // test delete leaf node
        binarySortTree.delete(7);
        binarySortTree.infixOrder();



    }
}

// create binary search tree
class BinarySortTree{
    private Node root;

    // find node to be deleted
    public Node search(int value){
        if(root==null){
            return null;
        } else{
            return root.search(value);
        }
    }

    // find parent node
    public Node searchParent(int value){
        if(root==null){
            return null;
        } else{
            return root.searchParent(value);
        }
    }

    // 1. return the min value of BST with node as the root
    // 2. delete the smallest node of BST with node as the root

    /**
     *
     * @param node Incoming node ( as root node of BST)
     * @return the min value of BST with node as the root
     */
    public int delRightTreeMin(Node node){
        Node target = node;
        // cyclic search left node to find the minimum node
        while(target.left!=null){
            target = target.left;
        }
        // now target is the minimum value
        delete(target.value);
        return target.value;
    }


    // delete node
    public void delete(int value){
        if (root==null){
            return;
        } else{
            // 1. find targetNode (node to be deleted)
            Node targetNode = search(value);
            if(targetNode==null){
                return;
            }
            // if this tree only have one node
            if(root.left==null && root.right==null){
                root = null;
                return;
            }
            // find parent node of targetNode
            Node parent = searchParent(value);

            // if node to be deleted is leaf node
            if(targetNode.left == null && targetNode.right == null){
                // determine target node is right or left node of parent node
                if(parent.left!=null && parent.left.value == value){
                    parent.left = null;
                } else if(parent.right != null && parent.right.value == value){
                    parent.right = null;
                }
            } else if(targetNode.left != null && targetNode.right != null){
                // delete node who has two subtrees
                // find the min value of right tree
                int min = delRightTreeMin(targetNode.right);
                targetNode.value = min;

            } else{ // delete node only with one subtree
                // if node to be deleted has left node
                if(targetNode.left!=null){
                    // if targetNode is left node of parent node
                    if(parent.left.value == value){
                        parent.left = targetNode.left;
                    } else{ // target node is right node of parent node
                        parent.right = targetNode.left;
                    }
                } else{ // node to be deleted has right node
                    // if target node is left node of parent node
                    if(parent.left.value == value){
                        parent.left = targetNode.right;
                    } else{
                        parent.right = targetNode.right;
                    }
                }

            }
        }
    }


    // add
    public void add(Node node){
        if(root==null){
            root = node;
        } else{
            root.add(node);
        }
    }
    // traversal
    public void infixOrder(){
        if(root!=null){
            root.infixOrder();
        } else{
            System.out.println("can not traverse");
        }
    }
}


// create Node
class Node{
    int value;
    Node left;
    Node right;

    public Node(int value) {
        this.value = value;
    }

    // find node wait for deleting

    /**
     *
     * @param value The value of node you wish to delete
     * @return if find it, return this node, or return null
     */
    public Node search(int value){
        if(value==this.value){ // find it
            return this;
        } else if(value<this.value){
            // if value smaller than current node, find it recursively to left side
            // if left node is null, return null
            if(this.left==null){
                return null;
            }
            return this.left.search(value);
        } else{
            // recursively search to right side
            if(this.right==null){
                return null;
            }
            return this.right.search(value);
        }
    }

    // find the parent node of the node to be deleted

    /**
     *
     * @param value the value of node you want to find
     * @return the parent node of the node to be deleted, if not found, return null
     */
    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 is smaller than current value and left node of current node is not null
            // recursively find left side
            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;
            }
        }
    }


    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }

    // add Node recursively
    public void add(Node node ){
        if(node == null){
            return;
        }
        // determine the relationship of node's value and
        // the value of the root node of the current subtree
        if(node.value<this.value){
            if(this.left==null){
                this.left = node;
            }else{ // 如果当前节点的左子树不为空,则向左递归添加node
                this.left.add(node);
            }
        } else{ // 添加的节点的值大于当前节点的值
            if(this.right==null){
                this.right = node;
            } else{
                this.right.add(node);
            }
        }
    }

    // infix order traversal
    public void infixOrder(){
        if(this.left!=null){
            this.left.infixOrder();
        }
        System.out.print(this.value+" ");
        if(this.right!=null){
            this.right.infixOrder();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值