《啊哈算法》——图

啊哈算法——图

深度和广度优先究竟是啥

DFS深度优先

首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的顶点,直到所有的顶点都被访问

package ch5;

import javax.swing.plaf.synth.SynthEditorPaneUI;
import java.util.Scanner;

public class TUDFS {
    static int[] book = new int[100];
    static int[][] e= new int[100][100];
    static int sum = 0;
    static int n;
    public static void dfs(int cur){//cur代表当前顶点的编号
        System.out.println(cur);
        sum++;//访问每一个顶点,就+1
        if(sum == n) return;//所有的顶点都遍历完,直接退出
        for (int i = 1; i<= n; i++){
            //判断当前顶点cur到顶点i是否有边,判断顶点i是否呗访问过
            if (e[cur][i] ==1 && book[i]==0){
                book[i] = 1;
                dfs(i);//从顶点i继续出发遍历
            }
        }
    }

    public static void main(String[] args) {
        int m,a,b;
        //初始化二维矩阵
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        //初始化矩阵
        for (int i = 1; i<=n;i++){
            for (int j=1;j<=m;j++){
                if(i == j) e[i][j] = 0;
                else e[i][j] = Integer.MIN_VALUE;
            }
        }
        //读入顶点之间的边
        for (int i =1; i<=m ;i++){
            a =scanner.nextInt();
            b =scanner.nextInt();
            e[a][b] = 1;
            e[b][a] = 1;
        }
        //从一号顶点开始出发
        book[1] = 1;
        dfs(1);
        scanner.close();
    }

}

BFS广度优先

首先以一个未被访问过的顶点作为起点,访问其所有相邻的顶点,然后对每个相邻的顶点,再访问他们相邻的未被访问过的顶点,直到所有顶点都被访问过,遍历结束。

package ch5;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class TUBFS {
    static int[] book = new int[100];
    static int[][] e = new int[100][100];
    static int[] queue = new int[100];
    static int n;
    //双指针
    static int head = 1,tail = 1;//定义首部和尾部

    public static void main(String[] args) {
        int m,a,b;
        //初始化二维矩阵
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        //初始化矩阵
        for (int i = 1; i<=n;i++){
            for (int j=1;j<=m;j++){
                if(i == j) e[i][j] = 0;
                else e[i][j] = Integer.MIN_VALUE;
            }
        }
        //读入顶点之间的边
        for (int i =1; i<=m ;i++){
            a =scanner.nextInt();
            b =scanner.nextInt();
            e[a][b] = 1;
            e[b][a] = 1;
        }
        //从一号队列出发
        queue[1] = 1;
        tail ++;
        book[1] = 1;

        while(head < tail&& tail <= n){
            int cur = queue[head];
            for (int i=1;i<=n;i++){
                if (e[cur][i] == 1 && book[i] == 0){
                    queue[tail] = i;
                    tail ++;
                    book[i] = 1;
                }
                if(tail >n) break;
            }
            head++;
        }
        for (int i=1;i<=n;i++){
            System.out.println(queue[i]);
        }
    }

}

城市地图—图的深度优先遍历

package ch5;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class TUBFS {
    static int[] book = new int[100];
    static int[][] e = new int[100][100];
    static int[] queue = new int[100];
    static int n;
    //双指针
    static int head = 1,tail = 1;//定义首部和尾部

    public static void main(String[] args) {
        int m,a,b;
        //初始化二维矩阵
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        m = scanner.nextInt();
        //初始化矩阵
        for (int i = 1; i<=n;i++){
            for (int j=1;j<=m;j++){
                if(i == j) e[i][j] = 0;
                else e[i][j] = Integer.MIN_VALUE;
            }
        }
        //读入顶点之间的边
        for (int i =1; i<=m ;i++){
            a =scanner.nextInt();
            b =scanner.nextInt();
            e[a][b] = 1;
            e[b][a] = 1;
        }
        //从一号队列出发
        queue[1] = 1;
        tail ++;
        book[1] = 1;

        while(head < tail&& tail <= n){
            int cur = queue[head];
            for (int i=1;i<=n;i++){
                if (e[cur][i] == 1 && book[i] == 0){
                    queue[tail] = i;
                    tail ++;
                    book[i] = 1;
                }
                if(tail >n) break;
            }
            head++;
        }
        for (int i=1;i<=n;i++){
            System.out.println(queue[i]);
        }
    }

}

小结

图的概念

图就是有N个顶点和M条边组成的集合

有向图和无向图

有向图:如果给图的每一条边规定一个方向,那么得到的图称为有向图,其边也称有向边。在有向图中,与一个点相关联的边有出边和入边支付,而与一个有向边关联的两个点也有始点和终点之分。

无向图:边没有方向的图称为无向图

无向图的代码

package ch5;

import java.util.Scanner;

public class CityMapDFS2 {
    static int min = Integer.MAX_VALUE;//设定一个最小值
    static int destination;
    static int[][] e = new int[100][100];
    static int[] book = new int[100];
    public static void DFS(int cur,int dis){
        if(dis > min)return;
        if (cur == destination) {
            if (dis < min) min = dis;
            return;
        }
        for (int j = 1; j<=destination;j++) {
            //判断当前城市cur到城市j是否有路,并判断当前城市是否已经在走过的路中
            if (e[cur][j] != Integer.MAX_VALUE && book[j] == 0){
                book[j] = 1;
                DFS(j,dis+e[cur][j]);//从j城市继续出发遍历
                book[j] = 0;//退回到前一步的探索,取消对j的标记
            }
        }
    }

    public static void main(String[] args) {
        int a,b,c;
        Scanner scanner = new Scanner(System.in);
        destination = scanner.nextInt();
        int m =scanner.nextInt();
        for (int i=1;i<=destination;i++){
            for (int j =1; j<=destination;j++){
                if (i==j) e[i][j] = 0;
                else e[i][j] = Integer.MAX_VALUE;
            }
        }
        for (int i=1; i<=m;i++){
            a = scanner.nextInt();
            b = scanner.nextInt();
            c = scanner.nextInt();
            e[a][b] = c;
            e[b][a] = c;//无向图
        }
        book[1]=1;
        DFS(1,0);
        System.out.println(min);
    }
}

最少转机—图的广度优先遍历

package ch5;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/*
5 7 1 5
1 2
1 3
2 3
2 4
3 4
3 5
4 5
2

Process finished with exit code 0

 */
public class ZSZJBFS {
    static Queue<Node> queue = new LinkedList<>();
    static int[][] e  = new int[100][100];
    static int[] book = new int[100];
    static int start,end,n,m,a,b,cur,falg;
    static {
        Scanner scanner = new Scanner(System.in);

        n = scanner.nextInt();
        m = scanner.nextInt();
        start = scanner.nextInt();
        end = scanner.nextInt();

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (i == j) e[i][j] = 0;
                else e[i][i] = Integer.MAX_VALUE;
            }
        }

        for (int i = 1; i <= m; i++) {
            a = scanner.nextInt();
            b = scanner.nextInt();
            e[a][b] = 1;
            e[b][a] = 1;
        }
    }

    public static void main(String[] args) {
        Node node = new Node(start,0);//初始化第一个城市
        queue.add(node);//把第一个城市加入队列
        book[start] = 1;//把第一个城市做标记

        //当队列不为空的时候循环
        while (!queue.isEmpty()){
            cur = queue.peek().x;
            for (int j =1;j<=n;j++){//一次每个城市循环遍历
                if (e[cur][j] == 1 && book[j] ==0){
                    //如果这个城市可以和cur当前城市连接并且没有在队列当中,那么把这个j加入到队列中
                    Node node1 = new Node(j,queue.peek().s+1);
                    queue.add(node1);
                    book[j] = 1;//标记这个队列
                }
                if (queue.peek().x == end){
                    falg = 1;
                    break;
                }
            }
            if (falg == 1)
                break;
            queue.remove();
        }
        System.out.println(queue.peek().s);
    }






}
class Node{
    int x;//城市编号
    int s;//转机次数
    public Node(){}
    public Node(int x, int s){
        this.x =x;
        this.s =s;
    }
}
上一篇:Java中的关键字static和this


下一篇:09-XPath 语言-python爬虫