图的遍历:深度优先遍历和广度优先遍历

图的遍历一般有两种方式:深度优先和广度优先。

深度优先(DFS)

深度优先遍历也叫深度优先搜索(Depth First Search)。它的遍历规则:不断地沿着顶点的深度方向遍历。顶点的深度方向是指它的邻接点方向。

具体点,给定一图G=,用visited[i]表示顶点i的访问情况,则初始情况下所有的visited[i]都为false。假设从顶点V0开始遍历,则下一个遍历的顶点是V0的第一个邻接点Vi,接着遍历Vi的第一个邻接点Vj,……直到所有的顶点都被访问过。

“第一个”是指在某种存储结构中(邻接矩阵、邻接表),所有邻接点中存储位置最近的,通常指的是下标最小的。按照某种规律的第一个。

遍历过程中通常有两种情况:
1、某个顶点的邻接点都已被访问过的情况,此时需回溯已访问过的顶点。
2、图不连通,所有的已访问过的顶点都已回溯完了,仍找不出未被访问的顶点。此时需从下标0开始检测visited[i],找到未被访问的顶点i,从i开始新一轮的深度搜索。

一般而言,接触到的大部分是连通图。

示例

图的遍历:深度优先遍历和广度优先遍历_第1张图片
从V0开始遍历:
遍历分析:V0有两个邻接点V1和V2,选择下标最小的V1遍历。接着从V1开始深度遍历,V1只有邻接点V3,也就是没有选的:遍历V3。接着从V3开始遍历,V3只有邻接点V0,而V0已经被遍历过。此时出现了上面提到的情况一,开始回溯V1,V1无未被遍历的邻接点,接着回溯V0,V0有一个未被遍历的邻接点V2,新的一轮深度遍历从V2开始。V2无邻接点,且无法回溯。此时出现了情况二,检测visited[i],只有V4了。深度遍历完成。
遍历序列是
V0->V1->V3->V2->V4。

实现(二叉树为例)

一般回溯的实现可以使用,也可以递归

栈实现:
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/

public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> lists=new ArrayList<Integer>();
        if(root==null)
            return lists;
        Stack<TreeNode> stack=new Stack<TreeNode>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode tree=stack.pop();
      //先往栈中压入右节点,再压左节点,这样出栈就是先左节点后右节点了。
            if(tree.right!=null)
                stack.push(tree.right);
            if(tree.left!=null)
                stack.push(tree.left);
            lists.add(tree.val);
        }
        return lists;
    }
}
递归实现

实际上是树的先序遍历

public void depthOrderTraversalWithRecursive()  
    {  
        depthTraversal(root);  
    }  
      
    private void depthTraversal(TreeNode tn)  
    {  
        if (tn!=null)   
        {  
            System.out.print(tn.value+"  ");  
            depthTraversal(tn.left);  
            depthTraversal(tn.right);  
        }         
    }

广度优先(BFS)

广度优先遍历也叫广度优先搜索(Breadth First Search)。它的遍历规则:
1、先访问完当前顶点的所有邻接点。(应该看得出广度的意思)
2、先访问顶点的邻接点先于后访问顶点的邻接点被访问。

具体点,给定一图G=,用visited[i]表示顶点i的访问情况,则初始情况下所有的visited[i]都为false。假设从顶点V0开始遍历,且顶点V0的邻接点下表从小到大有Vi、Vj…Vk。按规则1,接着应遍历Vi、Vj和Vk。再按规则2,接下来应遍历Vi的所有邻接点,之后是Vj的所有邻接点,…,最后是Vk的所有邻接点。接下来就是递归的过程…

在广度遍历的过程中,会出现图不连通的情况,此时也需按上述情况二来进行:测试visited[i]…。

示例

图的遍历:深度优先遍历和广度优先遍历_第2张图片
从V0开始遍历
遍历分析:V0有两个邻接点V1和V2,于是按序遍历V1、V2。V1先于V2被访问,于是V1的邻接点应先于V2的邻接点被访问,那就是接着访问V3。V2无邻接点,只能看V3的邻接点了,而V0已被访问过了。此时需检测visited[i],只有V4了。广度遍历完毕。
遍历序列是
V0->V1->V2->V3->V4。

实现(二叉树为例)

一般可以使用队列。(就是树的层次遍历)

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/

public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> lists=new ArrayList<Integer>();
        if(root==null)
            return lists;
        Queue<TreeNode> queue=new LinkedList<TreeNode>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode tree=queue.poll();
            if(tree.left!=null)
                queue.offer(tree.left);
            if(tree.right!=null)
                queue.offer(tree.right);
            lists.add(tree.val);
        }
        return lists;
    }
}

参考:
深度优先遍历和广度优先遍历
树的深度优先遍历和广度优先遍历java实现

你可能感兴趣的:(Java基础知识与理解,数据结构,算法,深度优先遍历,广度优先遍历)