Depth-first traversal and breadth-first traversal of binary trees

Depth-first traversal (DFS) and breadth-first traversal (BFS) of binary trees

Java implementation of depth-first traversal and breadth-first traversal algorithm example of binary tree

The principle of depth-first traversal and breadth-first traversal of trees

 

Depth-first traversal (stack) and breadth-first traversal (queue) of binary trees

 

Depth - first traversal ( DFS ) and breadth-first traversal (BFS) of binary trees

 

Depth-first traversal: Starting from the root node, traverse vertically along the left subtree until a leaf node is found. Then go back to the previous node and traverse the right subtree node until all reachable nodes are traversed.

Depth-first traversal has first, middle, and post-order methods, and the method can be recursive and non-recursive

 

Breadth-first traversal: Starting from the root node, traverse the level of the binary tree vertically on the basis of traversing the level nodes of the binary tree horizontally. (Starting from the root node, traversing layer by layer)


DFS:ABDECFG

BFS:ABCDEFG

 

DFS implementation:

Data Structure: Stack

The parent node is pushed into the stack, the parent node is popped out, the right child node is pushed into the stack first, and then the left child node is pushed into the stack. Iterate through all nodes recursively

 

BFS implementation:

Data Structure: Queue

The parent node is queued, the parent node is dequeued, the left child node is queued first, and then the right child node is queued. Iterate through all nodes recursively

 

package com.test;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

/**
 * Tree traversal depth-first traversal: recursive and non-recursive breadth-first traversal:
 *
 */
public class PrintTree {
    public static void main(String[] args) {
 
        TreeNode tree = createTree();
        // System.out.println("递归方式先序遍历:");
        // ForeachTree.rePreTree(tree);
        
         //System.out.println("非递归方式先序遍历:");
         //ForeachTree.nRePreTree(tree);
         //System.out.println();
         //ForeachTree.nRePreTree2(tree);
        
        // System.out.println("递归方式中序遍历:");
         //ForeachTree.reInTree(tree);
         
        // System.out.println("非递归方式中序遍历:");
         ForeachTree.nReInTree(tree);
         
        // System.out.println("递归方式后序遍历:");
        // ForeachTree.reEndTree(tree);
         
        // System.out.println("非递归方式后序遍历:");
        // ForeachTree.nReEndTree(tree);
         
        //System.out.println("广度优先遍历:");
        //ForeachTree.BFSTree(tree);
    }
 
    /**
     * 创建一个用作测试的树
     * 
     * @return
     */
    public static TreeNode createTree() {
 
        /*
         * 示例: 
         *          1 
         *      2       3 
         *    4   5    6  7 
         *  8      9
         */
        TreeNode root = new TreeNode(1);
        TreeNode left1Tree = new TreeNode(2);
        TreeNode left2Tree = new TreeNode(4);
        TreeNode left3Tree = new TreeNode(8);
        TreeNode left4Tree = new TreeNode(6);
        TreeNode right1Tree = new TreeNode(5);
        TreeNode right2Tree = new TreeNode(9);
        TreeNode right3Tree = new TreeNode(3);
        TreeNode right4Tree = new TreeNode(7);
        left2Tree.leftNode = left3Tree;
        right1Tree.rightNode = right2Tree;
        left1Tree.leftNode = left2Tree;
        left1Tree.rightNode = right1Tree;
        right3Tree.leftNode = left4Tree;
        right3Tree.rightNode = right4Tree;
        root.leftNode = left1Tree;
        root.rightNode = right3Tree;
        return root;
 
    }
}
 
class ForeachTree {
 
    /**
     * 先序遍历:根左右的顺序--递归方式
     * 
     * @param tree
     */
    public static void rePreTree(TreeNode tree) {
        if (tree != null) {
            System.out.println(tree.val);
            rePreTree(tree.leftNode);
            rePreTree(tree.rightNode);
        }
    }
 
    /**
     * 先序遍历:根左右的顺序--非递归方式
     * 思路:
     * 1. 获取当前节点,首先输出当前节点,然后将其两个节点压入栈中,然后利用栈的先进后出的特性,弹出节点并获取其子节点
     * 2. 在此判断条件为当前节点不为空,若为空则直接结束本次循环然后进行下一次循环
     * @param tree
     */
    public static void nRePreTree(TreeNode tree) {
        // 创建栈,由于深度遍历是
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(tree);
        while (stack != null && !stack.isEmpty()) {
            TreeNode te = stack.pop();
            System.out.println(te.val);
            
            List<TreeNode> trees = te.getChildren();
            if(trees == null) continue;
            for(TreeNode t:trees) {
                if(t!=null) {
                    stack.push(t);
                }
            }
        }
 
    }
    
    public static void nRePreTree2(TreeNode tree) {
        // 创建栈,由于深度遍历是
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(tree);
        while (stack != null && !stack.isEmpty()) {
            TreeNode te = stack.pop();
            System.out.println(te.val);
          
            if(te.rightNode != null){
            	stack.push(te.rightNode);
            }
           
            
            if(te.leftNode != null){
            	stack.push(te.leftNode);
            }
            
        }
 
    }
 
    /**
     * 中序遍历:左根右的顺序--递归方式
     * 
     * @param tree
     */
    public static void reInTree(TreeNode tree) {
        if (tree != null) {
            reInTree(tree.leftNode);
            System.out.println(tree.val);
            reInTree(tree.rightNode);
        }
    }
 
    /**
     * 中序遍历:左根右的顺序--非递归方式
     * 思路:
     * 1. 由于中序遍历方式为左根右,所以先判断当前节点是否有左子节点,若有的话将当前节点的左子节点置为空(防止下次遍历到重复判
     * 断)再压入栈,然后将当前节点的左子节点压入栈,一次类推
     * 2. 直到当前节点没有左子节点时,输出当前节点的值,然后判断是否有右子节点,若有的话则继续进行压栈操作(在此有一技巧之处在
     * 于若该节点的左右子节点都没有的话,则不需要将当前节点压入栈--在第一次获取当前节点时已经将当前节点弹出了)
     * 3. 注:只有在当前节点有左子节点时需要将当前节点压入栈,因为遍历顺序为左中右,所以在当前节点有左节点时,需要再进行回根节
     * 点查找输出根节点的值,若当前节点没有左节点时,则不需要记录上一节点
     * @param tree
     */
    public static void nReInTree(TreeNode tree) {
        // 创建栈,由于深度遍历是
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(tree);
        while(stack != null && !stack.isEmpty()) {
            TreeNode root = stack.pop();
            if(root.leftNode != null) {
                TreeNode left = root.leftNode;
                root.leftNode = null;
                stack.push(root);
                stack.push(left);
            }else {
                System.out.println(root.val);
                if(root.rightNode != null) {
                    TreeNode right = root.rightNode;
                    stack.push(right);
                }
            }
        }
    }
    

 
    /**
     * 后序遍历:左右根的顺序--递归方式
     * 
     * @param tree
     */
    public static void reEndTree(TreeNode tree) {
        if (tree != null) {
            reEndTree(tree.leftNode);
            reEndTree(tree.rightNode);
            System.out.println(tree.val);
        }
    }
 
    /**
     * 后序遍历:左右根的顺序--非递归方式
     * 
     * @param tree
     */
    public static void nReEndTree(TreeNode tree) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(tree);
        while( stack != null && !stack.isEmpty()) {
 
            TreeNode root = stack.pop();
            if(root.leftNode != null) {
                TreeNode left = root.leftNode;
                root.leftNode = null;
                stack.push(root);
                stack.push(left);
            }else if(root.rightNode != null) {
                TreeNode right = root.rightNode;
                root.rightNode = null;
                stack.push(root);
                stack.push(right);
            }else {
                System.out.println(root.val);
            }
        }
    }
 
    /**
     * 广度优先遍历
     * 
     * @param tree
     */
    public static void BFSTree(TreeNode tree) {
        Deque<TreeNode> queue = new ArrayDeque<TreeNode>();
        queue.push(tree);
        while (queue != null && !queue.isEmpty()) {
            TreeNode root = queue.pop();
            System.out.println(root.val);
            
            if (root.leftNode != null) {
                queue.add(root.leftNode);
            }
            if (root.rightNode != null) {
                queue.add(root.rightNode);
            }
        }
    }
 
}
 
class TreeNode {
 
    int val;
 
    public TreeNode(int val) {
        this.val = val;
    }
 
    TreeNode leftNode;
    TreeNode rightNode;
 
    /**
     * 获取该节点的所有左右子节点-先右后左
     * 由于所有遍历方式都是从左向右的顺序,所以压入栈时需要先将右子节点压入,后将左子节点压入,
     * 因此在此获取子节点时先添加右子节点,后添加左子节点
     * @return
     */
    public List<TreeNode> getChildren() {
        List<TreeNode> list = new LinkedList<TreeNode>();
        if (this.rightNode != null)
            list.add(this.rightNode);
        if (this.leftNode != null)
            list.add(this.leftNode);
        return list.size() == 0 ? null : list;
    }
 
}

 。。

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326011061&siteId=291194637