对二叉树遍历其实是将二叉树中的节点(非线性结构)以线性序列访问的过程。
如果二叉树是顺序结构(数组)保存的,直接遍历底层数组即可;
如果二叉树是用链表保存节点的,有下面两类遍历方式:
1) 深度优先遍历:先访问到树中最深层次的节点。有如下3种方式:
- 先(前)序遍历
- 中序遍历
- 后序遍历
2) 广度优先遍历:逐层访问每层节点,即先访问根节点,然后第二层节点……,所以又被称为按层遍历。
由于二叉树的定义本身就有“递归性”,所以深度优先遍历能非常方便地利用递归来遍历每个节点:依次遍历一个非空二叉树的根、左子树和右子树,就完成了整个二叉树的遍历。
1 深度优先遍历
1.1 先序遍历
先序遍历指先处理根节点,然后访问左右子树,遍历步骤如下:
1) 访问根节点
2) 递归遍历左子树
3) 递归遍历右子树
先序遍历的示例如下:
public List<TreeNode> preIterator(){
return preIterator(root);
}
private List<TreeNode> preIterator(TreeNode node){
List<TreeNode> list = new ArrayList<TreeNode>();
// 处理根节点
list.add(node);
// 递归左子树
if(node.left != null){
list.addAll(preIterator(node.left));
}
// 递归右子树
if(node.right != null){
list.addAll(preIterator(node.right));
}
return list;
}
1.2 中序遍历
中序遍历指先处理左右子树,然后访问根节点、左右子树,遍历步骤如下:
扫描二维码关注公众号,回复:
868523 查看本文章
1) 递归遍历左子树
2) 访问根节点
3) 递归遍历右子树
中序遍历的示例如下:
public List<TreeNode> midIterator(){
return midIterator(root);
}
private List<TreeNode> midIterator(TreeNode node){
List<TreeNode> list = new ArrayList<TreeNode>();
// 递归左子树
if(node.left != null){
list.addAll(midIterator(node.left));
}
// 处理根节点
list.add(node);
// 递归右子树
if(node.right != null){
list.addAll(midIterator(node.right));
}
return list;
}
1.3 后序遍历
后序遍历指最后处理根节点,遍历步骤如下:
1) 递归遍历左子树
2) 递归遍历右子树
3) 访问根节点
后序遍历的示例如下:
public List<TreeNode> postIterator(){
return postIterator(root);
}
private List<TreeNode> postIterator(TreeNode node){
List<TreeNode> list = new ArrayList<TreeNode>();
// 递归左子树
if(node.left != null){
list.addAll(postIterator(node.left));
}
// 递归右子树
if(node.right != null){
list.addAll(postIterator(node.right));
}
// 处理根节点
list.add(node);
return list;
}
2 广度优先遍历
广度优先遍历可以通过队列来实现,步骤如下:
1) 创建一个队列,把根节点添加至队列;
2) 从队列中取出根节点,然后把该节点的左右节点添加至队列,若没有子节点,说明已经到达叶子节点;
3) 重复执行第二步,直到队列为空,此时说明所有的叶子节点都经过了队列,即完成了遍历。
对二叉树的广度遍历,利用Queue对象的特性,可以方便的实现二叉树的广度优先遍历,程序如下:
public List<TreeNode> breadthFirst(){
Queue<TreeNode> nodeQueue = new ArrayDeque<TreeNode>();
List<TreeNode> nodeList = new ArrayList<TreeNode>();
if(root != null){
// 添加根元素至队列
nodeQueue.offer(root);
}
while(!nodeQueue.isEmpty()){
// 将队列的“顶部”元素添加至list
nodeList.add(nodeQueue.peak());
TreeNode tn = nodeQueue.poll();
// 将左子树节点加入队列
if(tn.left != null){
nodeQueue.offer(tn.left);
}
// 将右子树节点加入队列
if(tn.right != null){
nodeQueue.offer(tn.right);
}
}
return nodeList;
}
参考资料:
疯狂Java:突破程序员基本功的16课-树和二叉树(第11课)