Java数据结构----图--深度优先遍历BFS和广度优先遍历DFS

本文详细介绍了图的两种基本遍历算法——广度优先搜索(BFS)与深度优先搜索(DFS),并通过具体的代码实现展示了这两种算法的工作原理。文章不仅解释了算法的思想,还提供了递归和非递归的实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文来自:http://blog.youkuaiyun.com/ochangwen/article/details/50729993


一、图的遍历

广度优先搜索BFS( Breadth-first search) 算法思想
(1)顶点v入队列。
(2)当队列非空时则继续执行,否则算法结束。
(3)出队列取得队头顶点v;访问顶点v并标记顶点v已被访问。
(4)查找顶点v的第一个邻接顶点col。
(5)若v的邻接顶点col未被访问过的,则col入队列。
(6)继续查找顶点v的另一个新的邻接顶点col,转到步骤(5)。直到顶点v的所有未被访问过的邻接点处理完。转到步骤(2)。

深度优先搜索DFS(depth-first search) 算法思想:
(1)Start 顶点 v选择一个与v相邻的未被访问的顶点w
(2)并从w出发以深度优先搜索
(3)若一个顶点u的所有相邻顶点都被访问过了,则退回到最近被访问过、且有未被访问的w顶点!!!
(4)然后从w出发继续进行深度优先搜索
(5)当从任何已经访问的顶点出发,不再有未访问的顶点时,搜索终止

图的深度优先遍历:1->2->4->6->5->3
图的广度优先遍历:1->2->3->4->5->6

具体实现代码如下:

[java]  view plain  copy
  1. public class GraphByMatrix {  
  2.     public static final boolean UNDIRECTED_GRAPH = false;//无向图标志  
  3.     public static final boolean DIRECTED_GRAPH = true;//有向图标志  
  4.   
  5.     public static final boolean ADJACENCY_MATRIX = true;//邻接矩阵实现  
  6.     public static final boolean ADJACENCY_LIST = false;//邻接表实现  
  7.   
  8.     public static final int MAX_VALUE = Integer.MAX_VALUE;  
  9.     private boolean graphType;  
  10.     private boolean method;  
  11.     private int vertexSize;  
  12.     private int matrixMaxVertex;  
  13.   
  14.     //存储所有顶点信息的一维数组  
  15.     private Object[] vertexesArray;  
  16.     //存储图中顶点之间关联关系的二维数组,及边的关系  
  17.     private int[][] edgesMatrix;  
  18.   
  19.     // 记录第i个节点是否被访问过  
  20.     private boolean[] visited;  
  21.   
  22.     /** 
  23.      * @param graphType 图的类型:有向图/无向图 
  24.      * @param method    图的实现方式:邻接矩阵/邻接表 
  25.      */  
  26.     public GraphByMatrix(boolean graphType, boolean method, int size) {  
  27.         this.graphType = graphType;  
  28.         this.method = method;  
  29.         this.vertexSize = 0;  
  30.         this.matrixMaxVertex = size;  
  31.   
  32.         if (this.method) {  
  33.             visited = new boolean[matrixMaxVertex];  
  34.             vertexesArray = new Object[matrixMaxVertex];  
  35.             edgesMatrix = new int[matrixMaxVertex][matrixMaxVertex];  
  36.   
  37.             //对数组进行初始化,顶点间没有边关联的值为Integer类型的最大值  
  38.             for (int row = 0; row < edgesMatrix.length; row++) {  
  39.                 for (int column = 0; column < edgesMatrix.length; column++) {  
  40.                     edgesMatrix[row][column] = MAX_VALUE;  
  41.                 }  
  42.             }  
  43.   
  44.         }  
  45.     }  
  46.   
  47.     /** 
  48.      * 深度优先搜索DFS(depth-first search),递归 
  49.      */  
  50.     public void DFS() {  
  51.         //这里是从第一上添加的顶点开始搜索  
  52.         DFS(vertexesArray[0]);  
  53.     }  
  54.   
  55.     public void DFS(Object obj) {  
  56.         int index = -1;  
  57.         for (int i = 0; i < vertexSize; i++) {  
  58.             if (vertexesArray[i].equals(obj)) {  
  59.                 index = i;  
  60.                 break;  
  61.             }  
  62.         }  
  63.         if (index == -1) {  
  64.             throw new NullPointerException("没有这个值: " + obj);  
  65.         }  
  66.   
  67.         for (int i = 0; i < vertexSize; i++) {  
  68.             visited[i] = false;  
  69.         }  
  70.   
  71.         //这里要想清楚,不能放下面if else的后面!  
  72.         traverse(index);  
  73.   
  74.         //graphType为true为有向图  
  75.         if (graphType) {  
  76.             for (int i = 0; i < vertexSize; i++) {  
  77.                 if (!visited[i])  
  78.                     traverse(i);  
  79.             }  
  80.         }  
  81.   
  82.     }  
  83.   
  84.     // 深度优先就是由开始点向最深处遍历,没有了就回溯到上一级顶点  
  85.     private void traverse(int i) {  
  86.         visited[i] = true;  
  87.         System.out.print(vertexesArray[i] + " ");  
  88.   
  89.         //由于是递归,如果j=-1,该方法仍然会运行,会回溯到上一级顶点!!!  
  90.         for (int j = firstAdjVex(i); j >= 0; j = nextAdjVex(i, j)) {  
  91.             if (!visited[j]) {  
  92.                 traverse(j);  
  93.             }  
  94.         }  
  95.   
  96.     }  
  97.   
  98.     /** 
  99.      * 广度优先遍历算法 Breadth-first search(非递归) 
  100.      */  
  101.     public void BFS() {  
  102.         // LinkedList实现了Queue接口 FIFO  
  103.         Queue<Integer> queue = new LinkedList<Integer>();  
  104.         for (int i = 0; i < vertexSize; i++) {  
  105.             visited[i] = false;  
  106.         }  
  107.   
  108.         //这个循环是为了确保每个顶点都被遍历到  
  109.         for (int i = 0; i < vertexSize; i++) {  
  110.             if (!visited[i]) {  
  111.                 queue.add(i);  
  112.                 visited[i] = true;  
  113.                 System.out.print(vertexesArray[i] + " ");  
  114.   
  115.                 while (!queue.isEmpty()) {  
  116.                     int row = queue.remove();  
  117.   
  118.                     for (int k = firstAdjVex(row); k >= 0; k = nextAdjVex(row, k)) {  
  119.                         if (!visited[k]) {  
  120.                             queue.add(k);  
  121.                             visited[k] = true;  
  122.                             System.out.print(vertexesArray[k] + " ");  
  123.                         }  
  124.                     }  
  125.   
  126.                 }  
  127.             }  
  128.         }  
  129.     }  
  130.   
  131.     private int firstAdjVex(int row) {  
  132.         for (int column = 0; column < vertexSize; column++) {  
  133.             if (edgesMatrix[row][column] == 1)  
  134.                 return column;  
  135.         }  
  136.         return -1;  
  137.     }  
  138.   
  139.     private int nextAdjVex(int row, int k) {  
  140.         for (int j = k + 1; j < vertexSize; j++) {  
  141.             if (edgesMatrix[row][j] == 1)  
  142.                 return j;  
  143.         }  
  144.         return -1;  
  145.     }  
  146.   
  147.     /*********************************************************************/  
  148.     // 深度非递归遍历  
  149.     public void DFS2() {  
  150.         Stack<Integer> stack = new Stack<Integer>();  
  151.         for (int i = 0; i < vertexSize; i++) {  
  152.             visited[i] = false;  
  153.         }  
  154.         for (int i = 0; i < vertexSize; i++) {  
  155.             if (!visited[i]) {  
  156.                 stack.add(i);  
  157.                 // 设置第i个元素已经进栈  
  158.                 visited[i] = true;  
  159.                 while (!stack.isEmpty()) {  
  160.                     int j = stack.pop();  
  161.                     System.out.print(vertexesArray[j] + " ");  
  162.   
  163.                     for (int k = lastAdjVex(j); k >= 0; k = lastAdjVex(j, k)) {  
  164.                         if (!visited[k]) {  
  165.                             stack.add(k);  
  166.                             visited[k] = true;  
  167.                         }  
  168.                     }  
  169.                 }  
  170.             }  
  171.         }  
  172.     }  
  173.   
  174.     // 最后一个  
  175.     public int lastAdjVex(int i) {  
  176.         for (int j = vertexSize - 1; j >= 0; j--) {  
  177.             if (edgesMatrix[i][j] == 1)  
  178.                 return j;  
  179.         }  
  180.         return -1;  
  181.     }  
  182.   
  183.     // 上一个  
  184.     public int lastAdjVex(int i, int k) {  
  185.         for (int j = k - 1; j >= 0; j--) {  
  186.             if (edgesMatrix[i][j] == 1)  
  187.                 return j;  
  188.         }  
  189.         return -1;  
  190.     }  
  191.   
  192.     public boolean addVertex(Object val) {  
  193.         assert (val != null);  
  194.         vertexesArray[vertexSize] = val;  
  195.         vertexSize++;  
  196.         return true;  
  197.     }  
  198.   
  199.   
  200.     public boolean addEdge(int vnum1, int vnum2) {  
  201.         assert (vnum1 >= 0 && vnum2 >= 0 && vnum1 != vnum2);  
  202.   
  203.         //有向图  
  204.         if (graphType) {  
  205.             edgesMatrix[vnum1][vnum2] = 1;  
  206.   
  207.         } else {  
  208.             edgesMatrix[vnum1][vnum2] = 1;  
  209.             edgesMatrix[vnum2][vnum1] = 1;  
  210.         }  
  211.         return true;  
  212.     }  
  213.   
  214. }  
测试:

[java]  view plain  copy
  1. <pre name="code" class="java">    @Test  
  2.     public void test3() {  
  3.         GraphByMatrix g = new GraphByMatrix(Graph.DIRECTED_GRAPH, Graph.ADJACENCY_MATRIX, 6);  
  4.         g.addVertex("1");  
  5.         g.addVertex("2");  
  6.         g.addVertex("3");  
  7.         g.addVertex("4");  
  8.         g.addVertex("5");  
  9.         g.addVertex("6");  
  10.   
  11.         g.addEdge(01);  
  12.         g.addEdge(02);  
  13.         g.addEdge(13);  
  14.         g.addEdge(14);  
  15.         g.addEdge(21);  
  16.         g.addEdge(24);  
  17.         g.addEdge(35);  
  18.         g.addEdge(24);  
  19.         g.addEdge(45);  
  20.   
  21.         g.DFS();  
  22.         System.out.println();  
  23.         g.DFS2();  
  24.         System.out.println();  
  25.         g.DFS("2");  
  26.   
  27.         System.out.println();  
  28.         g.BFS();  
  29.     }  

 
1 2 4 6 5 3 

1 2 4 6 5 3 
2 4 6 5 1 3 
1 2 3 4 5 6 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值