图BFS,DFS
1.采用邻接表的数据结构:
public class Graph { static ArrayList<Vertex> vertexList=new ArrayList<Vertex>(); static int vertexNum=0; static int edgeNum=0; public Graph(){} //边 public static class Edge { int edgeName;//边的后面的节点 Edge next; public Edge(){} } //点 public static class Vertex { String vertexName; Edge firstEdge=new Edge(); public Vertex(){} } public static void main(String[] args) { Graph g=new Graph(); Graph.initialGraph(g); Graph.outputGraph(g); Graph.DFS(g, 0); System.out.println(); Graph.BFS(g, 0); } //根据节点名称生成节点下标,我们后续是需要用这个下标来进行遍历的 public static int vtoe(Graph graph,String str){ for(int i=0;i<graph.vertexNum;i++){ if(graph.vertexList.get(i).vertexName.equals(str)){ return i; } } return -1; } public static void initialGraph(Graph graph){ Scanner scan=new Scanner(System.in); System.out.println("请输入顶点数和边数:"); graph.vertexNum=scan.nextInt(); graph.edgeNum=scan.nextInt(); System.out.println("请依次输入定点名称:"); for(int i=0;i<graph.vertexNum;i++){ Vertex vertex=new Vertex();//构建一个个点 String name=scan.next(); vertex.vertexName=name;//顶点的名字 vertex.firstEdge=null;//顶点后面的第一条边 graph.vertexList.add(vertex);//然后把它加到点的list里面 } System.out.println("请依次输入每个边:"); for(int i=0;i<graph.edgeNum;i++){ String preV=scan.next();//边的前一个节点 String folV=scan.next();//边的后一个节点 int v1=vtoe(graph,preV);//第v1个点 int v2=vtoe(graph,folV);//第v2个点 if(v1==-1 || v2==-1) System.out.println("输入顶点数据错误!"); //下面代码是图构建的核心:链表操作 Edge edge1=new Edge(); edge1.edgeName=v2; //下面相当于链表的头插法,总是插到头结点的后面 edge1.next=graph.vertexList.get(v1).firstEdge; graph.vertexList.get(v1).firstEdge=edge1; // 下面代码加上便是构建无向图,不加便是构建有向图 // Edge edge2=new Edge(); // edge2.edgeName=v1; // edge2.next=graph.vertexList.get(v2).firstEdge; // graph.vertexList.get(v2).firstEdge=edge2; } } public static void outputGraph(Graph graph){ Edge edge=new Edge(); for(int i=0;i<graph.vertexNum;i++){ System.out.print(graph.vertexList.get(i).vertexName); edge=graph.vertexList.get(i).firstEdge; while(edge!=null){ System.out.print("-->"+graph.vertexList.get(edge.edgeName).vertexName); edge=edge.next; } System.out.println(); } } //以邻接表为数据结构的DFS static int[] visited=new int[5]; static void DFS(Graph graph,int v) { Edge p; visited[v]=1; System.out.print(graph.vertexList.get(v).vertexName+"-->"); p = vertexList.get(v).firstEdge; while(p!=null) { if(visited[p.edgeName]==0) DFS(graph,p.edgeName);//每次要先查到最深处 p=p.next; } } static void BFS(Graph graph,int v) { Edge p; Queue<Integer> queue=new LinkedList<>(); int[] visited=new int[vertexNum]; System.out.print(graph.vertexList.get(v).vertexName+"-->"); visited[v]=1; queue.add(v); while(!queue.isEmpty()) { int temp=queue.poll(); p = vertexList.get(temp).firstEdge; while(p!=null) { if(visited[p.edgeName]==0) { System.out.print(graph.vertexList.get(p.edgeName).vertexName+"-->"); visited[p.edgeName]=1; queue.add(p.edgeName); } p=p.next;//首先把每个链表里面走完。(这里的链表的值是和这个节点连接的所有节点) } } } int vn,en; void DfsForTree(Graph graph,int v) { Edge p; visited[v]=1; vn++; p=graph.vertexList.get(v).firstEdge; while(p!=null) { en++; if(visited[p.edgeName]==0) { DfsForTree(graph, p.edgeName); } p=p.next; } } int GisTree(Graph g) { DfsForTree(g, 0); if(vn==g.vertexNum&&en==2*(g.edgeNum-1)) return 1; else return 0; } }
2. 对一个01矩阵用BFS求最短路径
static class point{ int x; int y; int len; public point(int x, int y,int len) { this.x = x; this.y = y; this.len = len; } } //01矩阵广度优先搜索 从(0,0)到(x,y) public static int minPathLength(int[][] grids, int x, int y) { int[][] dir = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};//方向 int m = grids.length, n = grids[0].length; Queue<point> queue = new LinkedList<>(); queue.add(new point(0, 0, 1)); while (!queue.isEmpty()) { point cur = queue.poll(); for (int i = 0; i < 4; i++) { point next = new point(cur.x + dir[i][0], cur.y + dir[i][1], cur.len+1); if (next.x < 0 || next.x >= m || next.y < 0 || next.y >= n) continue; if (grids[next.x][next.y] != 1) continue;//不能走 grids[next.x][next.y] = 0; if (next.x == x && next.y == y) return next.len; queue.add(next); } } return -1; }
3.一个整数可以由多少个平方数组成(求最小的个数)BFS
两个数之间的差是一个平方数的话,代表两个数之间是连通的。
//求平方数集合 private List<Integer> generateSquares(int n) { List<Integer> squares = new ArrayList<>(); int square = 1; while (square*square <= n) { squares.add(square*square); square++; } return squares; } public int numSquares(int n) { List<Integer> squares = generateSquares(n); Queue<Integer> queue = new LinkedList<>(); boolean[] visit = new boolean[n + 1]; queue.add(n); visit[n] = true; int level = 0; while (!queue.isEmpty()) { int size = queue.size(); level++; while (size-- > 0) { int cur = queue.poll(); for (int s : squares) { int next = cur - s; if (next < 0) { break;//走不通 } if (next == 0) { return level; } if (visit[next]) { continue; } visit[next] = true; queue.add(cur - s); } } } return n; }
4.求最大的岛屿
//01矩阵中连续1的个数(求这样的最大值)DFS深度优先搜索 public int dfs(int [][]grid, int x, int y, int [][]visit, int count) { if (x < 0 || x > grid.length - 1 || y < 0 || y > grid[0].length - 1) { return count; } if (visit[x][y] == 1 || grid[x][y] == 0) { return count; } visit[x][y] = 1; count ++; count += dfs(grid, x + 1, y, visit, 0);//向右走 count += dfs(grid, x - 1, y, visit, 0);//向左 count += dfs(grid, x, y + 1, visit, 0); count += dfs(grid, x, y - 1, visit, 0); return count; } public int maxAreaOfIsland(int[][] grid) { int [][]visit = new int[grid.length][grid[0].length]; int max = 0; for (int i = 0;i < grid.length;i ++) { for (int j = 0;j < grid[0].length;j ++) { if (grid[i][j] == 1) { max = Math.max(max, dfs(grid, i, j, visit, 0)); } } } return max; }
5.和上面类似,也是在01矩阵中,上面是求岛屿的最大值,这里是求一共有多少个岛屿,每个岛屿是被0包围着的
//仅仅是去遍历然后修改visit不用返回 public void dfs(int [][]grid, int x, int y, int [][]visit) { if (x < 0 || x > grid.length - 1 || y < 0 || y > grid[0].length - 1) { return ; } if (visit[x][y] == 1 || grid[x][y] == 0) { return ; } visit[x][y] = 1; dfs(grid, x + 1, y, visit);//向右走 dfs(grid, x - 1, y, visit);//向左 dfs(grid, x, y + 1, visit); dfs(grid, x, y - 1, visit); return; } public int numOfIsland(int[][] grid) { int [][]visit = new int[grid.length][grid[0].length]; int res = 0; for (int i = 0;i < grid.length;i ++) { for (int j = 0;j < grid[0].length;j ++) { if (grid[i][j] == 1&&visit[i][j]==0) { //是岛屿且没有被遍历才去搜索 dfs(grid, i, j, visit); res++; } } } return res; }
6.有点像组合,但是没有解决重复的问题,从数组中取出k个数
public void dfs(List<Integer> list, int[] a, int k, int cur) {//k代表从中取的个数 if (list.size() == k) { Alllist.add(new ArrayList<Integer>(list)); return; } int n=a.length; for (int i = cur;i < n; i ++) { list.add(a[i]); dfs(list, a, k, i + 1); list.remove(list.size() - 1); } }
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/11101532.html
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号