8、二分搜索树便利(中篇)

一、二分搜索树便利的介绍

     在我们实现二分搜索树中,我们学习了好多的知识,二分搜索树当中,我觉得最重要的是实现树的便利和查找操作。

实现二分搜索树的便利,我们有两种不同的实现方式。

1、第一种,递归实现。

(1)、先序便利,我们可以通过先输出根节点,然后便利左子树,最后便利右子树。

(2)、中序便利,我们可以先便利左子树,然后输出根节点,最后输出右子树。

(3)、后续便利,我们是可以先便利左子树,然后便利右子树,最后便利根节点。

下面 是它们的实现代码。

    /**
     * 前序遍历
     */
    public void preOrder() {
        preOrder(root);
    }

    public void preOrder(Node node) {  // 当前节点  左   右
        if (node == null) {
            return;
        }
        System.out.println(node.e);
        preOrder(node.left);
        preOrder(node.right);
    }
  /**
     * 中序便利
     */
    public void inOrder() {
        inOrder(root);
    }

    private void inOrder(Node node) {
        if (node == null) return;
        inOrder(node.left);    //左 当前 右
        System.out.println(node.e);
        inOrder(node.right);

    }
    /**
     * 后序便利
     */
    public void postOrder() {

        postOrder(root);
    }

    //左子树  右子树  当前节点
    private void postOrder(Node node) {
        if (node == null) return;
        postOrder(node.left);    //左 右 当前
        postOrder(node.right);
        System.out.println(node.e);
    }

2、非递归实现

1、前序便利的基本思想,我们可以利用栈来实现

第一步,首先把树的根元素,加入我们的栈中。

第二步,然后判断栈是不是空、然后弹出栈顶元素,并打印输出。

第三步,判断弹出的右孩子是不是空,不为null,就压入栈顶元素。

第四步,判断弹出的左孩子是不是空,不为空,就压入栈顶元素。

    public void preOrderDq() {
        if (root == null) {
            return;
        }
        Stack<Node> stack = new Stack<Node>();
        stack.push(root);
        while (!stack.isEmpty()) {
            Node node = stack.pop();
            System.out.println(node.e);
            //如果右子树不为null 压人栈中。
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }
    }

2、中序便利的基本思想,我们可以利用栈来实现

第一步,首先把树的根元素,加入我们的栈中,然后把树的根节点的左子树,复制给当前节点。

第二步,判断栈是不是空,或者说当前元素是不是空,只要是栈不为null,或者当前元素不为null。我们进入循环。

第三步,判断当前元素是不是空,如果不空,我们就把它压入栈顶。当前元素,就变成它的左孩子。

如果为null 的话,弹出栈顶元素,然后,当前元素变成它的右孩子。继续执行第二步。

基本思想是,先把左子树,全部压入栈中,然后弹出来,并打印。然后判断右子树是不是存在,存在就也压入栈中。


    /**
     * 非递归实现中序便利。
     * 我们主要是先便利左子树,依次压入栈中。
     * 然后,弹出栈顶的元素,并打印出来。
     * 然后,判断弹出元素的右子树为不为null。
     * 不为null ,就压人栈中,又判断该元素的左子树为不为null。
     */
    public void dgInOrder() {
        if (root == null) return;
        Stack<Node> stack = new Stack<Node>();
        stack.push(root);
        Node cur = root.left;
        while (!stack.isEmpty() || cur != null) {  //如果左孩子不为null  或者栈也不为 null
            if (cur != null) {  //如果 cur 为 null ,必须栈顶还有元素。
                stack.push(cur);
                cur = cur.left;
            } else {
                cur = stack.pop();  //弹出一个元素
                System.out.println(cur.e);
                cur = cur.right;
            }
        }
        stack.push(root);

    }

3、后序便利的基本思想,我们可以利用栈来实现

我的基本实现方式和前序基本一样。我们只是把 前序便利,访问根节点   然后左子树,最后右节点。改成了  先根节点 ,然后右节点,最后左节点。然后我们利用栈,把顺序反过来,就变成后续便利,先左子树,然后右子树,最后根节点。

 

 //1、非递归实现后续便利。
    //基本思想:左  右  根  我们可以用两个栈来实现。
    //利用  根右左的思想实现。
    public void DgpostOrder() {
        Stack<Node> stack = new Stack<Node>();
        Stack<Node> stack2 = new Stack<Node>();
        if (root == null) {
            return;
        }
        Node node = root;
        stack.push(node);  //栈为null
        while (!stack.isEmpty()) {
            node = stack.pop();
            stack2.push(node);
            if (node.left != null) {
                stack.push(node.left);
            }
            if (node.right != null) {
                stack.push(node.right);
            }
        }
        while (!stack2.isEmpty()) {
            System.out.println(stack2.pop());
        }
    }

3、层次便利的实现

 我们是利用队列来实现的,基本实现思路。

第一步,我们把根 元素入队列。

第二步,我们判断队列是不是空,队列不为空,我们就弹出队首元素,

第三步,然后判断队首元素的左孩子为不为空,不为空就压入队列中。

第四步,然后判断队首元素的右孩子为不为空,不为空就压入队列中。依次第二步。

 

    // 二分搜索树的层序遍历
    public void levelOrder(){

        if(root == null)
            return;

        Queue<Node> q = new LinkedList<>();
        q.add(root);
        while(!q.isEmpty()){
            Node cur = q.remove();
            System.out.println(cur.e);

            if(cur.left != null)
                q.add(cur.left);
            if(cur.right != null)
                q.add(cur.right);
        }
    }

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值