• 【428】Dijkstra 算法


    算法思想:(单源最短路径)

    • 1个点到所有其他点的最短路径
    • 查找顶点到其他顶点的最短路径,无法到达的记为+∞,找到最小的,就找到了最短路径的顶点
    • 查看上一轮找到的最小点到达其他点的最小值,找到最短路径的顶点。
    • 以此类推
    • trivial relax:无穷大 ==> 具体数字
    • non-trival relax:具体数字 ==> 具体数

    参考:https://www.bilibili.com/video/av36886088


     

    运行效果:

    step = 1, minw = 0, pacost[0] = 0.00
        trival relax: pacost[1] = inf ==> 1.00
        trival relax: pacost[3] = inf ==> 2.00
    
    step = 2, minw = 1, pacost[1] = 1.00
        trival relax: pacost[2] = inf ==> 4.00
    
    step = 3, minw = 3, pacost[3] = 2.00
        trival relax: pacost[2] = 4.00 ==> 3.00
    
    step = 4, minw = 2, pacost[2] = 3.00
    
    visited: {1, 1, 1, 1}
    parent: {-1, 0, 3, 0}
    pacost: {0.00, 1.00, 3.00, 2.00}
    

    代码:

     Dijkstra.c 

    #include <stdio.h>
    #include <stdlib.h>
    
    #include "WeGraph.h"
    
    void DijkstraPrim(Graph g, int nV, int nE, Vertex src, char alg);
    
    int main(){
    	Graph g = newGraph(4);
    	Edge e = newEdge(0, 1, 1);
    	insertEdge(e, g);
    	
    	e = newEdge(1, 2, 3);
    	insertEdge(e, g);
    	
    	e = newEdge(2, 3, 1);
    	insertEdge(e, g);
    	
    	e = newEdge(3, 0, 2);
    	insertEdge(e, g);
    	
    	DijkstraPrim(g, 4, 4, 0, 'd');
    	
    	return 0;
    }
    
    int *mallocArray(int numV) {               
    	int *array = malloc(numV * sizeof(int));// l
    	if (array == NULL) {                    // o
    		fprintf(stderr, "Out of memory
    ");  // c
    		exit(1);                             // a
    	}                                       // l
    	int i;                                  // f
    	for (i=0; i<numV; i++) {                // u
    		array[i] = UNVISITED;                // n
    	}                                       // c
    	return array;                           // t
    } 
    
    float *mallocFArray(int numV) {               
    	float *array = malloc(numV * sizeof(float));// l
    	if (array == NULL) {                    // o
    		fprintf(stderr, "Out of memory
    ");  // c
    		exit(1);                             // a
    	}                                       // l
    	int i;                                  // f
    	for (i=0; i<numV; i++) {                // u
    		array[i] = MAXWEIGHT;                // n
    	}                                       // c
    	return array;                           // t
    } 
    
    void showArray(char *desc, int *array, int numV) {
    	int i;                                  // l
    	printf("%s: {", desc);                   // o
    	for (i=0; i<numV; i++) {                // c
    		printf("%d", array[i]);              // a
    		if (i <= numV-2) {                   // l
    			printf(", ");                     // f
    		}                                    // u
    	}                                       // n
    	printf("}
    ");                          // c
    	return;                                 // t
    }
    
    void showFArray(char *desc, float *array, int numV) {
    	int i;                                  // l
    	printf("%s: {", desc);                   // o
    	for (i=0; i<numV; i++) {                // c
    		printf("%0.2f", array[i]);              // a
    		if (i <= numV-2) {                   // l
    			printf(", ");                     // f
    		}                                    // u
    	}                                       // n
    	printf("}
    ");                          // c
    	return;                                 // t
    }
    
    void DijkstraPrim(Graph g, int nV, int nE, Vertex src, char alg) {
    // the last parameter arg is set by main, and is:
    // 'd' for Dijkstra or
    // 'p' for Prim
    
       int *visited = mallocArray(nV);   // initialised to UNVISITED
       int *parent = mallocArray(nV);    // initialised to UNVISITED
       float *pacost = mallocFArray(nV); // floats: initialised to INFINITY
    
       pacost[src] = 0.0;
       for (int step = 1; step <= nV; step++) {
       
       	  printf ("
    step = %d, ", step);
       	  
          Vertex minw = -1;
          for (Vertex w = 0; w < nV; w++) {        // find minimum cost vertex
             if ((visited[w] == UNVISITED) &&
                 (minw == -1 || pacost[w] < pacost[minw])) {
                minw = w;
             }
          }
          
          printf ("minw = %d, ", minw);
    	  printf ("pacost[%d] = %0.2f
    ", minw, pacost[minw]);
    	  
          visited[minw] = VISITED;
    
          for (Vertex w = 0; w < nV; w++) {         // 
             Weight minCost = getWeight(g, minw, w);// if minw == w, minCost = NOWEIGHT 
             // minCost is cost of the minimum crossing edge
             if (minCost != NOWEIGHT) {
                if (alg == 'd') {                   // if DIJKSTRA ...
                   minCost = minCost + pacost[minw];// add in the path cost 
                }
                if ((visited[w] != VISITED) &&
                    (minCost < pacost[w])) {
                       printf ("    trival relax: pacost[%d] = %0.2f ", w, pacost[w]);
                    
                       pacost[w] = minCost;
                       parent[w] = minw;
                       
                       printf ("==> %0.2f
    ", pacost[w]);
                }
             }
          }
          
          
          
       }
       
       printf("
    ");
       
       showArray("visited", visited, nV);
       showArray("parent", parent, nV);
       showFArray("pacost", pacost, nV);
       free(visited);
       free(parent);
       free(pacost);
       return;
    }
    

     WeGraph.c  

    // WeGraph.c: an adjacency matrix implementation of a weighted graph
    #include <stdio.h>
    #include <stdlib.h>
    #include "WeGraph.h"
    
    struct graphRep { 
        int nV;       // #vertices 
        int nE;       // #edges 
        Weight **edges;  // matrix of weights
    };
    
    Graph newGraph(int numVertices) { 
        Graph g = NULL;
        if (numVertices < 0) {
           fprintf(stderr, "newgraph: invalid number of vertices
    ");
        }
        else {
            g = malloc(sizeof(struct graphRep)); 
            if (g == NULL) {
                fprintf(stderr, "newGraph: out of memory
    ");
                exit(1);
            }
            g->edges = malloc(numVertices * sizeof(int *)); 
            if (g->edges == NULL) {
                fprintf(stderr, "newGraph: out of memory
    ");
                exit(1);
            }
            int v; 
            for (v = 0; v < numVertices; v++) { 
                g->edges[v] = malloc(numVertices * sizeof(int)); 
                if (g->edges[v] == NULL) {
                    fprintf(stderr, "newGraph: out of memory
    ");
                    exit(1);
                }
                int j;
                for (j = 0; j < numVertices; j++) {
                    g->edges[v][j] = NOWEIGHT;
                }
            } 
            g->nV = numVertices; 
            g->nE = 0; 
        }
        return g;
    }
    
    void freeGraph(Graph g) { 
        if (g != NULL) {
            int i; 
            for (i = 0; i < g->nV; i++) { 
                free(g->edges[i]);           // free the mallocs for each row ...
            } 
            free(g->edges);                  // now the malloc for the edges array ...
            free(g);                         // now the malloc for the graph rep
        }
        return;
    }
    
    static int validV(Graph g, Vertex v) { // checks if v is in graph 
        return (v >= 0 && v < g->nV); 
    }
    
    Edge newEdge(Vertex v, Vertex w, Weight x) { // create an edge from v to w
        Edge e = {v, w, x};
        return e; 
    } 
    
    void showEdge(Edge e) { // print an edge and its weight
        printf("%d-%d: %.2f", e.v, e.w, e.x);
        return; 
    } 
    
    int isEdge(Edge e, Graph g) { // 0 if not found, else 1; also fill in wgt
       int found = 0;
       if (g != NULL) {
          if (g->edges[e.v][e.w] != NOWEIGHT) {
             found = 1;
          }
       }
       return found;
    }
    
    Edge getEdge(Vertex v, Vertex w, Graph g) {
       Edge e = {0, 0, 0.0};
       if (validV(g, v) || validV(g, w)) {
          e.v = v;
          e.w = w;
          e.x = g->edges[v][w];
       }
       return e;
    }
    
    int cmpEdge(Edge e1, Edge e2) { // comparison based on edge weight
       int retval = 0;
       if (e1.x < e2.x) {
          retval = -1;
       }
       else if (e1.x > e2.x) {
          retval = 1;
       }
       return retval;
    }
    
    void insertEdge(Edge e, Graph g) { // insert an edge into a graph 
       if (g == NULL) {
          fprintf(stderr, "insertEdge: graph not initialised
    ");
       }
       else {
           if (!validV(g, e.v) || !validV(g, e.w)) {
              fprintf(stderr, "insertEdge: invalid vertices %d-%d
    ", e.v, e.w);
           }
           else {
              if (!isEdge(e, g)) { // increment nE only if it is new
                 g->nE++; 
              }
              g->edges[e.v][e.w] = e.x;
              g->edges[e.w][e.v] = e.x; 
           }
       }
       return;
    } 
    
    void removeEdge(Edge e, Graph g) { // remove an edge from a graph 
        if (g == NULL) {
            fprintf(stderr, "removeEdge: graph not initialised
    ");
        }
        else {
            if (!validV(g, e.v) || !validV(g, e.w)) {
                fprintf(stderr, "removeEdge: invalid vertices
    ");
            }
            else {
                if (isEdge(e, g) == NOWEIGHT) {   // is edge there?
                    g->edges[e.v][e.w] = NOWEIGHT; 
                    g->edges[e.w][e.v] = NOWEIGHT; 
                    g->nE--; 
                }
            }
        }
        return;
    } 
    
    Weight getWeight(Graph g, Vertex v1, Vertex v2) { // get Weight: NOWEIGHT if not existing
        Edge e = {v1, v2}; // not required, but for consistency
        Weight retval = 0.0;
    
        if (g == NULL) {
            fprintf(stderr, "getWeight: graph not initialised
    ");
        }
        else {
            if (!validV(g, e.v) || !validV(g, e.w)) {
                fprintf(stderr, "getWeight: invalid vertices
    ");
            }
            else {
                retval = g->edges[e.v][e.w];
            }
        }
        return retval;
    }
    
    void showGraph(Graph g) { // print a graph
        if (g == NULL) {
            printf("NULL graph
    ");
        }
        else {
            printf("V=%d, E=%d
    ", g->nV, g->nE); 
            int i;
            for (i = 0; i < g->nV; i++) { 
                int nshown = 0; 
                int j;
                for (j = 0; j < g->nV; j++) { 
                    if (g->edges[i][j] != NOWEIGHT) { 
                        printf("%d %d:%.2f ", i, j, g->edges[i][j]);
                        nshown++;
                    }
                }
                if (nshown > 0) {
                    printf("
    ");
                }
            }
        }
        return;
    }
    

     WeGraph.h  

    // WeGraph.h: an interface for a weighted graph ADT
    #include <math.h>
    
    typedef float Weight;             // define a WEIGHT
    #define NOWEIGHT  -1.0
    #define MAXWEIGHT INFINITY
    
    typedef int Vertex;               // define a VERTEX
    #define UNVISITED -1
    #define VISITED 1
    
    typedef struct { 
      Vertex v; 
      Vertex w; 
      Weight x;
    } Edge;
    
    typedef struct graphRep *Graph;   // define a GRAPH
    
    Graph newGraph(int);
    void  freeGraph(Graph);
    void  showGraph(Graph);
    
    void insertEdge(Edge, Graph);
    void removeEdge(Edge, Graph);
    void showEdge(Edge);
    int  isEdge(Edge, Graph);
    Edge newEdge(Vertex, Vertex, Weight);
    Edge getEdge(Vertex, Vertex, Graph);
    int  cmpEdge(Edge, Edge);
    
    Weight getWeight(Graph, Vertex, Vertex);
    
  • 相关阅读:
    利用进制转换压缩数字
    一个不错的移动政务网站
    系统缓存全解析(转摘)
    GeoDatabase元数据不能编辑的问题“The application is not licensed to perform this operation ”
    RSA算法的分析与实现(转载)
    云计算经济学
    Memcached在Windows操作系统下多实例并存(转载)
    AGS FlexView 与 ArcGIS Server的FeatureLayer交互的过程
    转载>ArcEngine中版本的使用
    基于ArcEngine的地图四着色算法的实现(转载)
  • 原文地址:https://www.cnblogs.com/alex-bn-lee/p/11289220.html
Copyright © 2020-2023  润新知