08二叉树基础之二叉查找树

二叉查找树要求,在树中任意一个节点,其左子树中的任一个节点的值要小于该节点,其右子树中的任一个一个节点的值要大于该节点。这个要求是二叉查找树能够快速进行查找、插入、删除操作的基础。

1. 二差查找树的查找操作

二差查找树查找某一个元素的过程是一个递归的过程。先将一个元素的值和根节点进行比较,如果元素的值等于根节点,则返回该节点;如果元素的值小于根节点则递归的在左子树中查找;如果元素的值大于根节点则递归的在右子树中进行查找。

class Node{
    public int val;
    public Node left;
    public Node right;
    public Node(int a){
        this.val = a;
    };

}
class Solution{
    public Node binarySearchTree(Node root, int value){
        if(root == null)  return null;
        while(root != null){               
            if(root.val == value)        //如果值相同,已找到
                return root;
            else if(root.val < value)    //如果值小于value,左递归
                return binarySearchTree(root.left, value);
            else                         //如果值大于value,右递归
                return binarySearchTree(root.right, value);
        }
        return null;                    //没有找到该值时返回空
    };
}

2. 二叉排序树的插入操作

二叉树的插入过程也是一个递归的过程。(基本假设是插入的元素没有重复的),先将一个元素的值和根节点进行比较,如果元素的值小于根节点则递归的在左子树中插入;如果元素的值大于根节点则递归的在右子树中进行插入。

递归写法:

class Node{
    public int val;
    public Node left;
    public Node right;
    public Node(int a){
        this.val = a;
    };
}

class Solution{
    public Node insert(Node root, Node insertNode){
        if(root == null){  //根节点为空,直接插入          
            root = insertNode;
        }
        if(insertNode.val < root.val){                //小于根节点的值,插在左子树中
            root.left = insert(root.left, insertNode);   
        }else{                                        //大于根节点的值,插在右子树中
            root.right = insert(root.right, insertNode)
        }
        return root;                                  //返回根节点的值
    };
}

非递归写法(比递归写法要复杂):

class Node{
    public int val;
    public Node left;
    public Node right;
    public Node(int a){
        this.val = a;
    };
}

class Solution{
    public Node insert(Node root, Node insertNode){
        if(root == null){
            root = insertNode;
            return;
        }
        Node p = root;
        while(p != null){
            if(insertNode.val < p.val){   //在左子树中寻找插入位置
                if(p.left == null){    //若左子树为空,直接插入
                    p.left = insertNode;
                    return;
                }else{
                    p = p.left;         //重复上述过程
                }
            }else{                     //在右子树中寻找合适的位置
                if(p.right == null){    //若右子树为空直接插入
                    p.right = insertNode;
                    return;
                }else{
                    p = p.right;       //重复上述过程
                }
            }
        }
        return root;   //返回插入节点过后的树的根节点
    };
}

3. 二叉排序树的删除操作(leetcode450

二叉树排序树的删除操作是其查、插、删三种操作中最为复杂的一种,因为其涉及到好几种情况,需要分开进行讨论:

  • 如果待删除的节点没有子节点,则只需要将其父节点中,指向该节点的指针置为空
  • 如果待删除的节点只有一个子节点(不管是左节点还是右节点),我们只需要更新父节点中指向该节点的指针,将其指向待删除节点的子节点即可
  • 如果待删除的节点有两个子节点,我们需要找到待删除节点的右子树的最小节点然后将其删除,并替代待删除节点在树中的位置,因为该节点为右子树中的最小节点,所以必然没有左子树,故可以采用上述两种方法将其删除
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if(root == null){
            return null;
        }
        TreeNode p = root;
        TreeNode pParent = null;  //记录p的父亲节点
        while(p != null && p.val != key){ //找到和key值相等的节点值
            pParent = p;
            if(key < p.val){
                p = p.left;
            }else{
                p = p.right;
            }
        }
        if(p == null)  return root;   //没有找到key值对应的节点,说明树中不存在相应的节点值,直接返回
        if(p.left != null && p.right != null){  //待删除节点p左右两个节点的值都不为空
            //找到p的右子树中的最左节点(即最小节点)
            TreeNode minp = p.right;
            TreeNode minpParent = p;   //记录下最小节点的父节点
            while(minp.left != null){
               minpParent = minp;
               minp = minp.left;     
            }
            //找到p的最左节点过后,将其值赋值给p
            p.val = minp.val;
            p = minp;               //删除minp的工作留给后面的操作
            pParent = minpParent;
        }

        TreeNode child = null;   //用于记录待删除节点p的父节点的子节点
        if(p.left != null)  child = p.left;         //待删除节点p的左子节点不为空
        else if(p.right != null) child = p.right;  //待删除节点p的右子节点不为空   
        else
            child = null;     //待删除节点p的左右节点均为空


    if(pParent == null){   //待删除节点p就是根节点,这种情况
        root = child;
    }else if(pParent.left == p){
        pParent.left = child;
    }else{
        pParent.right = child;
    }
    return root;
};
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值