二叉树的遍历方式

文章目录

      • 什么是树的遍历
      • 遍历的种类
        • 深度优先
        • 广度优先
      • 代码实现
        • 深度优先
          • 前序遍历
          • 中序遍历
          • 后序遍历
        • 广度优先

什么是树的遍历

​ 树的遍历是图的遍历的一种,指的是按照某种规则,** 不重复地访问 **某种树的所有节点的过程。

遍历的种类

​ 由于从给定的某个节点出发,有多个可以前往的下一个节点(树不是线性数据结构),所以在顺序计算(即非并行计算)的情况下, 只能推迟对某些节点的访问 ——即以某种方式保存起来以便稍后再访问。常见的做法是采用栈(LIFO)或队列(FIFO)。

由于树本身是一种自我引用(即递归定义)的数据结构,因此很自然也可以用递归方式来实现延迟节点的保存。

深度优先

​ 深度优先搜索算法(Depth-First-Search,DFS)沿着树的深度遍历树的节点**,尽可能深的搜索树的分支**。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索

​ 深度优先可进一步按照根节点相对于左右子节点的访问先后来划分。如果把左节点和右节点的位置固定不动,那么根节点放在左节点的左边,称为前序(pre-order)、根节点放在左节点和右节点的中间,称为中序(in-order)、根节点放在右节点的右边,称为后序(post-order)。

广度优先

广度优先搜索算法(Breadth-First-Search,BFS),又译作宽度优先搜索,或横向优先搜索,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。给定一组已排序的子节点,其“广度优先”的遍历 只有一种唯一 的结果。

代码实现

深度优先

二叉树如下:

前序遍历:1->2->4->5->3->6

中序遍历:4->2->5->1->3->6

后序遍历:4->5->2->6->3->1

生成二叉树

public class Test5 {

    //创建节点类
    public class TreeNode{
        private int data;
        private TreeNode leftNode;
        private TreeNode rightNode;

        public TreeNode(int data, TreeNode leftNode, TreeNode rightNode) {
            this.data = data;
            this.leftNode = leftNode;
            this.rightNode = rightNode;
        }

        public int getData() {
            return data;
        }

        public void setData(int data) {
            this.data = data;
        }

        public TreeNode getLeftNode() {
            return leftNode;
        }

        public void setLeftNode(TreeNode leftNode) {
            this.leftNode = leftNode;
        }

        public TreeNode getRightNode() {
            return rightNode;
        }

        public void setRightNode(TreeNode rightNode) {
            this.rightNode = rightNode;
        }

    }


    /**
     * 二叉树的初始化时需要注意从下面的子节点开始创建
     * @return 返回根节点
     */
    public TreeNode init(){
        TreeNode D = new TreeNode(4, null, null);
        TreeNode E = new TreeNode(5, null, null);
        TreeNode H = new TreeNode(6, null, null);
        TreeNode B = new TreeNode(2, D, E);
        TreeNode C = new TreeNode(3, null, H);
        TreeNode A = new TreeNode(1, B, C);//A为根节点
       return A;
    }

}

前序遍历
 /**
     * 先序遍历:root->left->right
     * @param root
     * @return
     */
    ArrayList<Integer> preOrderlist = new ArrayList<>();//要注意将这个数组放在方法的外部,因为这是一个全局变量
   public ArrayList<Integer> preOrder(TreeNode root){
        if(root == null) return null;

        preOrderlist.add(root.getData());
        if(root.getLeftNode() != null) preOrder(root.getLeftNode());
        if(root.getRightNode() != null) preOrder(root.getRightNode());

        return preOrderlist;
    }

  public static void main(String[] args){
        Test5 test5 = new Test5();
        TreeNode root = test5.init();
        ArrayList<Integer> list = test5.preOrder(root);
        System.out.println("preOrder");
        for(int i = 0; i < list.size(); i++){
            System.out.print(list.get(i)+"->");
        }

    }
    /**
     * preOrder
     1->2->4->5->3->6
     */

贴上错误代码予以警示?

    public ArrayList<Integer> preOrder(TreeNode root){

        while (root != null){//这里事实上是个死循环啊?,如果是最后一个节点,它虽然没有孩子,但是它本身永远都不会为null呀
            preOrderlist.add(root.getData());
            if(root.getLeftNode() != null) preOrder(root.getLeftNode());
            if(root.getRightNode() != null) preOrder(root.getRightNode());
        }

        return preOrderlist;
    }
中序遍历
   /**
     * 中序遍历:left->root->right
     * @param root
     * @return
     */
ArrayList<Integer> inOrderlist = new ArrayList<>();//要注意将这个数组放在方法的外部,因为这是一个全局变量
    public ArrayList<Integer> InOrder(TreeNode root) {
       if(root.leftNode != null){
           InOrder(root.getLeftNode());
       }
        inOrderlist.add(root.getData());
       
       if(root.rightNode != null){
           InOrder(root.getRightNode());
       }
        return inOrderlist;
    }

同样贴上一个错误代码予以警示?

 public ArrayList<Integer> InOrder(TreeNode root) {
       if(root.leftNode != null){
           InOrder(root.getLeftNode());
       }else {//第一次写的时候这里加了else,真的是智障,难道不知道这样的话就是返回所有左节点为空的节点了吗
           inOrderlist.add(root.getData());
       }

       if(root.rightNode != null){
           InOrder(root.getRightNode());
       }
        return inOrderlist;
    }
后序遍历
 /**
     * 后序遍历left->right->root
     * @param root
     * @return
     */
 ArrayList<Integer> postOrderList = new ArrayList<Integer>();
    public ArrayList<Integer> postOrder(TreeNode root){
        if(root.getLeftNode() != null){
            postOrder(root.getLeftNode());
        }
        if(root.getRightNode() != null){
            postOrder(root.getRightNode());
        }
        postOrderList.add(root.getData());

        return postOrderList;
    }

广度优先

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

二叉树的遍历方式_第1张图片

  ArrayList<TreeNode> leverTraversalList = new ArrayList<TreeNode>();

    /**
     *广度优先遍历(层次遍历)
     * @param root
     * @return
     */
    public ArrayList<TreeNode> leverTraversal(TreeNode root){
        //创建一个队列用于存储当前节点的左右节点
        LinkedList<TreeNode> queue =  new LinkedList<TreeNode>();
        queue.add(root);

        while (!queue.isEmpty()){//注意终止条件
            //如果queue不为空就弹出第一个节点
            TreeNode currentNode = queue.pollFirst();
            leverTraversalList.add(currentNode);
            if(currentNode.getLeftNode() != null){
                queue.addLast(currentNode.getLeftNode());
            }
            if(currentNode.getRightNode() != null){
                queue.addLast(currentNode.getRightNode());

            }
        }
        return leverTraversalList;
    }

转载于:https://www.cnblogs.com/flyingcr/p/10428296.html

你可能感兴趣的:(二叉树的遍历方式)