二分搜索树前序遍历非递归写法

使用栈实现非递归的前序遍历二分搜索树,除了根节点root外先入栈右节点,后入栈左节点。

package blacktv.tree;

import java.util.Stack;

/**
 * 二分搜索树,传入的泛型必须实现Comparable接口,保证具有可比较性
 */
public class BinarySearchTree<E extends Comparable<E>> {
    private Node root;//根节点
    private Integer size = 0;

    /**
     * 使用栈实现非递归实现前序遍历
     */
    public void preOrderNR() {
        Stack<Node> stack = new Stack<>();
        stack.push(root); //将根节点压入栈1)
        for (Integer i = 0; i < size; i++) {
            Node buffer = stack.pop();
            System.out.println(buffer.e);//访问节点
            if (buffer.right != null)
                stack.push(buffer.right);//先让右子树入栈
            if (buffer.left != null)
                stack.push(buffer.left);//再让左子树入栈
        }
    }

    /**
     * 用内部类屏蔽具体的实现细节
     */
    private class Node {
        public E e;
        public Node left, right;

        public Node(E e) {
            this.e = e;
            left = null;
            right = null;
        }
    }
}

 

小案例:

package blacktv.tree;

import blacktv.stack.LinkedListStack;

import java.util.Stack;

/**
 * 二分搜索树,传入的泛型必须实现Comparable接口,保证具有可比较性
 */
public class BinarySearchTree<E extends Comparable<E>> {
    private Node root;//根节点
    private Integer size = 0;

    /**
     * 添加元素
     *
     * @param e
     */
    public void add(E e) {
        //根节点为空则本次添加为首次添加
        if (root == null) {
            root = new Node(e);
            size++;
        } else
            this.add(root, e);//调用添加方法
    }

    /**
     * 向以node为根的二分搜索树中插入节点,递归算法.
     * 改进后,改进的理念是null也视为二分搜索树
     * 由于Node是内部类以及递归的特殊性设置为private
     *
     * @param node
     * @param e
     * @return
     */
    private Node add(Node node, E e) {
        if (node == null) {
            size++;
            return new Node(e);//返回要添加的节点
        }
        //递归部分,小于去左子树,大于去右子树,等于则什么都不做
        if (e.compareTo(node.e) < 0)
            node.left = this.add(node.left, e);//将递归返回结果添加到左节点
        else if (e.compareTo(node.e) > 0)
            node.right = this.add(node.right, e);//将递归返回结果添加到右节点
        return node;
    }

    /**
     * 向以node为根的二分搜索树中插入节点,递归算法.
     * 改进前的算法,比较臃肿,已废弃
     * 由于Node是内部类以及递归的特殊性设置为private
     *
     * @param node
     * @param e
     */
    private void add_old(Node node, E e) {
        //递归的终止条件
        if (node.equals(e))
            return;// 如果重复则不改变二分搜索树
        else if (e.compareTo(node.e) < 0 && node.left == null) {
            // 如果e小于本节点,且左节点为空,则e为本节点的左节点
            node.left = new Node(e);
            size++;
            return;
        } else if (e.compareTo(node.e) > 0 && node.right == null) {
            // 如果e大于本节点,且右节点为空,则e为本节点的右节点
            node.right = new Node(e);
            size++;
            return;
        }

        //递归部分,小于去左子树,大于去右子树
        if (e.compareTo(node.e) < 0)
            this.add_old(node.left, e);
        else
            this.add_old(node.right, e);
    }

    /**
     * 查询二分搜索树中是否包含此元素
     *
     * @param e
     * @return
     */
    public Boolean contains(E e) {
        if (root == null)
            return false;
        else
            return this.contains(root, e);
    }

    /**
     * 递归查找二分搜索树中是否包含该元素
     * 由于Node是内部类以及递归的特殊性设置为private
     *
     * @param node
     * @param e
     * @return
     */
    private Boolean contains(Node node, E e) {
        if (node == null)
            return false;//代表该二分搜索树中不存在该元素
        else if (e.compareTo(node.e) < 0)
            return this.contains(node.left, e);//小于去左子树找
        else if (e.compareTo(node.e) > 0)
            return this.contains(node.right, e);//大于去右子树找
        else
            return true;//等于则返回true
    }

    /**
     * 二分搜索树的前序遍历入口
     */
    public void preOrder() {
        this.preOrder(root);
    }

    /**
     * 前序遍历二分搜索树
     * 由于Node是内部类以及递归的特殊性设置为private
     *
     * @param node
     */
    private void preOrder(Node node) {
        if (node == null)
            return;
        System.out.println(node.e);
        this.preOrder(node.left);
        this.preOrder(node.right);
    }

    /**
     * 使用栈实现非递归实现前序遍历
     */
    public void preOrderNR() {
        Stack<Node> stack = new Stack<>();
        stack.push(root);//将根节点压入栈
        for (Integer i = 0; i < size; i++) {
            Node buffer = stack.pop();
            System.out.println(buffer.e);//访问节点
            if (buffer.right != null)
                stack.push(buffer.right);//先让右子树入栈
            if (buffer.left != null)
                stack.push(buffer.left);//再让左子树入栈
        }
    }

    /**
     * 二分搜索树的中序遍历入口
     */
    public void inOrder() {
        this.inOrder(root);
    }

    /**
     * 中序遍历的递归方法
     * 由于Node是内部类以及递归的特殊性设置为private
     *
     * @param node
     */
    private void inOrder(Node node) {
        if (node == null)
            return;
        this.inOrder(node.left);
        System.out.println(node.e);
        this.inOrder(node.right);
    }

    /**
     * 二分搜索树后续遍历的入口
     */
    public void postOrder() {
        this.preOrder(root);
    }

    /**
     * 二分搜索树后续遍历的递归方法
     * 由于Node是内部类以及递归的特殊性设置为private
     *
     * @param node
     */
    private void postOrder(Node node) {
        if (node == null)
            return;
        this.postOrder(node.left);
        this.postOrder(node.right);
        System.out.println(node.e);
    }

    @Override
    public String toString() {
        StringBuilder binarySearchTree = new StringBuilder();
        this.toString(root, 0, binarySearchTree);
        return binarySearchTree.toString();
    }

    /**
     * 用前序遍历的方法生成该二分搜索树的字符串
     * 由于Node是内部类以及递归的特殊性设置为private
     *
     * @param node  当前节点
     * @param depth 操作数,从0开始
     * @return
     */
    private void toString(Node node, Integer depth, StringBuilder binarySearchTree) {
        if (node == null) {
            binarySearchTree.append(this.generateDepthString(depth) + "null\n");
            return;
        }
        binarySearchTree.append(this.generateDepthString(depth) + node.e + "\n");
        this.toString(node.left, depth + 1, binarySearchTree);
        this.toString(node.right, depth + 1, binarySearchTree);
    }

    /**
     * 为toString方法生成可看出二叉树深浅的字符串
     *
     * @param depth
     * @return
     */
    private String generateDepthString(Integer depth) {
        String buffer = "";
        for (Integer i = 0; i < depth; i++)
            buffer += "--";
        return buffer;
    }

    /**
     * 获取size
     *
     * @return
     */
    public Integer getSize() {
        return size;
    }

    /**
     * 当前的二分搜索树是否为空
     *
     * @return
     */
    public Boolean isEmpty() {
        return size == 0;
    }

    /**
     * 用内部类屏蔽具体的实现细节
     */
    private class Node {
        public E e;
        public Node left, right;

        public Node(E e) {
            this.e = e;
            left = null;
            right = null;
        }
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值