算法 二叉树的各种遍历

二叉树的遍历方式基本就是前序遍历,中序遍历,后序遍历和层次遍历。从代码的角度来说,前三种最简单的就是用递归了,代码会非常简洁。但是递归有一个缺陷,就是当二叉树的节点非常多的时候,层次深的递归会不停的进行程序的压栈和出栈操作,效率比较低。这里就不写递归算法了,只写四种遍历的非递归算法。

先定义二叉树的节点如下:

/**

* Definition for binary tree

* public class TreeNode {

*     int val;

*     TreeNode left;

*     TreeNode right;

*     TreeNode(int x) { val = x; }

* }

*/

前序中序后序三种非递归算法都要借助于栈来实现,层次遍历要借助于队列实现。

前序遍历

Given a binary tree, return the preorder traversal of its nodes‘ values.

For example:

Given binary tree {1,#,2,3},

   1
         2
    /
   3

return [1,2,3].

前序遍历在四种之中最简单,就是先把根节点进栈,然后一直出栈并不断把当前节点的右儿子和左儿子依次进栈。注意,必须先右儿子后左儿子。代码如下,

public List<Integer> preorderTraversal(TreeNode root) {

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

if(root==null)

{

return list;

}

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

stack.push(root);

while(!stack.empty())

{

TreeNode node=stack.pop();

list.add(node.val);

if(node.right!=null)

{

stack.push(node.right);

}

if(node.left!=null)

{

stack.push(node.left);

}

}

return list;

}

中序遍历

Given a binary tree, return the inorder traversal of its nodes‘ values.

For example:

Given binary tree {1,#,2,3},

   1
         2
    /
   3

return [1,3,2].

先将根节点进栈,然后不停的找到当前节点的左儿子节点,知道没有左儿子,然后当前节点出栈,访问,右儿子进栈。

public List<Integer> inorderTraversal(TreeNode root) {

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

if(root==null)

{

return list;

}

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

stack.push(root);

while(!stack.empty())

{

TreeNode node=null;

while((node=stack.peek())!=null)

{

stack.push(node.left);

}

stack.pop();

if(!stack.empty()){

node=stack.pop();

list.add(node.val);

stack.push(node.right);

}

}

return list;

}

后序遍历

Given a binary tree, return the postorder traversal of its nodes‘ values.

For example:

Given binary tree {1,#,2,3},

   1
         2
    /
   3

return [3,2,1].

后序遍历复杂一些,需要先访问左右再访问父节点,这需要记录一下上一个访问的节点是哪个,如果当前节点的左右儿子都为空,则当前节点是叶子节点;如果上一个节点是当前节点的左儿子,说明当前节点没有右儿子;如果上一个节点是当前节点的右儿子,说明当前节点的子孙已经访问完。这两种情况下,当前节点就是下一个要访问的节点。将当前节点出栈,访问。如果不是上述情况,则依次将右儿子和左儿子进栈。

public List<Integer> postorderTraversal(TreeNode root) {

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

if(root==null)

{

return list;

}

TreeNode pre=null;

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

stack.push(root);

while(!stack.empty())

{

TreeNode node=stack.peek();

if((node.left==null&&node.right==null)||(pre!=null&&(pre==node.left||pre==node.right)))

{

list.add(node.val);

pre=node;

stack.pop();

}

else

{

if(node.right!=null)

{

stack.push(node.right);

}

if(node.left!=null)

{

stack.push(node.left);

}

}

}

return list;

}

层次遍历

Given a binary tree, return the level order traversal of its nodes‘ values. (ie, from left to right, level by level).

For example:

Given binary tree {3,9,20,#,#,15,7},

    3
   /   9  20
    /     15   7

return its level order traversal as:

[
  [3],
  [9,20],
  [15,7]
]

层次遍历需要借助队列结构,队列是想FIFO的结构,和层次遍历的书序正好一致。

本题的描述比一般的层次遍历更复杂一些,不但要层次遍历,还要每个层单独的一个list。这里定义一个变量count,初始值为1,表示当前层次的节点数。这样在循环的时候,只要遍历了count个节点就表示当前层次的节点都访问完了。

public List<List<Integer>> levelOrder(TreeNode root) {

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

LinkedList<TreeNode> queue=new LinkedList<TreeNode>();

if(root==null)

{

return result;

}

int count=0;

queue.add(root);

count=1;

while(queue.size()!=0)

{

int temp=0;

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

for(int i=0;i<count;i++)

{

TreeNode node=queue.poll();

if(node!=null)

{

list.add(node.val);

if(node.left!=null)

{

queue.add(node.left);

temp++;

}

if(node.right!=null)

{

queue.add(node.right);

temp++;

}

}

}

result.add(list);

count=temp;

}

return result;

}

以上所有的代码都在LeetCode测试并通过。

时间: 2024-09-20 01:08:44

算法 二叉树的各种遍历的相关文章

python数据结构与算法——二叉树结构与遍历方法

先序遍历,中序遍历,后序遍历 ,区别在于三条核心语句的位置 层序遍历  采用队列的遍历操作第一次访问根,在访问根的左孩子,接着访问根的有孩子,然后下一层 自左向右一一访问同层的结点 # 先序遍历 # 访问结点,遍历左子树,如果左子树为空,则遍历右子树, # 如果右子树为空,则向上走到一个可以向右走的结点,继续该过程 preorder(t):    if t:       print t.value       preorder t.L       preorder t.R # 中序遍历 # 从根

算法与数据结构基础4:C++二叉树实现及遍历方法大全

binary search tree,中文翻译为二叉搜索树.二叉查找树或者二叉排序树.简称为BST. 本文集齐了二叉树的五大遍历算法:先序遍历.中序遍历.后序遍历.深度优先遍历和广度优先遍历(同层遍历也就是深度优先遍历). // BSTree.h #include <cstdio> #include <iostream> #include <stack> #include <queue> using namespace std; // binary sear

笔试算法题(37):二叉树的层序遍历 &amp; 最长递增的数字串

出题:要求层序遍历二叉树,从上到下的层次,每一层访问顺序为从左到右,并将节点一次编号,输出如下:如果只要求打印指定的level的节点,应该如何实现. a b  c d  e  f  g h  i  分析: 原始的层序遍历类似于BFS,打印当前访问的节点curNode的序列号,并将其直接子节点放入队列queue中,然后从queue中取出下一个节点,直 到队列为空:此方法仅能按照层序打印所有节点,并不能区分每一层节点的数量:如果需要区分当前层次的节点,和当前层次节点的子节点,可以使用两个队列 que

算法学习笔记 二叉树和图遍历—深搜 DFS 与广搜 BFS

图的深搜与广搜 马上又要秋招了,赶紧复习下基础知识.这里复习下二叉树.图的深搜与广搜.从图的遍历说起,图的遍历方法有两种:深度优先遍历(Depth First Search), 广度优先遍历(Breadth First Search),其经典应用走迷宫.N皇后.二叉树遍历等.遍历即按某种顺序访问"图"中所有的节点,顺序分为: 深度优先(优先往深处走),用的数据结构是栈, 主要是递归实现: 广度优先(优先走最近的),用的数据结构是队列,主要是迭代实现: 对于深搜,由于递归往往可以方便的利

【LeetCode-面试算法经典-Java实现】【094-Binary Tree Inorder Traversal(二叉树中序遍历)】

[094-Binary Tree Inorder Traversal(二叉树中序遍历)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given a binary tree, return the inorder traversal of its nodes' values. 题目大意 对一棵二叉树进行中序遍历. 解题思路 解法一:递归实现,解法二:迭代实现. 代码实现 二叉树结点类 public class TreeNode { int val; TreeNod

数据结构 《22》---- 二叉树三种遍历的迭代器算法

二叉树的三种遍历有递归版本,和迭代版本.本文介绍一种新的思路. 参考了 http://coolshell.cn/articles/9886.html 在许多应用中,我们还需要对遍历本身进行抽象.假如有一个求和的函数sum,我们希望它能应用于链表,数组,二叉树等等不同的数据结构.这时,我们可以抽象出迭代器(Iterator)的概念,通过迭代器把算法和数据结构解耦了,使得通用算法能应用于不同类型的数据结构. 以下给出了三种遍历的迭代器算法. class Iterator { public: virt

[数据结构与算法] 二叉树及其遍历方式

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4289830.html 一.数据结构分类 (一)按逻辑结构 集合(无辑关系) 线性结构(线性表):数组.链表.栈.队列 非线性结构:树.图.多维数组 (二)按存储结构 顺序(数组)储结构.链式储结构.索引储结构.散列储结构 二.二叉树相关性质

二叉树的各种遍历算法-leetcode Binary Tree Postorder Traversal 扩展

二叉树的各种遍历方法有  前序遍历   中序遍历    后序遍历  层序遍历.其中前三种遍历有递归程序可以实现,但是我们也有必要掌握其非递归版本的算法实现.正好在leetcode中遇到了遍历二叉树的问题,今天在这里一并总结了. 首先,引用leetcode中关于二叉树节点的定义. 1 // Definition for binary tree 2 struct TreeNode { 3 int val; 4 TreeNode *left; 5 TreeNode *right; 6 TreeNode

二叉树几种遍历算法的非递归实现

二叉树遍历的非递归实现 相对于递归遍历二叉树,非递归遍历显得复杂了许多,但换来的好处是算法的时间效率有了提高.下面对于我学习非递归遍历二叉树算法的过程进行总结 为了便于理解,这里以下图的二叉树为例,分析二叉树的三种遍历方式的实现过程. 一.非递归实现二叉树的前序遍历 不借助递归,要实现二叉树的前序遍历,我们需要用到前面学过的栈这种数据结构.根据前序遍历的定义,先访问根节点,再访问左子树,最后访问右子树.声明指向节点的指针pCur,我们可以先访问根节点,之后让根节点进栈,并让pCur在左子树上移动