每一个节点恰好被遍历一次

发布时间:2025-06-24 17:06:41  作者:北方职教升学中心  阅读量:289


空间复杂度取决于递归的栈深度,而栈深度在二叉树为一条链的情况下会达到 O(n) 的级别

 迭代方式:

class Solution {    public List<Integer> inorderTraversal(TreeNode root) {        List<Integer> res = new ArrayList<Integer>();        Stack<TreeNode> stack = new Stack<>();        while (root != null || !stack.isEmpty()) {            while (root != null) {                stack.push(root);                root = root.left;            }            root = stack.pop();            res.add(root.val);            root = root.right;        }        return res;    }}

子循环中root遍历到root左子树最深层次过程中,依次将左结点压栈,左结点为空退出子循环,将栈顶元素出栈, root=root.right重新进入大循环既可遍历该树所有结点。中序遍历和后序遍历的简单递归方法不附图讲解,主要解释它们的迭代方式及层序遍历


1、

  • 中序遍历(左根右)

        首先遍历左子树,然后访问根结点,最后遍历右子树。前序遍历

递归方式:

迭代方式: 

2、

  • 后序遍历(左右根)

        首先遍历左子树,然后遍历右子树,最后访问根结点。


4、

递归方式

class Solution {    List<List<Integer>> result=new ArrayList<>();    public List<List<Integer>> levelOrder(TreeNode root) {        order(root,0);        return result;    }    public void order(TreeNode node,int deep)    {        if(node==null)return;        deep++;        if(result.size()<deep)        {            List<Integer> item=new ArrayList<>();            result.add(item);        }        result.get(deep-1).add(node.val);        order(node.left,deep);        order(node.right,deep);    }}

在方法void order(TreeNode node,int deep) ,传相应的结点和二维数组下标,设置节点对应位置

加图理解: 

时间复杂度;O(n) 

迭代方式: 

代码设计重点:出栈既遍历。该结点无右结点  2、

class Solution {    public List<Integer> postorderTraversal(TreeNode root) {        List<Integer> res = new ArrayList<Integer>();        postorder(root, res);        return res;    }    public void postorder(TreeNode root, List<Integer> res) {        if (root == null) {            return;        }        postorder(root.left, res);        postorder(root.right, res);        res.add(root.val);    }}

复杂度分析

时间复杂度:O(n),其中 n 是二叉搜索树的节点数。

空间复杂度:O(n),为递归过程中栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)。进入子循环前,用size记录栈内元素,进入子循环后,依次将栈顶元素弹出,同时将不为空的左右结点入,size--;

class Solution {    public List<List<Integer>> levelOrder(TreeNode root) {        List<List<Integer>> res=new ArrayList<>();        if(root==null)        return res;        Queue<TreeNode> queue=new LinkedList<>();        queue.offer(root);        while(!queue.isEmpty()){            int size=queue.size();            List<Integer> list=new ArrayList<>();            while(size--!=0){                TreeNode top=queue.poll();                list.add(top.val);               if(top.left!=null)               queue.offer(top.left);                if(top.right!=null)                queue.offer(top.right);            }            res.add(list);        }        return res;    }}

时间复杂度;O(n)

二叉树的遍历结束

迭代方式: 

迭代的方式实现方法一的递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码。二叉树的遍历中每个节点会被访问一次且只会被访问一次。

class Solution {    public List<Integer> preorderTraversal(TreeNode root) {        List<Integer> res = new ArrayList<Integer>();        preorder(root, res);        return res;    }    public void preorder(TreeNode root, List<Integer> res) {        if (root == null) {            return;        }        res.add(root.val);        preorder(root.left, res);        preorder(root.right, res);    }}

复杂度分析

时间复杂度:O(n)其中 n 是二叉树的节点数。

上篇已经了解对二叉树有了大概了解,本篇学习二叉树的前序、每一个节点恰好被遍历一次。每一个节点恰好被遍历一次。      

  它是按广度优先搜索的策略,从根结点出发,依次访问每一层上的节点。

空间复杂度:O(n),为迭代过程中显式栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)。节点内容加 1)。该结点的右结点已遍历

      if (root.right == null || root.right == prev) {

                res.add(root.val);

                stack.pop();

                prev = root;//用prev指向root,表示已被遍历

                root = null;

           } else 

                root = root.right;

        }

        return res;

    }

}

如上图情况,若if条件语句不判断 D.right ( K )是否被上次遍历则会陷入K出栈压栈无限循环中

复杂度分析 

时间复杂度:O(n),其中 n 是二叉搜索树的节点数。

空间复杂度:O(n)。层序遍历

递归方式

迭代方式: 


二叉树的前序、在结点出栈时,同时将不为空的左右结点入栈。前序遍历

递归方式:

定义 preorder(root) 表示当前遍历到 root 节点的答案。访问结点所做的操作依赖于具体的应用问题(比如:打印节点内容、层序遍历

即逐层地,从左到右访问所有节点。

空间复杂度:O(n)。 遍历是二叉树上最重要的操作之一,是二叉树上进行其它运算之基础。

class Solution {    public List<Integer> inorderTraversal(TreeNode root) {        List<Integer> res = new ArrayList<Integer>();        inorder(root, res);        return res;    }    public void inorder(TreeNode root, List<Integer> res) {        if (root == null) {            return;        }        inorder(root.left, res);        res.add(root.val);        inorder(root.right, res);    }}

复杂度分析

时间复杂度:O(n),其中 n 为二叉树节点的个数。后序及层序遍历的递归与非递归共7种遍历方法,快收藏吧~

目录

1、这种策略在实际应用中使用较多,如在计算机图形学中用于渲染场景图等。按照定义,我们只要递归调用 postorder(root->left) 来遍历 root 节点的左子树,然后递归调用 postorder(root->right) 来遍历 root 节点的右子树,最后将 root 节点的值加入答案即可,递归终止的条件为碰到空节点。 


3、二叉树的遍历中每个节点会被访问一次且只会被访问一次。

空间复杂度:O(n),为递归过程中栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)。空间复杂度取决于栈深度,而栈深度在二叉树为一条链的情况下会达到 O(n) 的级别。按照定义,我们只要首先将 root 节点的值加入答案,然后递归调用 preorder(root.left) 来遍历 root 节点的左子树,最后递归调用 preorder(root.right) 来遍历 root 节点的右子树即可,递归终止的条件为碰到空节点。后序遍历:

递归方式

迭代方式:

4、例如对于二叉树:后序遍历的结果为:8->9->4->10->11->5->2->6->7->3->1。中序、

  • 层序遍历

   自上而下,自左至右逐层访问树的结点的过程就是层序遍历。每一个节点恰好被遍历一次。

迭代方式:

我们也可以用迭代的方式实现方法一的递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码(为了更好的注释,代码放入块引用中)

class Solution {

    public List<Integer> postorderTraversal(TreeNode root) {

        List<Integer> res = new ArrayList<Integer>();

        if (root == null) {

            return res;

       }

        Stack <TreeNode> stack = new Stack<>();

        TreeNode prev = null;

        while (root != null || !stack.isEmpty()) {

            while (root != null) {

                stack.push(root);

                root = root.left;

           }

            root = stack.peek();//  取栈顶元素

//因为是后序遍历,当前结点有无右结点决定它是否打印

//所以取出栈顶元素,判断有无右结点

         //而打印当前结点情况分为两种,1、中序、中序遍历

递归方式:

 迭代方式:

3、

时间复杂度:O(n),其中 n 是二叉树的节点数。例如对于二叉树:层次遍历的结果为:1->2->3->4->5->6->7->8->9->10->11

下面讲解代码,前序遍历、


2、

class Solution {    public List<Integer> preorderTraversal(TreeNode root) {        List<Integer> res = new ArrayList<>();        if(root==null) return res;        Stack<TreeNode> stack = new Stack<>();        stack.push(root);        while(!stack.isEmpty()){            TreeNode p = stack.pop();            res.add(p.val);            if(p.right!=null)            stack.push(p.right);            if(p.left!=null            )stack.push(p.left);        }        return res;    }}

注释: 先将root压栈,进入 while 循环,每循环一次栈顶出栈一次并记录该结点,将其左结点右结点压栈,栈为空退出循坏。例如对于二叉树:先序遍历的结果为:1->2->4->8->9->5->10->11->3->6->7。

二叉树的遍历方法有以下四种 :

  • 先序遍历(根左右)

        首先访问根结点,然后递归地遍历左子树,最后遍历右子树。每一个节点恰好被遍历一次。后序遍历

递归方式

定义 postorder(root) 表示当前遍历到 root 节点的答案。

时间复杂度:O(n),其中 n 为二叉树节点的个数。中序遍历

递归方式:

定义 inorder(root) 表示当前遍历到 root 节点的答案,那么按照定义,我们只要递归调用 inorder(root.left) 来遍历 root 节点的左子树,然后将 root 节点的值加入答案,再递归调用inorder(root.right) 来遍历 root 节点的右子树即可,递归终止的条件为碰到空节点。

空间复杂度:O(n),为迭代过程中显式栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)。例如对于二叉树:中序遍历的结果为:8->4->9->2->10->5->11->1->6->3->7。后序及层序遍历的递归与非递归遍历方法

遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结 点均做一次且仅做一次访问