二叉搜索树详解(Java实现)

1.二叉搜索树定义


二叉搜索树,是指一棵空树或者具有下列性质的二叉树:

  1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
  2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
  3. 任意节点的左,右子树也分别为二叉搜索树;
  4. 没有键值相等的节点。

2.用Java来表示二叉树


public class BinarySearchTree
{ // 二叉搜索树类
    private class Node
    { // 节点类
        int data; // 数据域
        Node right; // 右子树
        Node left; // 左子树
    }

    private Node root; // 树根节点
}

首先,需要一个节点对象的类。这个对象包含数据域和指向节点的两个子节点的引用。

其次,需要一个树对象的类。这个对象包含一个根节点root。

3.创建树(insert)

    public void insert(int key)
    {    
        Node p=new Node(); //待插入的节点
        p.data=key;
        
        if(root==null)
        {
            root=p;
        }
        else
        {
            Node parent=new Node();
            Node current=root;
            while(true)
            {
                parent=current;
                if(key>current.data)    
                {
                    current=current.right; // 右子树
                    if(current==null)
                    {
                        parent.right=p;
                        return;
                    }
                }
                else //本程序没有做key出现相等情况的处理,暂且假设用户插入的节点值都不同
                {
                    current=current.left; // 左子树
                    if(current==null)
                    {
                        parent.left=p;
                        return;
                    }
                }
            }
        }
    }

创建树的时候,主要用到了parent,current来记录要插入节点的位置。哪么怎么检验自己是否正确地创建了一颗二叉搜索树呢,我们通过遍历来输出各个节点的值

4.遍历树(travel)

遍历指的是按照某种特定的次序来访问二叉搜索树中的每个节点,主要有三种遍历的方法:

  1. 前序遍历,“中左右”
  2. 中序遍历,“左中右”
  3. 后续遍历,“左右中”

上面的口诀“中左右”表示的含义是,先访问根节点,再访问左子,最后访问右子。举个例子:

  • 前序遍历:39 24 23 30 64 53 60
  • 中序遍历:23 24 30 39 53 60 64
  • 后序遍历:23 30 24 60 53 64 39

你会发现,按照中序遍历的规则将一个二叉搜索树输入,结果为按照正序排列。

    public void preOrder(Node root)
    { // 前序遍历,"中左右"
        if (root != null)
        {
            System.out.print(root.data + " ");
            preOrder(root.left);
            preOrder(root.right);
        }
    }

    public void inOrder(Node root)
    { // 中序遍历,"左中右"
        if (root != null)
        {
            inOrder(root.left);
            System.out.print(root.data + " ");
            inOrder(root.right);
        }
    }

    public void postOrder(Node root)
    { // 后序遍历,"左右中"
        if (root != null)
        {
            postOrder(root.left);
            postOrder(root.right);
            System.out.print(root.data + " ");
        }
    }

    public void traverse(int traverseType)
    {    // 选择以何种方式遍历
        switch (traverseType)
        {
        case 1:
            System.out.print("preOrder traversal ");
            preOrder(root);
            System.out.println();
            break;
        case 2:
            System.out.print("inOrder traversal ");
            inOrder(root);
            System.out.println();
            break;
        case 3:
            System.out.print("postOrder traversal ");
            postOrder(root);
            System.out.println();
            break;
        }
    }

以上的代码采用递归的方式实现三种遍历,为了方便我们使用,又写了一个traverse函数来实现选择哪种方式进行树的遍历。

这会儿就可以写单元测试了,我们首先创建一个二叉搜索树,然后分别使用“前序”,“中序”,“后序”来遍历输出树的所有节点。

    public static void main(String[] args)    //unit test
    {    
        BinarySearchTree tree=new BinarySearchTree();
        
        tree.insert(39);
        tree.insert(24);
        tree.insert(64);
        tree.insert(23);
        tree.insert(30);
        tree.insert(53);
        tree.insert(60);
        
        tree.traverse(1);
        tree.traverse(2);
        tree.traverse(3);
    }

运行该单元测试,可以看到如下的结果:

5.查找节点(find)

猜你喜欢

转载自www.cnblogs.com/yahuian/p/10813614.html
今日推荐