概述

一颗二叉搜索树可以为空,但如果不为空,必须满足以下性质:

  • 非空左子树的所有键值小于其根结点的键值
  • 非空右子树的所有键值大于其根结点的键值
  • 左、右子树都是二叉搜索树

二叉树搜索树的操作

查找操作 Find

  • 查找从根结点开始,如果数为空,则返回 null
  • 若搜索数为非空,则根节点关键字和 X 进行对比,并进行不同处理:
    • 若 X 小于根结点键值,只需在左子树中继续搜索
    • 如果 X 大于根结点的键值,在右子树中继续搜索
    • 若两者比较结果是相等,搜索完成,返回指向此结点的指针

递归实现

BinaryTreeNode find(BinaryTreeNode root, int data){
    if(root == null) return null;
    if(data < root.getData() )
        return find(root.getLeft(), data);      /*在左子树中继续查找*/      
    else if(data > root.getData())
        return find(root.getRight(), data);   /*在右子树中继续查找*/
    return root;                             /*查找成功*/
}
// 时间复杂度:O(n)      空间复杂度:O(n)

非递归实现

BinaryTreeNode find(BinaryTreeNode root, int data){
    if(root == null) return null;
    while(root != null){
        if(data < root.getData())
            root = root.getLeft();        /*在左子树中继续查找*/        
        else if(data > root.getData())
            root = root.getRight();      /*在右子树中继续查找*/
        else
            return root;                 /*查找成功*/  
    }
    return null;
}
// 时间复杂度:O(n)      空间复杂度:O(1)

查找最大和最小元素

  • 最小元素一定是在树的最左分支的端结点上 findMin
  • 最大元素一定是在树的最右分支的端结点上 findMax

递归实现

BinaryTreeNode findMin(BinaryTreeNode root){
    if(root == null) 
        return null;
    else if(root.getLeft() != null)
        return findMin(root.getLeft())          /*沿左分支继续查找*/   
    else
        return root       /*找到最左叶结点并返回*/
}

BinaryTreeNode findMax(BinaryTreeNode root){
    if(root == null) 
        return null;
    else if(root.getRight() != null)
        return findMax(root.getRight())     /*沿右分支继续查找*/
    else
        return root
}

非递归实现

BinaryTreeNode findMin(BinaryTreeNode root){
    if(root == null)
        return null;
    while(root.getLeft() != null) 
        root = root.getLeft();        /*沿左分支继续查找*/        
    return root;       /*找到最左叶结点并返回*/
}


BinaryTreeNode findMax(BinaryTreeNode root){
    if(root == null)
        return null;
    while(root.getRight() != null) 
        root = root.getRight();       /*沿右分支继续查找*/
    return root;
}

插入操作 Insert

插入操作关键是要找到元素应该插入的位置,可以采用与 find 类似的方法

递归实现

BinaryTreeNode insert(BinaryTreeNode root, int data){
    if(root == null) 
        /*若原树为空,生成并返回一个新结点*/
        root = new BinaryTreeNode();
        root.setData(data);
        root.setRight(null);
        root.setLeft(null);
    else    /*开始找要插入元素的位置*/
        if(data < root.getData())
            // 递归插入左子树
            root.setLeft(insert(root.getLeft(), data));      
        else if(data > root.getData())
            // 递归插入右子树
            root.setRight(insert(root.getRight(), data));
    // 将生成的新结点返回
    return root;
}

删除操作 Delete

考虑三种情况:

1)要删除的是叶结点:直接删除,并再修改其父结点指针 --- 置为 null。例如下:删除 35

2)要删除的结点只有一个孩子结点:将其父结点的指针指向要删除结点的孩子结点。例如下:删除 33

3)要删除的结点有左、右两棵子树:用另一个结点替代被删除的结点,右子树的最小元素或者左子树的最大元素。例如下:用右子树最小 50 或左子树最大 35 代替 41 的值,且删除 35 或 50 所在的位置,此位置一定是叶子结点或只有一个孩子结点(此步骤又变成了上面第1条和第2条)

BinaryTreeNode delete(int data, BinaryTreeNode root){
    BinaryTreeNode tmp;
    if(root == null) 
        System.out.println("要删除的元素未找到");
    else if(data < root.getData())
        root.setLeft(delete(data, root.getLeft()));   /*左子树递归删除*/
    else if(data > root.getData())
        root.setRight(delete(data, root.getRight()))   /*右子树递归删除*/
    else
        if(root.getLeft() && root.getRight()){     /*被删除结点存在左右两个子结点*/
            tmp = findMin(root.getRight());    /*右子树中找最小的元素填充删除结点*/
            root.setData(tmp.getData());
            // 删除结点的右子树中删除最小元素
            root.setRight(delete(root.getData(), root.getRight()));    
        }else{  /*被删除结点有一个或无子结点*/
            tmp = root;
            if(root.getLeft() == null)   /*有右孩子或无子结点*/
                root = root.getRight();
            if(root.getRight() == null)  /*有左孩子或无子结点*/
                root = root.getLeft();
        }
    return root;     
}

results matching ""

    No results matching ""