アルゴリズム -- Dijistra (最短経路の探索)

アルゴリズム – Dijistra (最短経路を見つける)

先赞后看,养成好习惯。有帮助的话,点波关注!我会坚持更新,感谢您的支持!

要件:ダイクストラアルゴリズムの原理を学び、それを再現する。

参考
ダイクストラのアルゴリズム(最短経路の探索)

1. 核となるアイデア

1. コア機能:

void DijkstraMinTree(MGraph G, int v0, int p[V], int D[V]) 

2. 主要な手順:
1) 初始化
2) 选点: 現在のサイクルで最小の重みを持つ頂点を選択します。これが、今回の最短経路を決定できる頂点です。
3) 标记
4) 更新: マークされた頂点を使用して下方向に延長します。

2. コード

#include <stdio.h>
#include <iostream>

#define V 20       // 最大顶点个数
#define INF 65535  // 无穷大

// 无项有权图数据结构
typedef struct {
  int vexs[V];         // 顶点
  int arcs[V][V];      // 边
  int vexnum, arcnum;  //顶点数,边数
} MGraph;

//根据顶点本身数据,判断出顶点在二维数组中的位置
int LocateVex(MGraph *G, const int &v) {
  int i = 0;
  for (; i < G->vexnum; ++i) {
    if (G->vexs[i] == v) {
      break;
    }
  }
  // 如果找不到
  if (i > G->vexnum) {
    std::cerr << "no such vertex" << std::endl;
    return -1;
  }
  return i;
}

//构造无向有权图
void CreateDG(MGraph *G) {
  std::cout << "输入图的顶点数和边数:" << std::endl;
  scanf("%d %d", &(G->vexnum), &(G->arcnum));
  std::cout << "输入各个顶点: " << std::endl;
  for (int i = 0; i < G->vexnum; ++i) {
    scanf("%d", &(G->vexs[i]));
  }
  for (int i = 0; i < G->vexnum; ++i) {
    for (int j = 0; j < G->vexnum; ++j) {
      G->arcs[i][j] = INF;
    }
  }
  printf("输入各个边的数据:\n");
  for (int i = 0; i < G->arcnum; ++i) {
    int v1, v2, w;
    scanf("%d %d %d", &v1, &v2, &w);
    int n = LocateVex(G, v1);
    int m = LocateVex(G, v2);
    if (m == -1 || n == -1) {
      return;
    }
    G->arcs[n][m] = w;
    G->arcs[m][n] = w;
  }
}

//迪杰斯特拉算法,v0表示有向网中起始点所在数组中的下标
void DijkstraMinTree(MGraph G, int v0, int p[V], int D[V]) {
  int final[V];  // 标记数据,是否确认为最短路径
  // 初始化
  for (int i = 0; i < G.vexnum; ++i) {
    final[i] = 0;
    p[i] = 0;
    D[i] = G.arcs[v0][i];
  }

  // v0 作为初始点
  D[v0] = 0;
  final[v0] = 1;
  int k = 0;
  for (int i = 0; i < G.vexnum; ++i) {
    int min = INF;
    /* 选择到各顶点权值最小的顶点,即为本次能确定最短路径的顶点 */
    for (int w = 0; w < G.vexnum; ++w) {
      if (!final[w]) {
        if (D[w] < min) {
          k = w;  // 记录下标
          min = D[w];
        }
      }
    }
    // 标记
    final[k] = 1;
    // 更新
    for (int w = 0; w < G.vexnum; ++w) {
      if (!final[w] && (min + G.arcs[k][w] < D[w])) {
        D[w] = min + G.arcs[k][w];
        p[w] = k;  //记录上一个最短路径顶点
      }
    }
  }
}

// 网站中的测试用例
void TestDG(MGraph *G){
    G->vexnum = 7;
    G->arcnum = 9;

    for (int i = 0; i < G->vexnum; ++i) {
      for (int j = 0; j < G->vexnum; ++j) {
        G->arcs[i][j] = INF;
      }
    }

    for (int i = 0; i < G->vexnum; ++i) {
      G->vexs[i] = i;
    }

    G->arcs[0][1] = 2;
    G->arcs[1][0] = 2;
    G->arcs[0][2] = 6;
    G->arcs[2][0] = 6;
    G->arcs[1][3] = 5;
    G->arcs[3][1] = 5;
    G->arcs[2][3] = 8;
    G->arcs[3][2] = 8;

    G->arcs[3][5] = 15;
    G->arcs[5][3] = 15;
    G->arcs[3][4] = 10;
    G->arcs[4][3] = 10;
    G->arcs[4][5] = 6;
    G->arcs[5][4] = 6;
    G->arcs[4][6] = 2;
    G->arcs[6][4] = 2;
    G->arcs[5][6] = 6;
    G->arcs[6][5] = 6;    
}


int main() {
  MGraph G;
//   CreateDG(&G);
  TestDG(&G);

  int p[V] = {0};
  int D[V] = {0};
  DijkstraMinTree(G, 0, p, D);
  std::cout << "最短路径为:" << std::endl;
  for (int i = 1; i < G.vexnum; ++i) {
    std::cout << i << "-0 的最短路径为";
    std::cout << i;
    int j = i;
    while (p[j] != 0) {
      std::cout << "-"<< p[j];
      j = p[j];
    }
    std::cout <<"-0" << std::endl;
  }
  
  for(int i = 0; i< G.vexnum; ++i){
      std::cout << "p["<< i<< "]:" << p[i] << std::endl;
  }
   
  std::cout << "原点到各顶点的最短路径长度为:" << std::endl;
  for (int i = 1; i < G.vexnum; ++i) {
    std::cout << G.vexs[0] << "-" << G.vexs[i] << ": " << D[i] << std::endl;
  }
  return 0;
}

おすすめ

転載: blog.csdn.net/weixin_36354875/article/details/126650247