数据结构--图论1--基础概述--遍历--可达--最短路径问题

文章目录

  • 介绍
    • 基础概念
    • 图论的分类
  • 图的表示
  • 图的遍历
  • 可达问题
  • 最短路问题
    • dijkstra算法

介绍

图论〔Graph Theory〕是数学的一个分支。它以图为研究对象。图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物间具有这种关系。
我的学习也是的专业课的离散数学才进行过系统的学习。
这里在进行一次总结与复习。

基础概念

  • n阶矩阵:有n个顶点的图
  • 零图:没有一条边的图
  • 平凡图:只有一个顶点没有边。也称一阶零图
  • 孤立点:没有关联的顶点
  • 关联与相邻:
    e = ( u , v ) e=(u,v) e=(u,v) u 和 v u和v uv是顶点e是连接他们的边
    那么:e和u/v是关联,u和v是相邻
  • 环:有向边起点和终点一样
  • v的入度:v作为终点的次数和
  • v的出度:v作为起点的次数和

图论的分类

图可以分为有向图和无向图

  • (v, w) 表示无向边,即 v 和 w 是互通的
  • 表示有向边,该边始于 v,终于 w

图可以分为有权图和无权图:

  • 有权图:每条边具有一定的权重(weight),通常是一个数字
  • 无权图:每条边均没有权重,也可以理解为权为 1

图又可以分为连通图和非连通图:

  • 连通图:所有的点都有路径相连
  • 非连通图:存在某两个点没有路径相连

图的表示

图在程序中的表示一般有两种方式:

  1. 邻接矩阵
  • 在 n 个顶点的图需要有一个 n × n 大小的矩阵
  • 在一个无权图中,矩阵坐标中每个位置值为 1 代表两个点是相连的,0 表示两点是不相连的
  • 在一个有权图中,矩阵坐标中每个位置值代表该两点之间的权重,0 表示该两点不相连
  • 在无向图中,邻接矩阵关于对角线相等
  1. 邻接链表:
  • 对于每个点,存储着一个链表,用来指向所有与该点直接相连的点
  • 对于有权图来说,链表中元素值对应着权重

图的遍历

图的遍历就是要找出图中所有的点,一般有以下两种方法:

  1. 深度优先算法(DFS)
// a 为图的邻接矩阵
public void DFS(int i){
	visted[i] = true;
	for(int j = 0;j < n;j++){
		if(!visted[j] && a[i][j] == true){
			sout(j);
			DFS(j);
		}
	}
}
  1. 广度优先算法(BFS)
public void BFS(int i){
	Quene<Integer> q = new ArrayDeque();
	q.offer(i);
	while(!q.isEmpty()){
		int j = q.poll();
		sout(j);
		for(int j = 0;j<n;j++){
			if(a[i][j] == true){
				q.offer(j);
				a[i][j] == false;
				a[j][i] == false;
			}
		}
	}
}

可达问题

查看2点之间是否可达。

// b为矩阵,u为起点,v为终点
// 查看u到v是否可达。
	public static boolean f(int u,int v){
		Queue<Integer> q = new ArrayBlockingQueue<>(n + 2);
        q.offer(u);
        while (!q.isEmpty()) {
            int x = q.poll();
            for (int i = 1; i <= n; i++) {
                if (b[x][i]) {
                    if (i == v)
                        return true;
                    q.offer(i);
                    b[x][i] = false;
                    b[i][x] = false;
                }
            }
        }
        return false;
   }

最短路问题

在图中找到某一个顶点到其它所有点的最短距离

dijkstra算法

迪杰斯特拉算法主要特点是以起始点为中心向外层扩展,直到扩展到终点为止。迪杰斯特拉算法采用的是贪心策略,将 G r a p h Graph Graph 中的节点集分为最短路径计算完成的节点集 S S S和未计算完成的节点集 T T T ,每次将从 T T T 中挑选 V 0 − > V t V_0->V_t V0>Vt 最小的节点 V t V_t Vt 加入 S S S,并更新 V 0 V_0 V0 经由 V t V_t Vt T T T 中剩余节点的更短距离,直到 T T T 中的节点全部加入 S S S 中,它贪心就贪心在每次都选择一个距离源点最近的节点加入最短路径节点集合。迪杰斯特拉算法只支持非负权图,它计算的是单源最短路径,即单个源点到剩余节点的最短路径,时间复杂度为 O ( n 2 ) O(n²) O(n2),如果求解整个图各个节点之间的最短路径,那么使用迪杰斯特拉算法的时间复杂度就是 O ( n 3 ) O(n³) O(n3)

public void 
package com.yu;

import java.io.*;
import java.util.Arrays;

public class Main {
    static final StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static final PrintWriter print = new PrintWriter(System.out);

    public static String next() throws IOException {
        st.nextToken();
        return st.sval;
    }

    public static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }
    public static void main(String[] args) throws IOException {
        int n = nextInt();//点数
        int m = nextInt();//边数
        int[][] weights = new int[n+1][n+1];
        for (int i = 0; i < m; i++) {
            int u = nextInt();
            int v = nextInt();
            int w = nextInt();
            weights[u][v] = w;
            weights[v][u] = w;
        }
        long[] dist = new long[n+1];
        Arrays.fill(dist, Long.MAX_VALUE);
        dist[1] = 0;
        boolean[] visited = new boolean[n+1];
        int[] pre = new int[n+1];
        Arrays.fill(pre, -1);
        for (int i = 1; i <= n; i++) {
            int u = -1;
            long min = Long.MAX_VALUE;
            for (int j = 1; j <= n; j++) {
                if (!visited[j] && dist[j] < min) {
                    u = j;
                    min = dist[j];
                }
            }
            if (u == -1) {
                break;
            }
            visited[u] = true;
            for (int v = 1; v <= n; v++) {
                if (!visited[v] && weights[u][v] != 0 && dist[u] + weights[u][v] < dist[v]) {
                    dist[v] = dist[u] + weights[u][v];
                    pre[v] = u;
                }
            }
        }
        if (dist[n] == Long.MAX_VALUE) {
            print.println(-1);
        }else {
            prints(n, pre);
        }
        print.flush();


    }

    private static void prints(int n, int[] pre) {
        if (n == -1) {
            return;
        }
        prints(pre[n], pre);
        print.print(n + " ");
    }


}

你可能感兴趣的:(数据结构,数据结构,图论)