二叉树 非递归 遍历

先序遍历

先序遍历的顺序是 根 左孩子 右孩子

递归写法

public void dfs(Node node){
        if(node == null) {
            return;
        }
        System.out.println(node.val);
        dfs(node.left);
        dfs(node.right);
    }
}

递归的写法还是挺简单的,下面让我们看一下非递归的写法

非递归的写法

非递归与递归的不同点在于非递归需要一个栈来记录节点

先根遍历 是先打印根 那么我们就直接把根节点进行打印,然后把他的孩子节点加入栈中,
我们需要先打印左子树再打印右子树,而栈具有先进后出的特性,那么我们需要把右子树先压入栈中,之后在把左子树压入栈中。

        //先序遍历
        Stack<Node> assitStack = new Stack<>();//辅助栈
        assitStack.add(root);//把根节点压入栈中

        while (!assitStack.isEmpty()){
            Node popNode = assitStack.pop();
            System.out.println(popNode.val);
            if(popNode.right!=null){
                assitStack.add(popNode.right);//先压入右孩子
            }
            if(popNode.left!=null){
                assitStack.add(popNode.left);//再压左孩子
            }
        }

中序遍历

中序遍历的顺序是 左孩子 根 右孩子

递归写法

    public void dfs(Node node){
        if(node == null) {
            return;
        }
        dfs(node.left);
        System.out.println(node.val);
        dfs(node.right);
    }

非递归写法

中序遍历 比先序遍历还是稍微复杂一点。
因为我们先遍历左子树 所以我们不可以直接将节点抛弃,所以我们要判断什么时候将节点从栈中推出
所以我们需要一个辅助节点来记录还有没有左子树 如果没有那么我们就推出节点

        Stack<Node> midAssitStack = new Stack<>();
        Node assitNode = root;
        while (!midAssitStack.isEmpty()||assitNode!=null){
            if(assitNode!=null){
                //当左节点不为空那么我们就把左节点添加
                midAssitStack.add(assitNode);
                assitNode = assitNode.left;
            }else {
                Node tempNode = midAssitStack.pop();
                System.out.println(tempNode.val);
                assitNode = tempNode.right;

            }
        }

后序遍历

后序遍历的顺序是 左孩子 右孩子 根

递归写法

    public void dfs(Node node){
        if(node == null) {
            return;
        }
        dfs(node.left);
	    dfs(node.right);
        System.out.println(node.val);
    }

非递归写法

后序遍历的话,会更加的复杂一些。后序遍历和先序遍历还是比较像的,让我们来看一下先序遍历,先序遍历之所以会比较简单和清楚的是因为我们不需要关心已经读过的节点即父节点。在后序遍历中我们需要保存父节点的信息,因此我们需要多一个辅助栈来保存读过的节点。

我们知道后序遍历输出的顺序是: 左右根,那么第二个辅助栈的加入顺序是根右左。

其中根节点我们是直接插入的所以不需要加入栈一

那么栈一弹出顺序是右左,其加入顺序就是 左右(与先根相反)

       //后序遍历
        Stack<Node> backAssitStackOne = new Stack<>();
        Stack<Node> backAssitStackTwo = new Stack<>();
        backAssitStackOne.add(root);
        Node popNode;
        while (!backAssitStackOne.isEmpty()){
            popNode = backAssitStackOne.pop();
            backAssitStackTwo.add(popNode);
            if(popNode.left!=null){
                backAssitStackOne.add(popNode.left);
            }
            if(popNode.right!=null){
                backAssitStackOne.add(popNode.right);
            }
        }
        while (!backAssitStackTwo.isEmpty()){
            popNode = backAssitStackTwo.pop();
            System.out.println(popNode.val);
        }
posted @ 2021-12-23 15:55  度一川  阅读(76)  评论(0)    收藏  举报