二叉树的前序/中序/后序遍历[非递归方式]

package tree.binarytree;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.Stack;

/**
 * Created by Lanxiaowei
 * Craated on 2016/12/12 17:14
 * 采用二叉排序树的中序遍历实现对一个无序的数字序列进行排序
 */
public class TestBinarySortTree2 {

    public static void main(String[] args) {
        //测试100次
        //test(100);

        test2();
    }

    public static void test2() {
        BinarySortTreeNode parentNode = new BinarySortTreeNode(5);

        BinarySortTreeNode c3 = new BinarySortTreeNode(3);
        BinarySortTreeNode c6 = new BinarySortTreeNode(6);
        BinarySortTreeNode c1 = new BinarySortTreeNode(1);
        BinarySortTreeNode c4 = new BinarySortTreeNode(4);

        BinarySortTreeNode c8 = new BinarySortTreeNode(8);
        BinarySortTreeNode c9 = new BinarySortTreeNode(9);

        c8.left = c3;
        c8.right = c6;

        c9.left = c1;
        c9.right = c4;

        parentNode.left = c8;
        parentNode.right = c9;

        //中序遍历二叉树(非递归方式)
        Queue<Integer> queue = parentNode.midOrderWithoutRecursive(parentNode);
        while (!queue.isEmpty()) {
            int i = queue.poll();
            System.out.print(i + " ");
        }

        System.out.println();
        //前序遍历二叉树(非递归方式)
        queue = parentNode.preOrderWithoutRecursive(parentNode);
        while (!queue.isEmpty()) {
            int i = queue.poll();
            System.out.print(i + " ");
        }
        System.out.println();

        //后序遍历二叉树(非递归方式)
        queue = parentNode.postOrderWithoutRecursive(parentNode);
        while (!queue.isEmpty()) {
            int i = queue.poll();
            System.out.print(i + " ");
        }
        System.out.println();

        //后序遍历二叉树(非递归方式)-->另一种实现
        queue = parentNode.postorderTraversal(parentNode);
        while (!queue.isEmpty()) {
            int i = queue.poll();
            System.out.print(i + " ");
        }
        System.out.println();
        System.out.println("/**********************华丽的分割线 end**************************/\n");
    }

    /**
     * 测试方法
     * @param times    测试的总次数
     */
    public static void test(int times) {
        if(times <= 0) {
            throw new IllegalArgumentException("The number [times] MUST be greater than zero.");
        }

        while(times-- > 0) {
            System.out.println("/**********************华丽的分割线 begin************************/");
            int min = 1;
            int max = 100;
            //先随机生成一个随机数作为二叉树的父节点
            int parentVal = random(min,max);
            //打印生成的parent节点数值
            System.out.println("Parent:" + parentVal);
            //创建二叉树的父节点
            BinarySortTreeNode parentNode = new BinarySortTreeNode(parentVal);
            //假设我们的无序数字序列的长度n=10,这里我们随机生成无序数字序列里的每个数字,然后插入二叉树结构中
            int n = 10;
            //用于存储每个子节点的数值
            int num = 0;
            //这里之所以是n - 2,是因为我们已经生成了父节点,剩下我们只需要生成n - 1个子节点,
            //而i是从零开始的,因此这里是n - 2
            for(int i=0; i < n - 2; i++) {
                //随机生成每个子节点的数值
                num = random(min,max);
                System.out.println("Child:" + num);
                //创建每个子节点
                BinarySortTreeNode child = new BinarySortTreeNode(num);
                //往二叉排序树里插入子节点
                parentNode.insert(parentNode,child);
            }

            //中序遍历二叉树(非递归方式)
            Queue<Integer> queue = parentNode.midOrderWithoutRecursive(parentNode);
            while (!queue.isEmpty()) {
                int i = queue.poll();
                System.out.print(i + " ");
            }

            System.out.println();
            //前序遍历二叉树(非递归方式)
            queue = parentNode.preOrderWithoutRecursive(parentNode);
            while (!queue.isEmpty()) {
                int i = queue.poll();
                System.out.print(i + " ");
            }
            System.out.println();

            //后序遍历二叉树(非递归方式)
            queue = parentNode.postOrderWithoutRecursive(parentNode);
            while (!queue.isEmpty()) {
                int i = queue.poll();
                System.out.print(i + " ");
            }
            System.out.println();
            System.out.println("/**********************华丽的分割线 end**************************/\n");
        }
    }

    /**
     * 二叉排序树的每个节点
     */
    public static class BinarySortTreeNode {
        //左子节点
        private BinarySortTreeNode left;
        //右子节点
        private BinarySortTreeNode right;
        /**节点上的值*/
        private int val;

        public BinarySortTreeNode() {}

        public BinarySortTreeNode(int val) {
            this.val = val;
        }

        /**
         * 往指定的父节点上插入一个子节点
         * @param parentNode    父节点
         * @param newNode       待插入的节点
         * @return
         */
        public boolean insert(BinarySortTreeNode parentNode, BinarySortTreeNode newNode) {
            if(null == newNode) {
                throw new IllegalArgumentException("The Node to be inserted MUST NOT be null.");
            }
            if(null == parentNode) {
                parentNode = newNode;
                return true;
            }
            //若待插入的节点数值大于等于父节点,则待插入的newNode此时应该在右边
            if(parentNode.val <= newNode.val) {
                //如果父节点此刻的右树为空,那么就将待插入的newNode作为父节点右树的父节点
                if(parentNode.right == null) {
                    parentNode.right = newNode;
                    return true;
                } else {
                    //如果父节点的右树不为空,那么就插入到右树的父节点下
                    return insert(parentNode.right, newNode);
                }
            }
            //若待插入的节点数值大于等于父节点,则待插入的newNode此时应该在左边
            if(parentNode.val > newNode.val) {
                //如果父节点此刻的左树为空,那么就将待插入的newNode作为父节点左树的父节点
                if(parentNode.left == null) {
                    parentNode.left = newNode;
                    return true;
                } else {
                    //如果父节点的左树不为空,那么就插入到左树的父节点下
                    return insert(parentNode.left, newNode);
                }
            }
            return false;
        }

        /**
         * 在指定的父节点为parentNode的二叉树下查找是否存在一个数字x
         * @param parentNode  二叉树的父节点
         * @param x           待查找的数字x
         * @return
         */
        public boolean search(BinarySortTreeNode parentNode, int x) {
            //如果二叉树为null,直接return false
            if(null == parentNode) {
                return false;
            }
            //此时说明找到数字x了,直接return true
            if(parentNode.val == x) {
                return true;
            }
            //此时应该在右子树中查找
            if(parentNode.val < x) {
                return search(parentNode.right,x);
            }
            //此时应该在左子树中查找
            if(parentNode.val > x) {
                return search(parentNode.left,x);
            }
            return false;
        }

        /**
         * 中序遍历(递归方式实现)
         * @param parentNode
         */
        public void midorder(BinarySortTreeNode parentNode){
            if(null == parentNode) {
                return;
            }
            midorder(parentNode.left);
            System.out.print(parentNode.val + " ");
            midorder(parentNode.right);
        }

        /**
         * 二叉树前序遍历(非递归方式)
         * @param parentNode
         * @return
         */
        public Queue<Integer> preOrderWithoutRecursive(BinarySortTreeNode parentNode) {
            Stack<BinarySortTreeNode> stack = new Stack<BinarySortTreeNode>();
            Queue<Integer> queue = new LinkedList<Integer>();
            BinarySortTreeNode currentParent = parentNode;

            //当前节点非空或者Stack非空时执行
            while(currentParent != null || !stack.isEmpty()) {
                //先放父节点
                queue.add(currentParent.val);
                stack.push(currentParent);
                //然后遍历左子树
                currentParent = currentParent.left;
                while(currentParent == null && !stack.isEmpty()){
                    currentParent = stack.peek();
                    stack.pop();
                    //然后遍历右子树
                    currentParent = currentParent.right;
                }
            }
            return queue;
        }

        /**
         * 二叉树后序遍历(非递归方式)
         * 这种后序遍历实现方式相比postorderTraversal实现而言,性能更高效
         * 左子树 右子树 中间父节点
         * @param parentNode
         * @return
         */
        public Queue<Integer> postOrderWithoutRecursive(BinarySortTreeNode parentNode) {
            long start = System.nanoTime();
            Queue<Integer> queue = new LinkedList<Integer>();
            BinarySortTreeNode dummy = new BinarySortTreeNode(0);
            dummy.left = parentNode;
            BinarySortTreeNode cur = dummy;
            BinarySortTreeNode pre = null;
            while (cur != null) {
                if (cur.left == null) {
                    cur = cur.right;
                } else {
                    pre = cur.left;
                    while (pre.right != null && pre.right != cur) {
                        pre = pre.right;
                    }
                    if (pre.right == null) {
                        pre.right = cur;
                        cur = cur.left;
                    } else {
                        reverse(cur.left, pre);
                        BinarySortTreeNode temp = pre;
                        while (temp != cur.left) {
                            queue.add(temp.val);
                            temp = temp.right;
                        }
                        queue.add(temp.val);
                        reverse(pre, cur.left);
                        pre.right = null;
                        cur = cur.right;
                    }
                }
            }
            long end = System.nanoTime();
            System.out.println("postOrderWithoutRecursive take " + (end - start) + " ns");
            return queue;
        }

        /**
         * 二叉树后序遍历(非递归方式)
         * @param root
         * @return
         */
        public Queue<Integer> postorderTraversal(BinarySortTreeNode root) {
            long start = System.nanoTime();
            Queue<Integer> result = new LinkedList<Integer>();
            Stack<BinarySortTreeNode> stack = new Stack<BinarySortTreeNode>();
            BinarySortTreeNode prev = null;
            BinarySortTreeNode curr = root;
            if (root == null) {
                return result;
            }
            stack.push(root);
            while (!stack.empty()) {
                curr = stack.peek();
                if (prev == null || prev.left == curr || prev.right == curr) {
                    if (curr.left != null) {
                        stack.push(curr.left);
                    } else if (curr.right != null) {
                        stack.push(curr.right);
                    }
                }
                //从左子树往上遍历
                else if (curr.left == prev) {
                    if (curr.right != null) {
                        stack.push(curr.right);
                    }
                }
                //从右子树往上遍历
                else {
                    result.add(curr.val);
                    stack.pop();
                }
                prev = curr;
            }
            long end = System.nanoTime();
            System.out.println("postorderTraversal take " + (end - start) + " ns");
            return result;
        }

        /**
         * 二叉树的中序遍历(非递归方式)
         * @param parentNode
         * @return
         */
        public Queue<Integer> midOrderWithoutRecursive(BinarySortTreeNode parentNode) {
            Stack<BinarySortTreeNode> stack = new Stack<BinarySortTreeNode>();
            Queue<Integer> queue = new LinkedList<Integer>();
            BinarySortTreeNode currentParent = parentNode;
            BinarySortTreeNode node = null;
            while(currentParent != null || !stack.isEmpty()){
                stack.push(currentParent);
                //先遍历左子树
                currentParent = currentParent.left;
                //currentParent == null表明左子树已经遍历完,此时应该输出中间的父节点
                while(currentParent == null && !stack.isEmpty()){
                    currentParent = stack.peek();
                    node = stack.pop();
                    //保存中间的父节点
                    queue.add(node.val);
                    //最后遍历右子树
                    currentParent = currentParent.right;
                }
            }
            return queue;
        }

        public void reverse(BinarySortTreeNode start, BinarySortTreeNode end) {
            if (start == end) {
                return;
            }
            BinarySortTreeNode pre = start;
            BinarySortTreeNode cur = start.right;
            BinarySortTreeNode next;
            while (pre != end) {
                next = cur.right;
                cur.right = pre;
                pre = cur;
                cur = next;
            }
        }
    }

    /**
     * 生成[min,max)区间内的随机数
     * @param min
     * @param max
     * @return
     */
    public static int random(int min,int max) {
        Random random = new Random();
        return random.nextInt(max)%(max - min + 1) + min;
    }
}

猜你喜欢

转载自iamyida.iteye.com/blog/2344554
今日推荐