11.3 遍历二叉树方法整理

对二叉树遍历其实是将二叉树中的节点(非线性结构)以线性序列访问的过程。

如果二叉树是顺序结构(数组)保存的,直接遍历底层数组即可;
如果二叉树是用链表保存节点的,有下面两类遍历方式:

1) 深度优先遍历:先访问到树中最深层次的节点。有如下3种方式:

  1. 先(前)序遍历
  2. 中序遍历
  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 中序遍历

中序遍历指先处理左右子树,然后访问根节点、左右子树,遍历步骤如下:

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课)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值