排序二叉树(BST)

描述

英文全称:Binary Sort Tree,它满足以下3个特点:
1.一个节点的左节点的值,一定小于它本身节点的值
2.一个节点的右节点的值,一定大于它本身节点的值
3.一个节点的左右子树,都属于排序二叉树

相关操作

1、树节点构造

class Node {
    int data;
    Node left;
    Node right;

    public Node() {
    }

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

2、遍历树(中序遍历)

	/**
     * 中序遍历
     *
     * @param node
     */
    private void travel(Node node) {
        if (node == null) {
            return;
        }
        travel(node.left);
        System.out.print(node.data + " ");
        travel(node.right);
    }

3、添加节点

	/**
     * 添加节点
     *
     * @param data
     */
    private void add(int data) {
        Node newNode = new Node(data);
        if (root == null) {
            root = newNode;
            return;
        }

        Node current = root;
        while (true) {
            if (current.data > data) {
                if (current.left == null) {
                    current.left = newNode;
                    return;
                }
                current = current.left;
            } else {
                if (current.right == null) {
                    current.right = newNode;
                    return;
                }
                current = current.right;
            }
        }
    }

4、寻找某个节点

	/**
     * 寻找某个节点
     *
     * @param value
     * @return
     */
    private Node findNode(int value) {
        Node current = root;
        while (true) {
            if (current == null) {
                return null;
            }
            if (current.data == value) {
                return current;
            }
            if (current.data > value) {
                current = current.left;
            } else {
                current = current.right;
            }
        }
    }

5、删除操作

除了空树待删除节点不存在以外,删除操作有以下3中情况:

  • 待删除节点是叶子结点

直接删除

  • 待删除节点拥有左子树或者右子树

直接删除,并向上拼接左子树或者右子树

  • 待删除节点既有左子树又有右子树

找到中序排序下的前驱或者后驱节点(即是中序排序后,前后节点;这里寻找后节点,即是后驱节点),用它代替待删除节点

	/**
     * 删除某个节点(三种情况)
     *
     * @param value
     * @return
     */
    private Node del(int value) {
        //空树
        if (root == null) {
            return null;
        }
        Node target = findNode(value);
        Node targetParent = findNodeParent(value);
        if (target == null) {
            return null;
        } else {
            //找到了待删除节点
            //情况1:待删除节点没有左右子树 -> 直接删除
            if (target.left == null && target.right == null) {
                if (targetParent == null) {
                    //表示没有子树和父节点,整棵树只有待删除节点一个节点,直接置空
                    root = null;
                    return target;
                } else {
                    //有父节点,但有可能是该父节点的左或右子节点
                    if (targetParent.left == null) {
                        targetParent.right = null;
                        return target;
                    } else {
                        targetParent.left = null;
                        return target;
                    }
                }

            } else if (target.left == null || target.right == null) {
                //情况2:待删除节点有左子树或者右子树 -> 删除待删除节点,将待删除节点的左子树或右子树嫁接到它的父节点
                if (target.left == null) {
                    if (targetParent == null) {
                        root = target.right;
                        return target;
                    }
                    if (targetParent.left != null && target.left.data == value) {
                        targetParent.left = target.right;
                        return target;
                    } else {
                        targetParent.right = target.right;
                        return target;
                    }
                } else {
                    if (targetParent == null) {
                        root = target.left;
                        return target;
                    }
                    if (targetParent.left != null && target.left.data == value) {
                        targetParent.left = target.left;
                        return target;
                    } else {
                        targetParent.right = target.left;
                        return target;
                    }
                }
            } else {
                //情况3:待删除节点既有左子树又有右子树 -> 找到中序排序下的前驱或者后驱节点(即是中序排序后,前后节点;这里寻找后节点,即是后驱节点),用它代替待删除节点
                Node finalLeft = findFinalLeft(target);
                int data = finalLeft.data;
                del(data);
                target.data = data;
            }
        }
        return null;
    }

完整代码

package com.cxf.datastructures.binarytree;

/**
 * 排序二叉树
 */
public class BinarySortTree {

    public static void main(String[] args) {
        BinarySortTree binarySortTree = new BinarySortTree();
        binarySortTree.add(3);
        binarySortTree.add(1);
        binarySortTree.add(6);
        binarySortTree.add(5);
        binarySortTree.add(2);
        binarySortTree.add(9);
        binarySortTree.add(7);

        System.out.println("删除前: ");
        binarySortTree.travel(binarySortTree.root);

        binarySortTree.del(6);
        System.out.println();

        System.out.println("删除后: ");
        binarySortTree.travel(binarySortTree.root);
    }

    private Node root;

    /**
     * 中序遍历
     *
     * @param node
     */
    private void travel(Node node) {
        if (node == null) {
            return;
        }
        travel(node.left);
        System.out.print(node.data + " ");
        travel(node.right);
    }

    /**
     * 添加节点
     *
     * @param data
     */
    private void add(int data) {
        Node newNode = new Node(data);
        if (root == null) {
            root = newNode;
            return;
        }

        Node current = root;
        while (true) {
            if (current.data > data) {
                if (current.left == null) {
                    current.left = newNode;
                    return;
                }
                current = current.left;
            } else {
                if (current.right == null) {
                    current.right = newNode;
                    return;
                }
                current = current.right;
            }
        }
    }

    /**
     * 寻找某个节点
     *
     * @param value
     * @return
     */
    private Node findNode(int value) {
        Node current = root;
        while (true) {
            if (current == null) {
                return null;
            }
            if (current.data == value) {
                return current;
            }
            if (current.data > value) {
                current = current.left;
            } else {
                current = current.right;
            }
        }
    }

    /**
     * 寻找某个节点的父节点
     *
     * @param value
     * @return
     */
    private Node findNodeParent(int value) {
        if (root == null) {
            return null;
        }
        if (root.data == value) {
            return null;
        }
        Node current = root;
        while (true) {
            if (current == null) {
                return null;
            }
            if (current.data > value) {
                if (current.left == null) {
                    return null;
                }
                if (current.left.data == value) {
                    return current;
                }
                current = current.left;
            } else {
                if (current.right == null) {
                    return null;
                }
                if (current.right.data == value) {
                    return current;
                }
                current = current.right;
            }
        }
    }

    /**
     * 寻找中序遍历下node节点的后驱节点
     * 找到以node为根的树的左边的左边的左边的...的那个节点
     *
     * @param node
     * @return
     */
    private Node findFinalLeft(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    /**
     * 删除某个节点(三种情况)
     *
     * @param value
     * @return
     */
    private Node del(int value) {
        //空树
        if (root == null) {
            return null;
        }
        Node target = findNode(value);
        Node targetParent = findNodeParent(value);
        if (target == null) {
            return null;
        } else {
            //找到了待删除节点
            //情况1:待删除节点没有左右子树 -> 直接删除
            if (target.left == null && target.right == null) {
                if (targetParent == null) {
                    //表示没有子树和父节点,整棵树只有待删除节点一个节点,直接置空
                    root = null;
                    return target;
                } else {
                    //有父节点,但有可能是该父节点的左或右子节点
                    if (targetParent.left == null) {
                        targetParent.right = null;
                        return target;
                    } else {
                        targetParent.left = null;
                        return target;
                    }
                }

            } else if (target.left == null || target.right == null) {
                //情况2:待删除节点有左子树或者右子树 -> 删除待删除节点,将待删除节点的左子树或右子树嫁接到它的父节点
                if (target.left == null) {
                    if (targetParent == null) {
                        root = target.right;
                        return target;
                    }
                    if (targetParent.left != null && target.left.data == value) {
                        targetParent.left = target.right;
                        return target;
                    } else {
                        targetParent.right = target.right;
                        return target;
                    }
                } else {
                    if (targetParent == null) {
                        root = target.left;
                        return target;
                    }
                    if (targetParent.left != null && target.left.data == value) {
                        targetParent.left = target.left;
                        return target;
                    } else {
                        targetParent.right = target.left;
                        return target;
                    }
                }
            } else {
                //情况3:待删除节点既有左子树又有右子树 -> 找到中序排序下的前驱或者后驱节点(即是中序排序后,前后节点;这里寻找后节点,即是后驱节点),用它代替待删除节点
                Node finalLeft = findFinalLeft(target);
                int data = finalLeft.data;
                del(data);
                target.data = data;
            }
        }
        return null;
    }

}

class Node {
    int data;
    Node left;
    Node right;

    public Node() {
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值