数据结构和算法分析

看图说话之二叉排序树

2018-04-12  本文已影响0人  涂印
一丶二叉排序树基本介绍

    二叉树是一种常见的树结构,二叉排序树是二叉树的一种特殊情况,其在二叉树的基础上施加了一种“顺序性”的约束,BST在排序和查找中具有广泛的运用下图就是一个常见的BST(Binary sort tree,二叉排序树 )。


图1 二叉排序树

二叉树是一种常见的树结构,二叉排序树是二叉树的一种特殊情况,其在二叉树对照图1所示的二叉排序树,可以给出BST的如下主要特点:

二丶BST的插入操作

    假设待插入数组为: int [] A =new int []{1, 17},将该数组一次插入到图1所示的二叉排序树中(这次做一个特殊的说明,在插入数据中不存在重复的数据)。

  1. 插入元素1,首先和根节点比较,发现1比根节点8小, 接着和节点8的左节点比较,发现1还是小于7,接着继续和7的左节点6比较,1小于6,同时节点6左节点为null,不存在比较的可能了,此时节点1充当节点6的左节点,比较的过程和结果如下图所示。


    图2元素1的插入过程
  2. 在上图2的基础上继续插入元素17,重复和步骤1相同的过程。首先17和根节点9比较,17大于9,所以和节点9的右节点比较,17>15,继续和15的右节点比较发现,17<18,所以17和18的左节点比较,但是发现18的左节点为null,于是17找到了正确的位置,为了18的左节点。比较的过程和结果如下图所示


    图3元素17的插入过程

    依据上述的两个例子可以清晰的看到BST的插入过的基本实现,下面总结下BST插入过程的特点。

public Node insert(element t,Node root){
                 if(root==null) new Node(t);
                 if(t<root.element){
                 root.left= insert(t,root.left);
                }else if(t>root.element){
                         root.right =insert(t,root.right);
                }else {
                       //在BST中找到了相等的节点,不做处理直接返回
                        return ;
                }
          }
三丶BST树的删除操作

    BST树的删除操作相比较于BST树的插入操作,过程很相似,只是稍稍复杂一些,主要是分如下三种情况进行讨论。

  1. 被删除元素不存在左儿子和右儿子,其过程如下图所示


    图5定位被删除节点
    图6 删除节点

    在该种情况下被删除元素不存在儿子节点,直接用null代替被删除元素

  2. 被删除元素只存在一个儿子,其过程如下 图所示
    图7定位被删除节点
    图8删除节点
    在该种情况下,被删除节点只有一个儿子,直接由其儿子节点替代删除节点。
  3. 被删除节点有两个儿子,其主要过程如下所示三步完成。
    图9 定位被删除节点
    图10删除第二步
        如图9中所示,定位被删除节点后,如果该节点左右儿子都存在,那么找到该节点右子树中的最小节点,用该最小节点替代被删除节点
    图11 删除节点右子树最小节点。
         经过图8,图9,图10所表示的不步骤后,元素6被删除了且BST的顺序性并未改变。上述三个步骤的汇总如下图所示
    图12 被删除节点具有左儿子和右儿子的删除操作
public Node delete(int element,Node root){
       //未定位到删除元素
       if(root==null) return null;
       intdelta = element-root.element;
       if(delta<0){
           root.left = delete(element,root.left);
       }elseif(delta>0){
           root.right =delete(element,root.right);
       }else{
           if(root.left!=null&&root.right!=null){
              Node node = findMin(root.right);
              root.element =node.element;
              root.right = delete(node.element,root.right);
           }else{
              root = root.left!=null?root.left:root.right;
           }
       }
       returnroot;
    }
四丶二叉树的建树操作。

    二叉树的建树操作很容易理解,建立一个N个节点BST操作,就是对元素执行N次的插入操作,每次插入操作的时间复杂度若为理想得Log(N),那么建树操作的时间复杂度就是Nlog(N)。

五丶BST的应用
六丶BST树的java代码实现
 public class BinarySortTree {
    publicNode root = null;
    publicstatic void main(String []args){
       int[] elements = new int[]{5,4,9,3,2};
       BinarySortTree bst = new BinarySortTree();
       /****测试插入,建树和中序遍历操作***/
       bst.buildTree(elements);
       bst.midTrace();
       System.out.println();
       /****测数删除操作之无儿子***************/
    //  bst.delete(9);
    //  bst.midTrace();
       /****测数删除操作之只有一个儿子***************/
    //  bst.delete(4);
    //  bst.midTrace();
       /****测数删除操作只有两个儿子***************/
       bst.delete(5);
       bst.midTrace();
    }
    //节点类型定义
    publicstatic class Node{
       publicint element;
       publicNode left;
       publicNode right;
       publicNode(int element){
           this.element = element;
           left = null;
           right = null;
       }
    }
    //外部使用的插入方法
    publicvoid insert(int element){
       root=insert(element,root);
    }
    //内部使用的插入方法
    private  Node insert(int element,Node root){
       if(root==null)
           return new Node(element);
       intdelta = element-root.element;
       if(delta<0){
           root.left = insert(element,root.left);
       }elseif(delta>0){
           root.right = insert(element,root.right);
       }else{
           //不做处理
       }
       returnroot;
    }
    //外部使用的建树方法
    publicvoid buildTree(int [] elements){
       if(root==null){
           for(int i=0;i<elements.length;i++){
              insert(elements[i]);
           }
       }else{
           //若树以存在,则不能建
       }
    }
    publicvoid delete(int element){
       delete(element,root);
    }
    publicNode delete(int element,Node root){
       //未定位到删除元素
       if(root==null) return null;
       intdelta = element-root.element;
       if(delta<0){
           root.left = delete(element,root.left);
       }elseif(delta>0){
           root.right =delete(element,root.right);
       }else{
           if(root.left!=null&&root.right!=null){
              Node node = findMin(root.right);
              root.element =node.element;
              root.right = delete(node.element,root.right);
           }else{
              root = root.left!=null?root.left:root.right;
           }
       }
       returnroot;
    }
    //中序遍历二叉树
    publicvoid midTrace(){
       if(root!=null){
           print(root);
       }
    }
    privatevoid print(Node node){
       if(node!=null){
           print(node.left);
           System.out.print(node.element+" ");
           print(node.right);
       }
    }
    //找到该节点下子树的最小节点。
    publicNode findMin(Node node){
       if(node.left==null)
           return node;
       else
           return findMin(node.left);
    }
}

Reference:
[1] 数据结构与算法 jaba语言描述版
[2] 原文博客链接

上一篇下一篇

猜你喜欢

热点阅读