二叉树遍历(广度、深度、递归、非递归)

开始

/**
 * 名词:
 * 		完全二叉树:1~h-1层节点数达到最大值,第 h层的节点连续集中在左侧;
 * 		满二叉树:高度 h,有 n=2^h-1个节点;
 * 		平衡二叉树:一颗空树 或 一颗左子树、右子树的高度差不超过 1
 * 					且子树都是平衡二叉树;
 * 		最优二叉树:哈夫曼树,树的带权路径长度最小;
 * 二叉搜索树的查找效率:
 * 		最坏情况:树形成了一个链表   O(n)
 *		 最好情况:平衡二叉树        O(lgn)
 * 		一般情况:1.386lgn        O(lgn)
 */

遍历

广度优先

    /**
     * 广度优先遍历:从根到叶、从左到右,根节点入队;
     * 访问队首,将节点的孩子入队,循环;
     */
    public void breadFirst() {
        IntBSTNode p = root;
        Queue<IntBSTNode> queue = new LinkedList<>();
        if (p != null) {
            queue.offer(p);
            while (!queue.isEmpty()) {
                p = queue.poll();
//                visit(p);
                System.out.print(p.key + " ");
                if (p.left != null)
                    queue.offer(p.left);
                if (p.right != null)
                    queue.offer(p.right);
            }
        }
    }

深度优先

前序

递归
    /**
     * 先序遍历,递归方法
     */
    public void preorder() {
        preorder(root);
    }

    public void preorder(IntBSTNode p) {
        if (p != null) {
            visit(p);
            preorder(p.left);
            preorder(p.right);
        }
    }
非递归
    /**
     * 前序遍历非递归方法:根节点、左孩子、右孩子
     * 遇见即进栈,并且输出,直到没有左孩子,回溯即弹栈,向栈顶元素的右孩子找
     *
     * @param root
     */
    public void noRecurPreorder(IntBSTNode root) {
        IntBSTNode now = root;
        Stack<IntBSTNode> stack = new Stack<>();
        while (now != null || !stack.empty()) {
            while (now != null) {
                stack.push(now);
                System.out.print(now.key + " ");
                now = now.left;
            }
            IntBSTNode top = stack.pop();
            now = top.right;
        }
    }

中序

递归
    /**
     * 中序遍历:递归式
     */
    public void inorder() {
        inorder(root);
    }

    public void inorder(IntBSTNode p) {
        if (p != null) {
            inorder(p.left);
            visit(p);
            inorder(p.right);
        }
    }
非递归
    /**
     * 中序遍历非递归方法:左孩子、根节点、右孩子,遇见即进栈,
     * 直到没有左孩子,才弹栈回溯(弹栈才输出),向栈顶元素的右孩子找
     *
     * @param root
     */
    public void noRecurInorder(IntBSTNode root) {
        Stack<IntBSTNode> stack = new Stack<>();
        IntBSTNode now = root;
        while (now != null || !stack.empty()) {
            while (now != null) {
                stack.push(now);
                now = now.left;
            }
            IntBSTNode top = stack.pop();
            System.out.print(top.key + " ");
            now = top.right;
        }
    }

后序

递归
    /**
     * 后序遍历:递归方法
     */
    public void postorder() {
        postorder(root);
    }

    public void postorder(IntBSTNode p) {
        if (p != null) {
            postorder(p.left);
            postorder(p.right);
            visit(p);
        }
    }
非递归
    /**
     * 后序遍历:非递归方法,左孩子、右孩子、根节点
     * 第一次遇见才进栈,并标记遇见一次(false),一直向左找直到null,开始回溯向右找,取栈顶元素,
     * 若只遇见一次(false),就标记遇见两次(true),访问栈顶元素右子树
     * 若遇见了2次(true),就可以弹栈输出了,他就没用啦~
     *
     * @param root
     */
    public void noRecurPostorder(IntBSTNode root) {
        Stack<IntBSTNode> stack = new Stack<>();
        HashMap<IntBSTNode, Boolean> hashMap = new HashMap<>();
        IntBSTNode now = root;
        while (now != null || !stack.empty()) {
            while (now != null && hashMap.get(now) == null) {
            //都是第一次,一直向左访问,进栈
                stack.push(now);
                hashMap.put(now, false);
                //null表示未访问过,false表示访问一次,true表示访问2次
                now = now.left;
            }
            IntBSTNode top = stack.peek();
            if (!hashMap.get(top)) {
            //若此节点访问过一次,说明左边访问完了还没看右边呢
                now = top.right;
                hashMap.put(top, true);
            } else {
            //若此节点访问2次,就可以输出了~,然后弹栈,没他的事情咯
                System.out.print(top.key + " ");
                stack.pop();
            }
        }
    }

树节点

package dataStructure.tree;
/******************IntBSTNode.java****************
 * binary search tree node of integers
 */
public class IntBSTNode {
    public int key;
    public IntBSTNode left, right;

    public IntBSTNode() {
        left = right = null;
    }

    public IntBSTNode(int el) {
        this(el, null, null);
    }

    public IntBSTNode(int el, IntBSTNode l, IntBSTNode r) {
        key = el;
        left = l;
        right = r;
    }
}

/*****************IntBST.java****************
 * binary search tree of integers 整数的二叉搜索树
 */
public class IntBST {
    public IntBSTNode root;

    public IntBST() {
        root = null;
    }

    public IntBST(IntBSTNode r) {
        root = r;
    }

    /**
     * 搜索二叉查找树:查找某个元素是否在树中,若是,返回节点,若不是,返回null
     *
     * @param el
     * @return
     */
    public IntBSTNode search(int el) {
        return search(root, el);
    }


    public IntBSTNode search(IntBSTNode p, int el) {
        while (p != null) {
            if (el == p.key)
                return p;
            else if (el < p.key)//当前元素小于节点的值,进入左子树查找
                p = p.left;
            else if (el > p.key)
                p = p.right;
        }
        return null;//没找到,返回null
    }

    public void visit(IntBSTNode p) {
        System.out.print(p.key + " ");
    }

    /**
     * 广度优先遍历:从根到叶、从左到右,根节点入队;
     * 访问队首,将节点的孩子入队,循环;
     */
    public void breadFirst() {
        IntBSTNode p = root;
        Queue<IntBSTNode> queue = new LinkedList<>();
        if (p != null) {
            queue.offer(p);
            while (!queue.isEmpty()) {
                p = queue.poll();
//                visit(p);
                System.out.print(p.key + " ");
                if (p.left != null)
                    queue.offer(p.left);
                if (p.right != null)
                    queue.offer(p.right);
            }
        }
    }
    /**
     * 深度优先遍历包含:先序、中序、后序
     */

    /**
     * 先序遍历,递归方法
     */
    public void preorder() {
        preorder(root);
    }

    public void preorder(IntBSTNode p) {
        if (p != null) {
            visit(p);
            preorder(p.left);
            preorder(p.right);
        }
    }

    /**
     * 前序遍历非递归方法:根节点、左孩子、右孩子
     * 遇见即进栈,并且输出,直到没有左孩子,回溯即弹栈,向栈顶元素的右孩子找
     *
     * @param root
     */
    public void noRecurPreorder(IntBSTNode root) {
        IntBSTNode now = root;
        Stack<IntBSTNode> stack = new Stack<>();
        while (now != null || !stack.empty()) {
            while (now != null) {
                stack.push(now);
                System.out.print(now.key + " ");
                now = now.left;
            }
            IntBSTNode top = stack.pop();
            now = top.right;
        }
    }

    /**
     * 中序遍历:递归式
     */
    public void inorder() {
        inorder(root);
    }

    public void inorder(IntBSTNode p) {
        if (p != null) {
            inorder(p.left);
            visit(p);
            inorder(p.right);
        }
    }

    /**
     * 中序遍历非递归方法:左孩子、根节点、右孩子,遇见即进栈,直到没有左孩子,才弹栈回溯(弹栈才输出),向栈顶元素的右孩子找
     *
     * @param root
     */
    public void noRecurInorder(IntBSTNode root) {
        Stack<IntBSTNode> stack = new Stack<>();
        IntBSTNode now = root;
        while (now != null || !stack.empty()) {
            while (now != null) {
                stack.push(now);
                now = now.left;
            }
            IntBSTNode top = stack.pop();
            System.out.print(top.key + " ");
            now = top.right;
        }
    }

    /**
     * 后序遍历:递归方法
     */
    public void postorder() {
        postorder(root);
    }

    public void postorder(IntBSTNode p) {
        if (p != null) {
            postorder(p.left);
            postorder(p.right);
            visit(p);
        }
    }

    /**
     * 后序遍历:非递归方法,左孩子、右孩子、根节点
     * 第一次遇见才进栈,并标记遇见一次(false),一直向左找直到null,开始回溯向右找,取栈顶元素,
     * 若只遇见一次(false),就标记遇见两次(true),访问栈顶元素右子树
     * 若遇见了2次(true),就可以弹栈输出了,他就没用啦~
     *
     * @param root
     */
    public void noRecurPostorder(IntBSTNode root) {
        Stack<IntBSTNode> stack = new Stack<>();
        HashMap<IntBSTNode, Boolean> hashMap = new HashMap<>();
        IntBSTNode now = root;
        while (now != null || !stack.empty()) {
            while (now != null && hashMap.get(now) == null) {//都是第一次,一直向左访问,进栈
                stack.push(now);
                hashMap.put(now, false);//null表示未访问过,false表示访问一次,true表示访问2次
                now = now.left;
            }
            IntBSTNode top = stack.peek();
            if (!hashMap.get(top)) {//若此节点访问过一次,说明左边访问完了还没看右边呢
                now = top.right;
                hashMap.put(top, true);
            } else {//若此节点访问2次,就可以输出了~,然后弹栈,没他的事情咯
                System.out.print(top.key + " ");
                stack.pop();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值