Data structure and algorithm (4): Graph theory (graph theory concept, depth-first traversal DFS, breadth-first traversal BFS, shortest path, Dijkstra algorithm)

think

  1. WeChat friendship
  2. QQ recommends people you may know
  3. Graph database Neo4j
  4. Knowledge map recommendation algorithm, data mining
  5. Navigation software route recommendation, Dijkstra algorithm

Graph – Solving Relational Network Systems

Basic knowledge of graphs:

  1. vertex:
  2. side:
  3. Vertex degree:
  4. exit, entrance
  5. directed graph
  6. Undirected graph

Storage: array + linked list

Solving relational network systems

adjacency matrix

There are x points in the graph, which is the matrix of x*x

7*7matrix with 0 and 1

  • A[7][7]: Cleverly apply the subscript of the array
  • A[1][1]Indicates the situation from 1 to 1
  • A[1][2]It means the situation of 1 to 2, there is a side mark A[1][2]=1, and there is no side markA[1][3]=0

Sparse matrix: 3*3 matrix

0 0 0
1 1 1
0 1 0

Adjacency List: Linked List

  • Arrays: waste of space, but block of speed. Arrays are preferred for small data

  • Linked list: Save space, but slow

Graph traversal search algorithm

case:

Rescue the beauty: One day, Xiaomei went to play the maze with you. But Xiaomei, who has a bad sense of direction, will soon get lost. After you find out, go to
rescue the helpless Xiaomei. You have figured out the map of the maze. Now you need to know whether you can reach
Xiaomei from your current location. Beautiful location?

1: means obstacles on the map, 0 means there is a way to go

insert image description here

Adjacency matrix:

0 (you) 0 1 0
0 0 0 0
0 0 1 0
0 1 0 (Xiaomei) 0
0 0 0 1

Depth-first traversal (DFS)

You can imagine playing a maze, do you choose a direction to go to the end, until you can't go, you go back one step and continue to try other directions, yes, this is actually depth-first traversal. One way goes to the end, recursion, and backtracking. Also mark the points traveled

The key optimization: pruning
It is easy to face the search algorithm in the interview. Computer test
Direct interview questions are the easiest to ask the tree

class Point {
    
    
    int x;
    int y;

    public Point(int x, int y) {
    
    
        this.x = x;
        this.y = y;
    }
}

//深度遍历 最短路线
class DFS {
    
    

    int line; //地图行
    int column; //地图列
    int dx; //目标x
    int dy; //目标y
    int data[][]; //邻街矩阵
    boolean mark[][]; //标记数据

    int minStep = Integer.MAX_VALUE;

    int next[][] = {
    
    {
    
    0,1}, {
    
    1,0}, {
    
    0,-1}, {
    
    -1,0}}; // ACM 想到的

    Stack<Point> stack = new Stack<>(); //保存当前路径

    //保存所有的路径,key是步数
    Map<Integer, List<Stack<Point>>> result = new HashMap<>();

    public DFS(int line, int column, int dx, int dy, int[][] data, boolean[][] mark) {
    
    
        this.line = line;
        this.column = column;
        this.dx = dx;
        this.dy = dy;
        this.data = data;
        this.mark = mark;
    }

    public void dfs(int sx, int sy, int step) {
    
    
        if (sx == dx && sy == dy) {
    
    
            if (!result.containsKey(step)) {
    
    
                result.put(step, new ArrayList<>());
            }
            result.get(step).add((Stack<Point>) stack.clone());
            if (step < minStep ) minStep = step;
            return;
        }

        for (int i = 0; i < 4; i++) {
    
    
            int nextX = sx + next[i][0];
            int nextY = sy + next[i][1];
            if (nextX  < 0 || nextX > line || nextY < 0 || nextY > column) continue;

            if (data[nextX][nextY] == 0 && !mark[nextX][nextY]) {
    
    
                mark[nextX][nextY] = true;
                stack.add(new Point(nextX, nextY));
                dfs(nextX, nextY, step+1);
                mark[nextX][nextY] = false; //回溯
                stack.pop();
            }
        }
    }

    public static void main(String[] args) {
    
    
        int data[][] = {
    
    
                {
    
    0,0,1,0},
                {
    
    0,0,0,0},
                {
    
    0,0,1,0},
                {
    
    0,1,0,0},
                {
    
    0,0,0,1}
        };

        int dx = 3;
        int dy = 2;

        int sx = 0;
        int sy = 0;

        int line = 4;
        int column = 3;

        boolean mark[][] = new boolean[line+1][column+1];

        DFS dfs = new DFS(line, column, dx, dy, data, mark);
        dfs.dfs(sx, sy, 0);

        System.out.println(dfs.minStep);

        List<Stack<Point>> stacks = dfs.result.get(dfs.minStep);
        for (Stack<Point> stack : stacks) {
    
    
            for (Point point : stack) {
    
    
                System.out.printf("(" + point.x + ", " + point.y + ")");;
            }
            System.out.println();
        }
    }

}

Breadth-first traversal (BFS) ---- ArrayBlockingQueue

Similar to the hierarchical traversal of the tree structure, first find a point, then add the point to the queue, find out the associated edge of the point and add it to the queue, and loop until the queue is empty, and all the roads are gone at the beginning

Two key points: queue, mark array, added points cannot be added

Heuristic search, A*

class Point {
    
    
    int x;
    int y;

    public Point(int x, int y) {
    
    
        this.x = x;
        this.y = y;
    }
}

//广度遍历 能不能到达
class BFS {
    
    
    int line; //地图行
    int column; //地图列
    int dx; //目标x
    int dy; //目标y
    int data[][]; //邻街矩阵
    boolean mark[][]; //标记数据

    int next[][] = {
    
    {
    
    0,1}, {
    
    1,0}, {
    
    0,-1}, {
    
    -1,0}}; // ACM 想到的

    public BFS(int line, int column, int dx, int dy, int[][] data, boolean[][] mark) {
    
    
        this.line = line;
        this.column = column;
        this.dx = dx;
        this.dy = dy;
        this.data = data;
        this.mark = mark;
    }

    public boolean bfs(int sx, int sy) {
    
     //当前位置 x,y当前位置 求(x,y)->(dx,dy)
        if (sx < 0 || sx > line || sy < 0 || sy > column) return false;

        if (sx == dx && sy == dy) {
    
    
            System.out.println("当前位置就是目标位置: sx = " + sx + ", sy = " + sy);
            return true;
        }

        mark[sx][sy] = true;

        Queue<Point> queue = new ArrayBlockingQueue<>(line * column);

        queue.add(new Point(sx,sy));

        while (!queue.isEmpty()) {
    
    
            Point point = queue.poll(); //队列第一个点
            for (int i = 0; i < 4; i++) {
    
    
                int nextX = point.x + next[i][0];
                int nextY = point.y + next[i][1];

                if (nextX  < 0 || nextX > line || nextY < 0 || nextY > column) continue;

                if (data[nextX][nextY] == 0 && !mark[nextX][nextY]) {
    
    
                    if (nextX == dx && nextY == dy) {
    
    
                        System.out.println("找到了: dx = " + dx + ", dy = " + dy);
                        return true;
                    }
                    mark[nextX][nextY] = true;
                    queue.add(new Point(nextX, nextY));
                }
            }
        }
        return false;
    }


    public static void main(String[] args) {
    
    
        int data[][] = {
    
    
                {
    
    0,0,1,0},
                {
    
    0,0,0,0},
                {
    
    0,0,1,0},
                {
    
    0,1,0,0},
                {
    
    0,0,0,1}
        };

        int dx = 3;
        int dy = 2;

        int sx = 0;
        int sy = 0;

        int line = 4;
        int column = 3;

        boolean mark[][] = new boolean[line+1][column+1];

        BFS bfs = new BFS(line, column, dx, dy, data, mark);
        bfs.bfs(sx,sy);
    }
}

Shortest Path – Dijkstra’s Algorithm

Analysis of the core idea of ​​the shortest path: greedy: sorting, greedy strategy. 1-3 We consider 10, local

  1. We open a dis array to represent the distance from the starting point to each vertex. At the beginning, we assign a value of infinity
  2. Add the variable loc, the initial assignment is the starting point
  3. Update the dis array through loc, because we can update the path after adding a point贪心策略:在dis数组里面找离初始点最近的那个点
  4. Find the point closest to the initial point in the dis array, exclude the selected point, and assign it to loc
  5. Repeat 3 4 operations until all points are added

insert image description here

//地图--最短路径 迪杰斯特拉算法(Dijkstra)
/**
 6 个点
 8 个变
 1 是起点
 1 3 10
 1 5 30
 1 6 100
 2 3 5
 3 4 50
 4 6 10
 5 4 20
 5 6 60
 1 到 1 的最短距离是 0 === 最短路径是 1
 1 到 2 的最短距离是 2147483647 === 无法到达
 1 到 3 的最短距离是 10 === 最短路径是 1 -> 3
 1 到 4 的最短距离是 50 === 最短路径是 1 -> 5 -> 4
 1 到 5 的最短距离是 30 === 最短路径是 1 -> 5
 1 到 6 的最短距离是 60 === 最短路径是 1 -> 5 -> 4 -> 6
 */
class DJSTL {
    
    
    static Map<Integer, String> routes = new HashMap<>();

    public static void search(int start, int dis[], int value[][], int point) {
    
    
        boolean mark[] = new boolean[point+1];
        mark[start] = true;
        dis[start] = 0;
        int count = 1;
        while (count <= point) {
    
     //O(n^2)
            //求最小值点开始
            int loc = 0; //新加的点
            int min = Integer.MAX_VALUE;
            for (int i = 1; i <= point; i++) {
    
     //求dis里面最小的值 可以优化成 堆 logn
                if (!mark[i] && dis[i] < min) {
    
    
                    min = dis[i];
                    loc = i;
                }
            }

            if (loc == 0) break; //表示没有可以加入的点

            mark[loc] = true;

            if (routes.get(loc) == null) {
    
    
                routes.put(loc, start + " -> " + loc);
            }

            //加入的点到各点距离计算
            //优化只需要关注加入的点
            for (int i = 1; i <= point; i++) {
    
    
                //min(dis[3] + data[3][4], dis[4])
                if ( value[loc][i] != -1 && (dis[loc] + value[loc][i] < dis[i]) ) {
    
    
                    dis[i] = dis[loc] + value[loc][i];
                    routes.put(i, routes.get(loc) + " -> " + i);
                }
            }
            count++;
        }

        for (int i = 1; i <= point; i++) {
    
    
            System.out.print(start + " 到 " + i + " 的最短距离是 " + dis[i] + " === ");
            if (dis[i] == 0 && routes.get(i) == null) {
    
    
                System.out.println("最短路径是 " + i);
            } else if (dis[i] == Integer.MAX_VALUE) {
    
    
                System.out.println("无法到达");
            } else {
    
    
                System.out.println( "最短路径是 " + routes.get(i));
            }
        }
    }


    public static void main(String[] args) {
    
    
        int point, line, start; //n 点数, m 边数, x 起点
        Scanner scanner = new Scanner(System.in);

        point = scanner.nextInt();
        line = scanner.nextInt();
        start = scanner.nextInt();

        int value[][] = new int[point+1][line+1]; //点到点矩阵
        int dis[] = new int[point+1]; //存储最短路径

        for (int i = 1; i <= point; i++) {
    
    
            dis[i] = Integer.MAX_VALUE;
            for (int j = 1; j <= point; j++) {
    
    
                //初始化地图
                if (i == j) {
    
    
                    value[i][j] = 0;
                } else {
    
    
                    value[i][j] = -1;
                }
            }
        }

        for (int i = 0; i < line; i++) {
    
    
            int xx = scanner.nextInt();
            int yy = scanner.nextInt();
            int v = scanner.nextInt(); //xx 到 yy 的距离
            value[xx][yy] = v;
            if (xx == start) {
    
    
                dis[yy] = v;
            }
        }

        search(start, dis, value, point);
    }
}

Guess you like

Origin blog.csdn.net/menxu_work/article/details/130361924