数据结构及算法基础--树(Tree)(三)二叉排序树(Binary Sort Tree)

我们知道二分查找可以缩短查找的时间和复杂度,但是二分查找的要求是序列必须是有序的,所以我们引用了二分排序树

 

二叉排序树,又称二叉查找树、二叉搜索树、B树。

二叉树具有以下独特的性质:

若左子树不空,则左子树上所有的节点的值均小于根节点。

若右子树不空,则右子树上所有的节点的值均小于或等于根节点。

左右子树也分别为二叉排序树。

 

这里写图片描述

同样,上面三个规则和二叉树的定义都是递归定义:左子树所有子节点都比该节点小,右子树的所有子节点逗逼该节点大。

二叉排序树又一个非常重要的点:中序遍历二叉排序树,他的结果一定是从小到大的。不明朗的同学可以理一下二叉排序树的中序遍历。

 

根据二叉排序树,我们可以知道,在查找某个元素的时候

相同返回该节点,如果为空则返回空。

该元素比节点元素小,则返回左子树。

该元素比节点元素大,则返回右子树。

 

1)查找

同样的,这是递归的一种方式实现查找。我们也可以转换一下思想,这就是一个用树实现的二分查找。

实现过程:

    public BinarySortTreeNode getRoot(){
        return mRoot;
    }
    
    public BinarySearchTree(BinarySortTreeNode root){
        this.mRoot=root;
    }
    
    public BinarySortTreeNode Search(int data){
        return Search(mRoot,data);
    }
    
    public BinarySortTreeNode Search(BinarySortTreeNode node,int data){
        if(node==null||node.getData()==data){
            return node;
        }
        if(node.getData()>data){
            return Search(node.getLeftChild(),data);
        }
        else{
            return Search(node.getRightChild(),data);
        }
    }

 

 

2)插入:

插入分为两个部分

  1、查找是否有整个元素,如果有,则直接返回;

  2、找到合适的位置,进行插入操作

 实现代码如下

public void insert(int data){
        if(mRoot==null){
            mRoot=new BinarySortTreeNode(data,null,null);
            mRoot.setData(data);
            return ;
        }
        searchandinsert(null,mRoot,data);
    }
    
    private BinarySortTreeNode searchandinsert(BinarySortTreeNode parent,BinarySortTreeNode node,int data){
        if(node==null){          //destination
            node=new BinarySortTreeNode(data,null,null);
            if(parent!=null){
                if(data<parent.getData()){
                    parent.setLeftChild(node);
                }
                else parent.setRightChild(node);
            }
            return node;
        }
        
        if(node.getData()==data)return node;
        else if(node.getData()>data) return searchandinsert(node,node.getLeftChild(),data);
        else return searchandinsert(node,node.getRightChild(),data);
    }

 

3)删除

删除中会考虑很多种情况,其中包括删除节点是否有左右节点、删除节点是其父节点的左节点还是右节点。 这些判断在代码中会很好的理解出啦

public BinarySortTreeNode searchParent(int data){
        return searchParent(null,mRoot,data);
    }
    
    public BinarySortTreeNode searchParent(BinarySortTreeNode parent,BinarySortTreeNode node,int data){
        if(node==null)return null;
        if(data==node.getData())return parent;
        else if(data<node.getData())return searchParent(node,node.getLeftChild(),data);
        else return searchParent(node,node.getRightChild(),data);
    }
    
    public void delete(int data){
        if(mRoot==null)return ;
        if(mRoot.getData()==data){
            mRoot=null;return;
        }
        
        BinarySortTreeNode parent=searchParent(data);
        if(parent==null)return;
        
        BinarySortTreeNode deleteNode=Search(data);
        
        if(deleteNode==null)return;
        //deleteNode has not any subtree 
        if(deleteNode.getLeftChild()==null&&deleteNode.getRightChild()==null){
            if(parent.getLeftChild()!=null&&parent.getLeftChild().getData()==data)
                parent.setLeftChild(null);
            else parent.setRightChild(null);
            deleteNode=null;
        }
        //deleteNode only has the left subtree
        else if(deleteNode.getLeftChild()!=null&&deleteNode.getRightChild()==null){
            if(parent.getLeftChild()!=null&&parent.getLeftChild().getData()==data)
                parent.setLeftChild(deleteNode.getLeftChild());
            else parent.setRightChild(deleteNode.getLeftChild());
            deleteNode=null;
        }
        
        else if(deleteNode.getLeftChild()==null&&deleteNode.getRightChild()!=null){
            if(parent.getLeftChild()!=null&&parent.getLeftChild().getData()==data)
                parent.setLeftChild(deleteNode.getRightChild());
            else parent.setRightChild(deleteNode.getRightChild());
        }
        //
        //
        else{
            BinarySortTreeNode parentofInherientNode=deleteNode;
            BinarySortTreeNode heresNode=deleteNode.getRightChild();
            
            if(heresNode.getLeftChild()==null) heresNode.setLeftChild(deleteNode.getLeftChild());
            else{
                while(heresNode.getLeftChild()!=null){
                    parentofInherientNode=heresNode;
                    heresNode=heresNode.getLeftChild();
                }
                
                parentofInherientNode.setLeftChild(null);
                heresNode.setLeftChild(deleteNode.getLeftChild());
                heresNode.setRightChild(deleteNode.getRightChild());
            }
            
            if(parent.getLeftChild()!=null&&parent.getLeftChild().getData()==data)
                parent.setLeftChild(heresNode);
            else parent.setRightChild(heresNode);
            deleteNode=null;
        }
    }

 

当然,以上方法的具体功能和实现根据不同的需求,可以发生改变,就像我前面说的,我们只要掌握住整个树的结构,和核心的递归思想。我们就能够使用和扩展不同的树。

 

转载于:https://www.cnblogs.com/DSNFZ/articles/7639426.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值