一、题目
给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入格式:
输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。
输出格式:
按照"{ v1 v2 ... vk }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。
输入样例:
8 6
0 7
0 1
2 0
4 1
2 4
3 5
输出样例:
{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }
二、解答
import java.util.*;
public class Main{
static ArrayList<Integer> stack = new ArrayList<>();
static int index = -1;
static ArrayList<Integer> queue = new ArrayList<>();
static int front = -1, rear = -1;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[][] map = creatMap(sc);
printAllRes(map);
}
public static void printAllRes(int[][] map){
int nodeNum = map.length;
int[] visited = new int[nodeNum];
for (int i = 0; i < nodeNum; i++) {
if (visited[i] == 0) System.out.println(DFS(i, visited, map));
}
visited = new int[nodeNum];
for (int i = 0; i < nodeNum; i++) {
if (visited[i] == 0) System.out.println(BFS(i, visited, map));
}
}
public static String DFS(int node, int[] visited, int[][] map){
String res = "";
int nodeNum = map.length;
while(node != -1) {
//某个点可能与多个点相邻,被多次压入堆栈
if(visited[node] == 1) { node = pop(); continue;}
//从小到大输出,因此避免倒序
for (int i = nodeNum - 1; i >= 0; i--) {
if (map[node][i] != 0 && visited[i] == 0) push(i);
}
visited[node] = 1;
res += node + " ";
node = pop();
}
return "{ " + res.trim() + " }";
}
public static String BFS(int node, int[] visited, int[][] map){
String res = "";
int nodeNum = map.length;
while(node != -1) {
//某个点可能与多个点相邻,被多次压入堆栈
if(visited[node] == 1) { node = outQue(); continue;}
for (int i = 0; i < nodeNum; i++) {
if (map[node][i] != 0 && visited[i] == 0) inQue(i);
}
visited[node] = 1;
res += node + " ";
node = outQue();
}
return "{ " + res.trim() + " }";
}
public static int[][] creatMap(Scanner sc){
int nodeNum = sc.nextInt();
int lineNum = sc.nextInt();
int [][] map = new int[nodeNum][nodeNum];
for (int i = 0; i < lineNum; i++) {
int node1 = sc.nextInt();
int node2 = sc.nextInt();
map[node1][node2] = 1;
map[node2][node1] = 1;
}
return map;
}
public static void push(int num){
stack.add(num);
index++;
}
public static int pop(){
if (index < 0) return -1;
return stack.remove(index--);
}
public static void inQue(int num){
queue.add(num);
front++;
}
public static int outQue(){
if (rear >= front) return -1;
return queue.get(++rear);
}
}
思路:
考虑图的保存和遍历:二维数组DFS:深度遍历过程,将邻近点压入堆栈BFS:宽度遍历过程,将邻近点压入队列某个点可能与多个点相邻,被多次压入堆栈,只处理一次
思考:
很多时候递归可以用堆栈来解决,比如DFS尾递归可以用while循环来解决