树的三种遍历方式源码(递归与非递归)

在面试的时候,我们会经常被问到树的三种遍历,也就是前序遍历、中序遍历和后序遍历。

所谓前序遍历,就是先访问根节点,再左,再右。命名方式就是根据根节点是在哪访问的去定义的。下面我们先用Java实现三种遍历的递归,是非常的简单。

树的前序遍历:

public void recursiveProOrder(Node root) {
    if (root != null) {
        System.out.print(root.value);
        if (root.left != null) {
            recursivePostOrder(root.left);
        }
        if (root.right != null) {
            recursivePostOrder(root.right);
        }
    }
}

树的中序遍历:

public void recursiveInOrder(Node root) {
    if (root != null) {
        if (root.left != null) {
            recursiveInOrder(root.left);
        }
        System.out.print(root.value);
        if (root.right != null) {
            recursiveInOrder(root.right);
        }
    }
}

树的后序遍历:

public void recursivePostOrder(Node root) {
    if (root != null) {
        if (root.left != null) {
            recursivePostOrder(root.left);
        }
        if (root.right != null) {
            recursivePostOrder(root.right);
        }
        System.out.print(root.value);
    }
}

下面介绍如何用非递归的方式进行遍历。所谓递归,其实在语言的底层层面上来讲,也是用栈来实现的,因此,要把递归的算法改为非递归,我们都可以考虑用栈来实现怎么操作。其中,前序和中序的非递归实现都比较容易,需要重点理解的是树的后序遍历的非递归实现。下面直接给出代码。

树的前序遍历(非递归):

public void preOrder(Node node)
{
    Stack<Node> stack = new Stack<>();
    while(node != null || !stack.empty())
    {
        while(node != null)
        {
            System.out.print(node.element + " ");
            stack.push(node);
            node = node.left;
        }    //while循环负责扫描所有当前结点,并判断有没有左子树
        if(!stack.empty())    //当stack为空的时候,说明没有左子树了
        {
            node = stack.pop();
            node = node.right;
        }
    }
}

树的中序遍历(非递归):

public void midOrder1(Node node)
{
    Stack<Node> stack = new Stack<>();
    while(node != null || !stack.empty())
    {
        while (node != null)
        {
            stack.push(node);
            node = node.left;
        }    //先压到树的最左下角的左子树
        if(!stack.empty())
        {
            node = stack.pop();
            System.out.print(node.element + " ");
            node = node.right;
        }
    }
}

树的后序遍历(非递归):

public void postOrder(Node node){
        if(node==null)
            return;
        Stack<Node> s = new Stack<Node>();

        Node curNode; //当前访问的结点
        Node lastVisitNode; //上次访问的结点
        curNode = node;
        lastVisitNode = null;

        //把currentNode移到左子树的最下边
        while(curNode!=null){
            s.push(curNode);
            curNode = curNode.getLchild();
        }
        while(!s.empty()){
            curNode = s.pop();  //弹出栈顶元素
            //一个根节点被访问的前提是:无右子树或右子树已被访问过
            if(curNode.getRchild() != null
                && curNode.getRchild() != lastVisitNode){
                //根节点再次入栈
                s.push(curNode);
                //进入右子树,且可肯定右子树一定不为空
                curNode = curNode.getRchild();
                while(curNode != null){
                    //再走到右子树的最左边
                    s.push(curNode);
                    curNode = curNode.getLchild();
                }
            }else{
                //访问
                System.out.println(curNode.getData());
                //修改最近被访问的节点
                lastVisitNode = curNode;
            }
        } //while
}

对于后序遍历的非递归实现,需要好好理解。

猜你喜欢

转载自blog.csdn.net/fengchi863/article/details/80246994