二叉查找树(查询、插入、遍历、删除)--Java实现

搜索树数据结构支持许多动态集合操作,包括search、insert、delete、maximum、minimum等。因此,我们使用一棵搜索树既可以作为一个字典又可以作为一个优先队列。
二叉搜索树上的基本操作所花费的时间与这棵树的高度成正比。对于有n个结点的一棵完全二叉树来说,这些操作的最坏运行时间为O(logn)。然而,如果这棵树是一条n个结点组成的线性链,那么同样的操作就要花费O(n)的最坏的运行时间。

一、什么是二叉搜索树

一棵二叉搜索树是以一棵二叉树来组织的,这样的一棵树可以使用一个链表数据结构来表示,其中每个结点就是一个对象。最重要的特性就是:对任何结点x,其左子树的关键字最大不超过x.value,其右子树中的关键字最小不低于x.value。不同二叉搜索树可以代表同一组值的集合,大部分搜索树的最坏运行时间与树的高度成正比。下图为一棵包含11个结点、高度为4的二叉搜索树。
《二叉查找树(查询、插入、遍历、删除)--Java实现》

二、二叉查找树的操作(查询、插入、遍历、删除)

定义结点

 public class TreeNode{
        public int keyValue;    //关键字值
        public TreeNode leftNode;//左节点
        public TreeNode rightNode;//右节点

        public TreeNode(){}
        public TreeNode(int Key){
            this.keyValue = Key;
        }
    }

(1)查询二叉搜索树的结点

//查询结点
    public TreeNode BSTsearch(TreeNode root, int Key){
        TreeNode node=root;
        //当节点值不等于要查找的结点值就循环,如果没有找到则返回null
        while(node.keyValue!=Key){
            if(Key<node.keyValue){
                node=node.leftNode;
            }else{
                node=node.rightNode;
            }
            if(node==null){
                return null;
            }
        }
        return node;
    }

(2)插入二叉搜索树的结点

//插入结点,插入结点的过程就是先查询再插入
    public void BSTinsert(TreeNode root, int Key){
        TreeNode node=new TreeNode(Key);
        //插入结点之前先找到要插入的位置,这样就要记住插入结点的父节点
        //让父节点的左右指针指向要添加的结点
        if(root== null){
            root=node;
        }else{
            TreeNode currentNode = root;//定义当前节点为根节点
            TreeNode parentNode;
            while(true){
                parentNode=currentNode;
                if(Key<currentNode.keyValue){
                    currentNode=currentNode.leftNode;
                    if(currentNode==null){
                        parentNode.leftNode=node;
                        return;
                    }
                }else{
                    currentNode=currentNode.rightNode;
                    if(currentNode==null){
                        parentNode.rightNode=node;
                        return;
                    }
                }
            }
        }
    }

(3)遍历二叉树的结点

//遍历树,主要分为中序遍历、前序遍历和后序遍历
    //下面以中序遍历做例子
    public void BSTdisplay(TreeNode node){
        if(node!=null){
            BSTdisplay(node.leftNode);
            System.out.println(node.keyValue+",");
            BSTdisplay(node.rightNode);
        }
    }

(4)查询二叉查找树中的最大结点

 //最大值
    public int BSTmax(TreeNode root){
        TreeNode node=root;
        TreeNode parent=null;
        while(node!=null){
            parent=node;
            node=node.rightNode;
        }
        return parent.keyValue;

    }

(5)查询二叉查找树中的最小结点

  //最小值
    public int BSTmin(TreeNode root){
        TreeNode node=root;
        TreeNode parent=null;
        while(node!=null){
            parent=node;
            node=node.leftNode;
        }
        return parent.keyValue;

    }

(6)删除二叉搜索树的结点
二叉树的结点删除要分成三类:
删除没有子结点的结点;
删除只有一个子结点的结点;
删除有两个子结点的结点。

 // 删除节点分三种方式删除节点
    // 1、删除没有子节点的节点,直接让该节点的父节点的左节点或右节点指向空
    // 2、删除有一个子节点的节点,直接让该节点的父节点指向被删除节点的剩余节点
    // 3、删除有三个节点的子节点,找到要删除节点的后继节点, 用该节点替代删除的节点
    public boolean BSTdelete(TreeNode root,int Key) {
        // 首先查找节点,并记录该节点的父节点引用
        TreeNode current = root;
        TreeNode parent = root;
        boolean isLeftNode = true;
        while (current.keyValue != Key) {
            parent = current;
            if (Key < current.keyValue) {
                isLeftNode = true;
                current = current.leftNode;
            } else {
                isLeftNode = false;
                current = current.rightNode;
            }
        }
        if (current == null) {
            System.out.println("没有找到要删除的节点!");
            return false;
        }
        // 下面分三种情况删除节点
        if (current.leftNode == null && current.rightNode == null) {  //要删除的节点没有子节点
            if (current == root) { // 根节点就删除整棵树
                root = null;
            } else if (isLeftNode) { // 如果是左节点,做节点指向空
                parent.leftNode = null;
            } else { // 如果是右节点,右节点指向空
                parent.rightNode = null;
            }
        } else if (current.leftNode == null) {                         //要删除的节点只有右节点
            if (current == root) {
                root = current.rightNode;
            } else if (isLeftNode) {
                parent.leftNode = current.rightNode;
            } else {
                parent.rightNode = current.rightNode;
            }
        } else if (current.rightNode == null) {                         //要删除的节点只有左节点
            if (current == root) {
                root = current.leftNode;
            } else if (isLeftNode) {
                parent.leftNode = current.leftNode;
            } else {
                parent.rightNode = current.leftNode;
            }
        } else {                                                         //要删除的节点有两个节点
            TreeNode successor = findSuccessor(current);
            if(current == root){
                root = successor;
            }else if(isLeftNode){
                parent.leftNode = successor;
            }else{
                parent.rightNode = successor;
            }
            successor.leftNode = current.leftNode;
        }
        return true;
    }

    private TreeNode findSuccessor(TreeNode delNode){
        TreeNode parent = delNode;
        TreeNode successor = delNode;
        TreeNode current = delNode.rightNode;
        while(current != null){
            parent = successor;
            successor = current;
            current = current.leftNode;
        }

        if(successor != delNode.rightNode){
            parent.leftNode = successor.rightNode;
            successor.rightNode = delNode.rightNode;
        }
        return successor;
    }
    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/L_kanglin/article/details/68061191
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞