実験レポート - Dijsktra アルゴリズムに基づく最短経路ソリューション

武道の世界でカイゴウとして知られる無名の大学生
原作者: ジャッキー・リー
電子メール: [email protected]
最終編集日: 2022.12.3

f65e6a2d969044f6a4c8a2f02066848e.jpeg

 

目次

1. 実験目的

2. 実験装置

3. 実験内容

【問題の説明】

【入力条件】

【出力要件】

【入力サンプル】

【出力サンプル】

4. 実験のヒント

5. 実験手順

5.1

6. 実験結果

6.1 主要なソースコードとプログラム完成後の実行結果のスクリーンショット

7. 実験の概要

8: 参照コードを強調表示する

作者が言いたいことがある


 

コースタイトル:

データ構造

プロジェクト名:

Dijsktra アルゴリズムに基づく最短経路ソリューション

実験の種類:

設計実験

 

1. 実験目的

1. グラフの隣接行列表現を習得し、隣接行列表現を用いたグラフ作成アルゴリズムを習得する。

2. 最短経路を見つけるための Dijsktra アルゴリズムをマスターします。


2. 実験装置

Dev C++ がインストールされたコンピューター


3. 実験内容

以下の要件に限定されず、峠での実習課題の完了に基づいてフォームに記入してください。アルゴリズム分析、アルゴリズムの説明、フローチャートを自分で追加できます

 

【問題の説明】

地図には n 個の都市が含まれており、都市間には m 個のパス (有向グラフ) があり、各パスの長さが既知であると仮定します。地図上に開始点の都市と終了点の都市が指定されている場合、Dijsktra アルゴリズムを使用して開始点と終了点の間の最短経路を見つけます。

【入力条件】

複数のデータセット。各データセットには m+3 行があります。最初の行は 2 つの整数 n と m で、それぞれ都市の数 n とパスの数 m を表します。2 行目には n 文字があり、各都市の名前を表します。3 行目から m+2 行までの各行には、2 つの文字 a および b と、都市 a から都市 b までの距離 d の道路を表す整数 d が含まれています。最後の行は 2 文字で、最短経路が見つかる都市の始点と終点を表します。n と m が両方とも 0 に等しい場合、入力は終了します。

【出力要件】

各データセットは 2 ラインを出力します。最初の行は整数で、始点から終点までの最短パスの長さを表します。行 2 はパスを表す文字列です。2 文字ごとにスペースで区切ります。

【入力サンプル】

3 3

ABC

AB1

BC1

CA3

交流

6 8

ABCDEF

AF100

AE30

AC10

紀元前5年

CD50

DE 20

EF60

DF10

AF

0 0

【出力サンプル】

2

ABC

60

AEDF

4. 実験のヒント

この実験の内容は教科書本体のアルゴリズム 6.10 を拡張したもので、ソース点 v0 からグラフ内の他のすべての頂点までの最短経路を求めます。この実験では、指定された開始点から指定された終了点までの最短パスを見つける必要があります。アルゴリズムの効率を向上させるために、解法時に判定を行うことができ、得られた終点が指定された終点である場合、解法を終了し、必要に応じて対応する結果を出力することができます。

5. 実験手順


5.1

このセクションには、問題解決のアイデア、最初に入力したが失敗した手順、デバッグを通じて問題を見つけて修正する方法などを含めることができ、調整仕様のスクリーンショットや視覚化を貼り付けることができます。

 

6. 実験結果

6.1 主要なソースコードとプログラム完成後の実行結果のスクリーンショット

最終的なコード、実行結果、または視覚化効果をここに表示できます。

  

 

7. 実験の概要

導入と正確な言葉を使用して、この実験で解決することに重点を置いた問題、学んだ知識、それをどの程度習得したかなどを説明します。



8: 参照コードを強調表示する

#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <map>
#include <cmath>
#include <cstring>

#define IOS std::ios::sync_with_stdio(false)
//#define YES cout << "YES" << endl
//#define NO cout << "NO" << endl
#define MAXLEN 20  
#define INFINE 99999  

using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;

const int N = 100;

int n, m;

typedef struct ArcNode //定义结构体
{
	int adjvex;//邻接顶点下标
	int weight;//边的权值
	struct ArcNode *next; //指向下一个邻边节点指针
}ArcNode;

typedef struct
{
	char vertex;//顶点标志
	ArcNode *firstedge;//保存第一个边节点指针

}VertexNode;

typedef struct
{
	VertexNode adjlist[MAXLEN];//顶点数组
	int vexnum;  //顶点数 
	int arcnum;  //边数
}AdjList;

//创建邻接表
AdjList *Created_Graph(AdjList *G)
{
	int i, k, weight;
	ArcNode *s;
	char vex1, vex2; //顶点标志
	int n1, n2;//顶点下标
	G -> vexnum = n, G -> arcnum = m;
	for (i = 1; i <= G -> vexnum; i++)
	{
		cin >> G -> adjlist[i].vertex;
		G->adjlist[i].firstedge = NULL;   //头节点指向为空;
	}
	for (k = 1; k <= G -> arcnum; k ++) 
	{
		cin >> vex1 >> vex2;
		for (i = 1; i <= G -> vexnum; i ++) 
		{
			if (G -> adjlist[i].vertex == vex1) n1 = i;
			if (G -> adjlist[i].vertex == vex2) n2 = i;
		}
		cin >> weight;
		s = new(ArcNode);
		s -> adjvex = n2, s -> weight = weight;
		s -> next = G -> adjlist[n1].firstedge;
		G -> adjlist[n1].firstedge = s;
	}
	return G;
}

//获取位置
int getPosition(AdjList *G, char c)
{
	int m;
	for (m = 1; m <= G -> vexnum; m ++) 
		if (G -> adjlist[m].vertex == c)
			return  m;
	return 1;
}

//获取G中边<start, end>的权值;若start和end不是连通的,则返回无穷大。
int get_weight(AdjList *G, int start, int end)
{
	ArcNode *node;

	if (start == end)
		return 0;

	node = G -> adjlist[start].firstedge;
	while (node != NULL)
	{
		if (end == node -> adjvex)
			return node -> weight;
		node = node -> next;
	}
	return INFINE;
}

/*
* 迪杰斯特拉算法求最短路径。统计图(G)中"顶点vs"到其它各个顶点的最短路径。
* 参数说明:
* G -- 邻接图
* vs -- 起始顶点(start vertex)。即计算"顶点vs"到其它顶点的最短路径。
* prev -- 前驱顶点数组。即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。
* dist -- 长度数组。即,dist[i]是"顶点vs"到"顶点i"的最短路径的长度。
*/
void Dijkstra(AdjList *G, int vs, int prev[], int dist[], char over)
{
	int i, j, k, t,m;
	int min;
	int tmp;
	int flag[INFINE];      // flag[i]=1表示"顶点vs"到"顶点i"的最短路径已成功获取。
	int path[MAXLEN][MAXLEN]={0};
	// 初始化
	for (i = 1; i <= G->vexnum; i++)
	{
		flag[i] = 0;                     // 顶点i的最短路径还没获取到。
		prev[i] = 0;                     // 顶点i的前驱顶点为0。
		dist[i] = get_weight(G, vs, i);  // 顶点i的最短路径为"顶点vs"到"顶点i"的权。
		path[i][0] = 0;
	}
	// 对"顶点vs"自身进行初始化
	flag[vs] = 1;
	dist[vs] = 0;
	path[vs][0] =1;
	// 遍历G->vexnum-1次;每次找出一个顶点的最短路径。
	for (i = 2; i <= G->vexnum; i++)
	{
		// 寻找当前最小的路径,即在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
		t = 0;
		min = INFINE;
		for (j = 1; j <= G->vexnum; j++)
			if (flag[j] == 0 && dist[j]<min)
				min = dist[j], k = j;

		// 标记"顶点k"为已经获取到最短路径
		flag[k] = 1;
		// 修正当前最短路径和前驱顶点,即当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
		for (j = 1; j <= G->vexnum; j++)
		{
			tmp = get_weight(G, k, j);
			tmp = (tmp == INFINE ? INFINE : (min + tmp)); // 防止溢出
			if (flag[j] == 0 && (tmp  < dist[j]))
			{
				dist[j] = tmp;
				prev[j] = k;
				path[j][t] = k;
				t++;
			}
		}
	}
	// 打印dijkstra最短路径的结果
	for (i = 1; i <= G -> vexnum; i++)
	{
		if(G -> adjlist[i].vertex == over) 
		{
			cout << G -> adjlist[vs].vertex << "到" << over << "的最短路径长度为:" << dist[i];

			int showpath[MAXLEN] = {0};//存储最短路径上的节点
			for (m = 0; m < G->vexnum; m++)
			{
				if (path[i][m] == 0|| G->adjlist[path[i][m]].vertex == G->adjlist[vs].vertex) break;
				showpath[m] = path[i][m];
			}
//		//以下用于拼接路径
			if (dist[i]!= INFINE)
			{
				cout << endl << "当前最短路径为:" << G->adjlist[vs].vertex << "->";
				for (int q = MAXLEN - 1; q >= 0; q--)//存入的中间节点是【距离原点最远的顶点】依次递减存入的,故需逆序输出
				{
					if (showpath[q] == 0) continue;
					cout << G -> adjlist[showpath[q]].vertex << "->";
				}
				cout << G -> adjlist[i].vertex << endl;
			}
		}
	}

}

int main()
{
	while(scanf("%d%d", &n, &m) != EOF)
	{
	    AdjList G;
	    char start1, over1;
	    int ps;
	    int dist[MAXLEN], prev[MAXLEN];
	    AdjList *G2 = Created_Graph(&G);//创建表
	    cin >> start1 >> over1;
	    ps = getPosition(G2, start1);//获取起点位置
	    Dijkstra(G2, ps, prev, dist, over1);
	}
	return 0;
}

作者が言いたいことがある

コードが必要な場合は、ブロガーに個人的にメッセージを送信してください。ブロガーはそれを見て返信します。

ブロガーの発言が役に立ったと感じたら、「フォロー」をクリックしてサポートしてください。今後もそのような問題を更新していきます。

 

おすすめ

転載: blog.csdn.net/weixin_62075168/article/details/128167492