图论相关知识

本文介绍了图论的基本概念,包括无向图、有向图及其存储结构如邻接矩阵和邻接表。接着重点讲解了如何利用图论解决最短路径问题,以高德地图为例,阐述了有权图的表示方法,并提到了弗洛伊德算法和迪克斯特拉算法,这两种算法分别用于计算所有点对和单源最短路径。文章还分析了弗洛伊德算法的时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成

一、基本概念:

1.图是由顶点(或结点)及顶点之间的关系组成的集合。通常,图中的顶点数量或者一个顶点与其他顶点之间的连线的个数不受限制。

2.图由顶点集和边集组成。主要有4种类型:无向图、有向图(有方向)、无向网(当图的边有了权值)和有向网等。

3.常见的存储结构有邻接矩阵、邻接表、邻接多重表、十字链表等。

二、数据结构

1:邻接矩阵

 

 2、邻接表

 

三、最短优先路径

 高德地图相信大家一定都用过,每当我们输入一个目的地时,系统总是会帮助我们寻找一条最近的路。我们知道出发地到目的地可能有很多条路可以选择,而高德地图是怎样做到为我们选择更近的路呢?这一节的内容,我们就会来讨论关于图的最短路径的问题。

在计算机里,我们用有权图来表示城市的路网,其中每个节点代表一个地点每条边代表从一个地方到另一个地方的距离,数据结构我们使用邻接矩阵的形式。

计算最短路径分成两种情况,一种是一次计算所有点对的最短路径,就是下面我们要讲到的弗洛伊德算法;另一种是单源最短路径,也就是计算某一个节点到其他所有节点的最短距离,后面的迪克斯特拉算法采用的就是这种方式。

 

 

 

 上面的矩阵也可以代表在不借助中转站的情况下各节点之间的最短路径。接下来,我们只让节点 A 作为中转站,然后计算各节点的最短路径,然后对于矩阵的每一项,我们比较d[i][j]d[i][0]+d[0][j]的大小,然后取最小者作为d[i][j]的值。其中ij分别代表矩阵的行和列。

 

 

例如,第 1 行第 4 列代表从 A 到 D 的最短路径为 10。

由于程序中存在三重循环,所以弗洛伊德算法的时间复杂度为 O(n^3) ,而邻接矩阵有 [公式] 项,因此空间复杂度自然就为 [公式] 

public class Graph {
    private int vertexSize;
    private int edgeSize;
    private int arr[][];

    public Graph(int vertexSize){
        this.vertexSize = vertexSize;
        arr = new int[vertexSize][];
    }

    public int getVertexSize(){
        return this.vertexSize;
    }
    public int getEdgeSize(){
        return this.edgeSize;
    }
    /**
     * 判断传入节点之间是否有边
     * @param v
     * @param w
     * @return
     * */
    public boolean hasEdge(int v,int w){
        if(v>=0 && v<this.edgeSize && w>=0 && w<this.edgeSize ){
            if(arr[v][w] == 1){
                return true;
            } else {
                return false;
            }
        } else{
            return false;
        }
    }

    public int addEdge(int v, int w){
        if(!hasEdge(v,w)){
            arr[v][w] = 1;
            arr[w][v] = 1;
            this.edgeSize++;
            return 1;
        } else{
            return 0;
        }
    }
}
    public void testaaa(){
        int arr[][] ={{0,7,10000,10000,1,6},{7,0,2,4,10000,10000},{10000,2,0,9,3,10000}
        ,{10000,4,9,0,10000,10000},{1,10000,3,10000,0,3},{6,10000,10000,10000,3,0}};

        int path[][] = new int[6][6];
        for(int i=0;i<6;i++){
            for(int j=0;j<6;j++){
                if(arr[i][j] == 10000){
                    path[i][j] = -1;
                } else{
                    path[i][j] = j;
                }

            }
        }

        for(int k=0;k<arr.length;k++){
            for(int i = 0;i<arr.length;i++){
                for(int j= 0;j<arr.length;j++){
                    int temp = arr[i][k] + arr[k][j];
                    if(temp < arr[i][j]){
                        arr[i][j] = temp;
                        path[i][j] = k;
                    }
                }
            }
        }



        for(int i =0;i<arr.length;i++){
            for(int j = 0;j<arr[i].length;j++){
                System.out.print(arr[i][j]+"  ");
            }
            System.out.println("");
        }

        System.out.print(findRoute(path,0,3));
    }

    private List<Integer> findRoute(int[][] path,int start, int end){
        List<Integer> routeList = new ArrayList<Integer>();
        routeList.add(start);
        for(int tmp = path[start][end];tmp != end;tmp = path[tmp][end]){
            if(tmp == -1){
                throw new BusinessException("不可达");
            }
            routeList.add(tmp);
        }
        routeList.add(end);
        return routeList;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值