彻底理清二叉排序树的插入、查找、删除

二叉排序树的概述

  二叉排序树也被成为二叉查找树或者二叉搜索树。它或者是一棵空的二叉树。它具备以下性质。

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

  若它的右子树不空,则右子树上所有结点的值均大于根结点的值。

  它的左右子树也都是二叉排序树。

简述二叉排序树原理与实现

  二叉排序树的建立根基是二叉链表。

//二叉树节点
public class BinaryTreeNode {
    public  int data;
    public BinaryTreeNode left;
    public BinaryTreeNode right;
}

  假设有这样一组数据{11,2,5,7,3,9,4,66,55},那么它将构造这样一棵树结构。

  

  如何对搜索二叉树插入节点,从而构建一颗二叉树?

  根据二叉树的定义,向二叉排序树中插入节点s的过程,用伪代码描述:

    若root是空树,则将节点s作为根结点输入;

    否则,若s.data<root.data,则把节点s插入在root的左子树中;

    否则把结点s插入到root的右子树中;

  //构建搜索二叉树
    public  BinaryTreeNode build(int [] array){
        BinaryTreeNode root =new BinaryTreeNode(array[0]);  
        for( int i = 1 ; i < array.length ; i ++){  
            insertBST(root, array[i]);    
        }
        return root;
    }
    public BinaryTreeNode insertBST(BinaryTreeNode node,int data){
        if(node == null){  
            node = new BinaryTreeNode(data);  
            return node;  
        }else{  
            if(data <= node.data)  
                node.left =  insertBST(node.left, data);  
            else 
                node.right = insertBST(node.right,data);  
            return node;  
        }  
    }

  查找二叉树的指定值。

    若root是空树,则查找失败。

    若k=root.data,则查找成功。

    若k<root.data,则查找二叉树的左子树。

    若k>root.data,则查找二叉树的右子树。

//查找元素
    public BinaryTreeNode serachBST(BinaryTreeNode root,int target){
        if(null==root)
            return null;
        else if(root.getData()==target)
            return root;
        else if(root.getData()>target)
            return serachBST(root.getLeft(), target);
        else
            return serachBST(root.getRight(), target);
    }

  删除二叉树的指定值。删除元素其实并不难,重点是删除要元素以后依然要保持二叉搜索树,不能让它头脚分离变成森林。

  假设要删除结点为p(2),节点分为三种类型,p是叶子节点,p只有一个孩子,p有两个孩子。

  情况一:假设p是叶子节点,只需要把p设为null即可。

  情况二:假设p有一个孩子。假设它有左孩子,那么把p节点等于左孩子;假设它有右孩子,那么把p节点等于右孩子。

   情况三:假设p有两个孩子。

        查找p节点右子树的最左子树节点,也就是p节点的右子树的最小结点s,以及s的双亲节点par;

        将s的数据域替换被删除结点p的数据域;

        若节点p的右孩子无子树,则将s的右子树接到par的右子树上;否则,将s的右子树接到par的左字数上;

  图例原始图

  

  图例情况一:假设删除结点p为9,无孩子节点。

  

  图例情况二:假设删除节点p为3,有右孩子节点。

  

  图例情况三:假设删除节点p为5,有左右孩子。

  

    public BinaryTreeNode deleteBST(BinaryTreeNode root,int key){
        if(root==null){
            return null;
        }
        if(root.data==key){
            return deleteNode(root);
        }else if(root.data<key){
            root.right=deleteBST(root.right, key);
        }else{
            root.left=deleteBST(root.left, key);
        }
        return root;
    }
</span><span style="color: #008000;">//</span><span style="color: #008000;">删除元素</span>
<span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode deleteNode(BinaryTreeNode p){
    </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>==p.left&amp;&amp;<span style="color: #0000ff;">null</span>==<span style="color: #000000;">p.right){
        p</span>=<span style="color: #0000ff;">null</span>;<span style="color: #008000;">//</span><span style="color: #008000;">无孩子节点</span>
    }<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(p.left==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
        p</span>=p.right;<span style="color: #008000;">//</span><span style="color: #008000;">只有右孩子</span>
    }<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(p.right==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
        p</span>=p.left;<span style="color: #008000;">//</span><span style="color: #008000;">只有左孩子</span>
    }<span style="color: #0000ff;">else</span><span style="color: #000000;">{
        BinaryTreeNode par</span>=<span style="color: #000000;">p;
        BinaryTreeNode s</span>=<span style="color: #000000;">p.right;
        </span><span style="color: #0000ff;">while</span>(s.left!=<span style="color: #0000ff;">null</span><span style="color: #000000;">){
            par</span>=<span style="color: #000000;">s;
            s</span>=<span style="color: #000000;">s.left;
        }
        p.data</span>=<span style="color: #000000;">s.data;
        </span><span style="color: #0000ff;">if</span>(par==<span style="color: #000000;">p){
            par.right</span>=s.right;<span style="color: #008000;">//</span><span style="color: #008000;">处理特殊情况,par节点没有左孩子</span>
        }<span style="color: #0000ff;">else</span><span style="color: #000000;">{
            par.left</span>=s.right;<span style="color: #008000;">//</span><span style="color: #008000;">处理一般情况,p节点替换成par的最左节点。</span>

}
}
return p;
}

发散思考-更进一步

  假设一颗二叉树为是一颗右斜树,二叉搜索树的优势也将荡然无存。那问题出在哪?就是构造二叉树的时候,就是我们改善的着手点。

  那么就引出了平衡二叉树的概念,那什么是平衡二叉树呢?

    平衡二叉树或者是一棵空的二叉树,或者是具有以下性质的二叉树。

    根结点的左子树和右子树的深度最多相差1。

    根结点的左子树和右子树也都是平衡二叉树。

  那如何构建一颗平衡二叉树呢?先对数组进行排序,然后像折半查找一样,向两侧平均构造二叉树。当排序的数值多的时候,它将提高查找效率。

  

//构建平衡搜索二叉树
    public BinaryTreeNode buildBlanceTree(int [] array,int start,int end){
        if(start>end)
            return null;
        int mid=(start+end)/2;
        BinaryTreeNode node=new BinaryTreeNode(array[mid]);
        if(start==end){
            return node;
        }
        node.left=buildBlanceTree(array, start,mid-1);
        node.right=buildBlanceTree(array, mid+1,end);
        return node;
    }

  善于思考的大佬们又脑洞大开了,直接删除节点、插入节点的时候,若产生不平衡,重构平衡二叉树岂不是难上加难?具体代码又读者自行思考完成。

  平衡二叉树分为四种类型:LL型、RR型、LR型、RL型。

  

  LR型:不平衡点的左子树左转,以不平衡点为基点向右转。RL型:不平衡点的右子树右转,以补平衡点为基点向左转。

  

public class BinaryTreeNode {
    public  int data;
    public BinaryTreeNode left;
    public BinaryTreeNode right;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode() {}

</span><span style="color: #0000ff;">public</span> BinaryTreeNode(<span style="color: #0000ff;">int</span><span style="color: #000000;"> data, BinaryTreeNode left, BinaryTreeNode right) {
    </span><span style="color: #0000ff;">super</span><span style="color: #000000;">();
    </span><span style="color: #0000ff;">this</span>.data =<span style="color: #000000;"> data;
    </span><span style="color: #0000ff;">this</span>.left =<span style="color: #000000;"> left;
    </span><span style="color: #0000ff;">this</span>.right =<span style="color: #000000;"> right;
}

</span><span style="color: #0000ff;">public</span> BinaryTreeNode(<span style="color: #0000ff;">int</span><span style="color: #000000;"> data) {
    </span><span style="color: #0000ff;">this</span>(data,<span style="color: #0000ff;">null</span>,<span style="color: #0000ff;">null</span><span style="color: #000000;">);
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getData() {
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> data;
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> setData(<span style="color: #0000ff;">int</span><span style="color: #000000;"> data) {
    </span><span style="color: #0000ff;">this</span>.data =<span style="color: #000000;"> data;
}

</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode getLeft() {
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> left;
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setLeft(BinaryTreeNode left) {
    </span><span style="color: #0000ff;">this</span>.left =<span style="color: #000000;"> left;
}

</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode getRight() {
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> right;
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setRight(BinaryTreeNode right) {
    </span><span style="color: #0000ff;">this</span>.right =<span style="color: #000000;"> right;
}

}

public class BinarySortTree {

</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> BinarySortTree(){}

</span><span style="color: #008000;">//</span><span style="color: #008000;">构建搜索二叉树</span>
<span style="color: #0000ff;">public</span>  BinaryTreeNode build(<span style="color: #0000ff;">int</span><span style="color: #000000;"> [] array){
    BinaryTreeNode root </span>=<span style="color: #0000ff;">new</span> BinaryTreeNode(array[0<span style="color: #000000;">]);  
    </span><span style="color: #0000ff;">for</span>( <span style="color: #0000ff;">int</span> i = 1 ; i &lt; array.length ; i ++<span style="color: #000000;">){  
        insertBST(root, array[i]);    
    }
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> root;
}

</span><span style="color: #008000;">//</span><span style="color: #008000;">构建平衡搜索二叉树</span>
<span style="color: #0000ff;">public</span> BinaryTreeNode buildBlanceTree(<span style="color: #0000ff;">int</span> [] array,<span style="color: #0000ff;">int</span> start,<span style="color: #0000ff;">int</span><span style="color: #000000;"> end){
    </span><span style="color: #0000ff;">if</span>(start&gt;<span style="color: #000000;">end)
        </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;
    </span><span style="color: #0000ff;">int</span> mid=(start+end)/2<span style="color: #000000;">;
    BinaryTreeNode node</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> BinaryTreeNode(array[mid]);
    </span><span style="color: #0000ff;">if</span>(start==<span style="color: #000000;">end){
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> node;
    }
    node.left</span>=buildBlanceTree(array, start,mid-1<span style="color: #000000;">);
    node.right</span>=buildBlanceTree(array, mid+1<span style="color: #000000;">,end);
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> node;
}

</span><span style="color: #0000ff;">public</span> BinaryTreeNode insertBST(BinaryTreeNode node,<span style="color: #0000ff;">int</span><span style="color: #000000;"> data){
    </span><span style="color: #0000ff;">if</span>(node == <span style="color: #0000ff;">null</span><span style="color: #000000;">){  
        node </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> BinaryTreeNode(data);  
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> node;  
    }</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{  
        </span><span style="color: #0000ff;">if</span>(data &lt;=<span style="color: #000000;"> node.data)  
            node.left </span>=<span style="color: #000000;">  insertBST(node.left, data);  
        </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> 
            node.right </span>=<span style="color: #000000;"> insertBST(node.right,data);  
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> node;  
    }  
}

</span><span style="color: #008000;">//</span><span style="color: #008000;">层序遍历</span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> levelOrder(BinaryTreeNode root){
    BinaryTreeNode temp;
    Queue</span>&lt;BinaryTreeNode&gt; queue=<span style="color: #0000ff;">new</span> LinkedList&lt;BinaryTreeNode&gt;<span style="color: #000000;">();
    queue.offer(root);
    </span><span style="color: #0000ff;">while</span>(!<span style="color: #000000;">queue.isEmpty()){
        temp</span>=<span style="color: #000000;">queue.poll();
        System.out.print(temp.getData()</span>+"\t"<span style="color: #000000;">);
        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>!=<span style="color: #000000;">temp.getLeft()) 
            queue.offer(temp.getLeft());
        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>!=<span style="color: #000000;">temp.getRight()){
            queue.offer(temp.getRight());
        }
    }
}

</span><span style="color: #0000ff;">public</span> BinaryTreeNode deleteBST(BinaryTreeNode root,<span style="color: #0000ff;">int</span><span style="color: #000000;"> key){
    </span><span style="color: #0000ff;">if</span>(root==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
        </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;
    }
    </span><span style="color: #0000ff;">if</span>(root.data==<span style="color: #000000;">key){
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> deleteNode(root);
    }</span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(root.data&lt;<span style="color: #000000;">key){
        root.right</span>=<span style="color: #000000;">deleteBST(root.right, key);
    }</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{
        root.left</span>=<span style="color: #000000;">deleteBST(root.left, key);
    }
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> root;
}

</span><span style="color: #008000;">//</span><span style="color: #008000;">删除元素</span>
<span style="color: #0000ff;">public</span><span style="color: #000000;"> BinaryTreeNode deleteNode(BinaryTreeNode p){
    </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>==p.left&amp;&amp;<span style="color: #0000ff;">null</span>==<span style="color: #000000;">p.right){
        p</span>=<span style="color: #0000ff;">null</span>;<span style="color: #008000;">//</span><span style="color: #008000;">无孩子节点</span>
    }<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(p.left==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
        p</span>=p.right;<span style="color: #008000;">//</span><span style="color: #008000;">只有右孩子</span>
    }<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(p.right==<span style="color: #0000ff;">null</span><span style="color: #000000;">){
        p</span>=p.left;<span style="color: #008000;">//</span><span style="color: #008000;">只有左孩子</span>
    }<span style="color: #0000ff;">else</span><span style="color: #000000;">{
        BinaryTreeNode par</span>=<span style="color: #000000;">p;
        BinaryTreeNode s</span>=<span style="color: #000000;">p.right;
        </span><span style="color: #0000ff;">while</span>(s.left!=<span style="color: #0000ff;">null</span><span style="color: #000000;">){
            par</span>=<span style="color: #000000;">s;
            s</span>=<span style="color: #000000;">s.left;
        }
        p.data</span>=<span style="color: #000000;">s.data;
        </span><span style="color: #0000ff;">if</span>(par==<span style="color: #000000;">p){
            par.right</span>=s.right;<span style="color: #008000;">//</span><span style="color: #008000;">处理特殊情况,par节点没有左孩子</span>
        }<span style="color: #0000ff;">else</span><span style="color: #000000;">{
            par.left</span>=s.right;<span style="color: #008000;">//</span><span style="color: #008000;">处理一般情况,p节点替换成par的最左节点。</span>

}
}
return p;
}

</span><span style="color: #008000;">//</span><span style="color: #008000;">查找元素</span>
<span style="color: #0000ff;">public</span> BinaryTreeNode serachBST(BinaryTreeNode root,<span style="color: #0000ff;">int</span><span style="color: #000000;"> target){
    </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">null</span>==<span style="color: #000000;">root)
        </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">;
    </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(root.getData()==<span style="color: #000000;">target)
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> root;
    </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(root.getData()&gt;<span style="color: #000000;">target)
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> serachBST(root.getLeft(), target);
    </span><span style="color: #0000ff;">else</span>
        <span style="color: #0000ff;">return</span><span style="color: #000000;"> serachBST(root.getRight(), target);
    
}

</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
    </span><span style="color: #0000ff;">int</span> [] array=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">int</span>[]{11,2,5,7,3,9,4,66,55<span style="color: #000000;">};
    BinarySortTree bst</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> BinarySortTree();
    </span><span style="color: #008000;">//</span><span style="color: #008000;">构建一颗搜索二叉树</span>
    BinaryTreeNode root=<span style="color: #000000;">bst.build(array);
    System.out.println(bst.serachBST(root, </span>9<span style="color: #000000;">).getData());
    bst.levelOrder(root);
    System.out.println();
    
    </span><span style="color: #008000;">//</span><span style="color: #008000;">构建一颗平衡搜索二叉树</span>

Arrays.sort(array);
BinaryTreeNode node
=bst.buildBlanceTree(array, 0,array.length-1);
System.out.println(bst.serachBST(root,
11).getData());
bst.levelOrder(node);
System.out.println();

    BinaryTreeNode n</span>=bst.deleteBST(root,2<span style="color: #000000;">);
    bst.levelOrder(n);
    System.out.println();
}

}

搜索二叉树整体代码
posted @ 2017-05-11 19:39  码农皮邱  阅读(1108)  评论(0编辑  收藏  举报