二叉排序树基础+代码

324 阅读4分钟

二叉排序树

性质

  1. 二叉排序树是一种特殊的二叉树,它的每个结点都有一个关键字,且满足以下性质:

(1)如果左子树不为空,则左子树上所有结点的关键字都小于根结点的关键字。

(2)如果右子树不为空,则右子树上所有结点的关键字都大于根结点的关键字。

(3)左右子树也都是二叉排序树。

建立、查找、插入和删除

  1. 二叉排序树的主要操作有建立、查找、插入和删除。

(1)建立二叉排序树是指从一个无序的序列中逐个插入结点,构造出一个二叉排序树。

(2)查找二叉排序树是指从根结点开始,根据关键字和当前结点的比较结果,沿着左右子树递归地查找目标结点,如果找到则返回该结点,否则返回空。

(3)插入二叉排序树是指在查找过程中,如果发现目标关键字不存在,则在最后一个访问的空位置上插入一个新结点,保持二叉排序树的性质不变。

删除二叉排序树是指在查找过程中,如果发现目标关键字存在,则分三种情况处理:

  • 如果待删除结点是叶子结点,则直接删除该结点。
  • 如果待删除结点只有一个孩子,则用该孩子替换该结点,并删除该结点。
  • 如果待删除结点有两个孩子,则用该结点的左子树的最大值或者右子树的最小值替换该结点,并删除原来的最大值或最小值结点。

(4)二叉排序树的优点是查找、插入和删除的时间复杂度都是O(logn),其中n是结点的个数。二叉排序树的缺点是如果序列本身就是有序或者接近有序的,那么构造出来的二叉排序树会退化成链表,导致时间复杂度变成O(n)。为了避免这种情况,可以使用平衡二叉排序树,如AVL树、红黑树等。

代码

    //定义二叉排序树节点类
    class BSTNode {
      int data; //节点存储的数据
      BSTNode left; //左子节点
      BSTNode right; //右子节点

      //构造方法
      public BSTNode(int data) {
        this.data = data;
        this.left = null;
        this.right = null;
      }
    }

    //定义二叉排序树类
    class BSTree {
      BSTNode root; //根节点

      //构造方法
      public BSTree() {
        this.root = null;
      }

      //插入方法,向二叉排序树中插入一个数据
      public void insert(int data) {
        //如果根节点为空,直接创建一个新节点作为根节点
        if (this.root == null) {
          this.root = new BSTNode(data);
          return;
        }
        //否则,从根节点开始遍历,找到合适的位置插入新节点
        BSTNode current = this.root; //当前遍历到的节点
        BSTNode parent = null; //当前节点的父节点
        while (current != null) {
          parent = current; //更新父节点
          if (data < current.data) { //如果插入的数据小于当前节点的数据,向左子树遍历
            current = current.left;
          } else if (data > current.data) { //如果插入的数据大于当前节点的数据,向右子树遍历
            current = current.right;
          } else { //如果插入的数据等于当前节点的数据,不做任何操作,直接返回
            return;
          }
        }
        //当遍历结束时,parent指向了插入位置的父节点,current为null
        if (data < parent.data) { //如果插入的数据小于父节点的数据,作为父节点的左子节点
          parent.left = new BSTNode(data);
        } else { //如果插入的数据大于父节点的数据,作为父节点的右子节点
          parent.right = new BSTNode(data);
        }
      }

      //中序遍历方法,按照从小到大的顺序输出二叉排序树中的数据
      public void inorder() {
        inorder(this.root); //从根节点开始遍历
      }

      //辅助方法,递归地中序遍历以node为根的子树
      private void inorder(BSTNode node) {
        if (node == null) { //递归基准情形,如果节点为空,直接返回
          return;
        }
        inorder(node.left); //递归地中序遍历左子树
        System.out.print(node.data + " "); //输出当前节点的数据
        inorder(node.right); //递归地中序遍历右子树
      }
    }

    //测试代码
    public class TestBSTree {
      public static void main(String[] args) {
        BSTree tree = new BSTree(); //创建一个空的二叉排序树对象
        tree.insert(5); //向二叉排序树中插入一些数据
        tree.insert(3);
        tree.insert(7);
        tree.insert(2);
        tree.insert(4);
        tree.insert(6);
        tree.insert(8);
        tree.inorder(); //中序遍历二叉排序树,输出结果应为2 3 4 5 6 7 8 
      }
    }

这个代码主要分为两个类,一个是BSTNode,表示二叉排序树的节点,一个是BSTree,表示二叉排序树本身。BSTNode类有三个属性,分别是data,left和right,分别表示节点存储的数据,左子节点和右子节点。BSTNode类有一个构造方法,用于创建一个新的节点,并给定数据。BSTree类有一个属性,就是root,表示二叉排序树的根节点。BSTree类有两个主要的方法,一个是insert,用于向二叉排序树中插入一个数据,一个是inorder,用于按照从小到大的顺序输出二叉排序树中的数据。