数据结构->二叉排序树

43 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情

二叉排序树是什么

二叉排序树又称二叉查找树(Binary Search Tree),亦称二叉搜索树。

二叉排序树或者是一棵空树,或者是具有下列特点的二叉树

  • 若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值;
  • 若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
  • 左、右子树也分别为二叉排序树;

二叉搜索树的特征

1.中序遍历的序列是递增的序列

public LinkedList inorder(TreeNode root, LinkedList arr) {
    if (root == null) return arr;
    inorder(root.left, arr);
    arr.add(root.val);
    inorder(root.right, arr);
    return arr;
}

2.中序遍历的下一个节点,称后继节点,即比当前节点大的最小节点

public int successor(TreeNode root) {
    root = root.right;
    while (root.left != null) root = root.left;
    return root;
}

3.中序遍历的前一个节点,称前驱节点,即比当前节点小的最大节点

public int predecessor(TreeNode root) {
    root = root.left;
    while (root.right != null) root = root.right;
    return root;
}

二叉树的操作

1.添加节点

思路:

  1. 检查该二差排序树是否为空,如果为空,则将新节点指定为根节点,否则将新节点与根节点进行比较;
  2. 根据比较结果,确定新节点应该插入根节点的左子树还是右子树,之后我们将应该被插入的左右子树作为新的研究对象,重复1过程

代码实现:

    public Node add(Node root, int value) {
        if(root == null){
            //走到叶子节点添加
            root = new Node(value);
            size++;
            return root;
        }
        //比较value和根节点的大小
       if(value < root.val){
           root.left = add(root.left,value);
        }else{
           root.right = add(root.right,value);
       }
       return root;
    }

2.查询节点 思路:

二叉排序树中进行指定值的节点查找非常简便,这个查找过程实际上就是一个二分搜索的过程,我们首先创建一个遍历指针,让这个指针指向排序树的根节点,如果根节点值等于我们想要查找的值,那么我们就直接进行返回操作即可,如果不等于,那么根节点必定大于或者小于我们要查找的值,此时我们根据具体情况在根节点的左子树或者右子树中继续查询,这里是一个递归过程.

代码实现:

public TreeNode search(TreeNode node, int value){
        if(node == null){
            return null;
        }
        if(node.getValue()>value){
            if(node.getLeftTreeNode() == null)
                return null;
            return search(node.getLeftTreeNode(),value);
        }else if(node.getValue()<value){
            if(node.getRightTreeNode() == null)
                return null;
            return search(node.getRightTreeNode(),value);
        }else{
            return node;
        }
}

3.删除节点

分几种情况:

  1. 删除叶子节点

基本思路:

1. 找到要删除的节点targeNode
2. 找到删除节点的父节点parent节点
3. 判断targeNode节点是parent节点的左子树还是右子树
4. 根据上述情况进行删除
   左子节点:parent.left = null;
   右子节点:parent.right = null;

2. 删除只有一个子树的结点(左子树,右子树)

1.找到要删除的节点targeNode
2.找到删除节点的父节点parent节点
3.确定要删除的节点的子节点是左子节点还是右子节点
4.判断targeNode节点是parent节点的左子树还是右子树
5.如果target有左子节点
    target是parent的左子节点 parent.left = target.left
    target是parent的右子节点 parent.right = target.right
6.如果target有右子节点
    target是parent的左子节点 parent.left = target.right
    target是parent的右子节点 parent.right = target.left

3. 删除有两个子树的结点

1.找到要删除的节点targeNode
2.找到删除节点的父节点parent节点(考虑是否有父节点)
3.从targetNode的右子树去找最小值(或左子树的最大值)
4.右子树去找最小值(或左子树的最大值)和要删除的节点 target值进行替换
5.删除.右子树去找最小值(或左子树的最大值)

代码实现:

/**
 *
 * @param value  希望删除啊的节点值
 * @return  如果找到返回该节点值,找不到返回null
 */
public TreeNode search(TreeNode node,int value){
 
    if(root == null){
        return null;
    }
 
    // 找到的就是这个节点
    if(value == node.getValue()){
        return node;
    }else if(value < node.getValue()){ //如果查找的值小于当前节点向左子树递归查找
        // 判断左子树是否为空
        if(node.getLeftTreeNode() == null){
            return  null;
        }
       return search(node.getLeftTreeNode(),value);
    }else {
        if(node.getRightTreeNode() == null){
            return null;
        }
        return search(node.getRightTreeNode(),value);
    }
 
}

4.遍历节点 采用二叉树的中序遍历