【图】最短路径算法

2023-05-13 13:35:31 浏览数 (1)

图的最短算法

从起点开始访问所有路径,可以到达终点的有多条地址,其中路径权值最小的为最短路径。 最短路径算法有深度优先遍历、广度优先遍历、Bellman-Ford算法、弗洛伊德算法、SPFA(Shortest Path Faster Algorithm)算法和迪杰斯特拉算法等。

本代码使用深度优先遍历

主要实现思路

从起点开始,到达终点有多条分支,这些分支中又有多条分支… 选择其实一条分支,走到终点,再选择另一个分支(temp = temp ->next)走到终点,分支的分支…

大致流程:

代码实现:

代码语言:javascript复制
#include<iostream>
#include<queue>
using namespace std;

/*
	邻接列表的大致排列类似于哈希表
	自己定义出"邻接桶"的概念,类似于“哈希桶”
	邻接桶中存着每个顶点
	每个顶点的通过EdgeNode——边,来链接着顶点和顶点,
	每个顶点都可以作为起始点,指向/被指向。


	这个容器就是“邻接桶”
						   *
	*			*			*
	*			**************	
	*			*			*
	*			*		   *
	*			*	
	*			*	
	*			*	
	*			*		   *
	*			*			*
	*			**************	
	*			*			*
	*			*		   *	
	*			*	
	*			*	
	*			*	
	*			*	
	*			*		   *
	*			*			*
	*			**************	
	*			*			*
	*			*		   *
	*			*	
	*			*	
	*			*	
	*	顶点	*	
	*			*	
	*			*	
	************
*/
#define Max_Size 1024 
bool visited[Max_Size];
typedef struct _EdgeNode
{
	int adjvex;
	int weight;
	struct _EdgeNode* next;
}EdgeNode;

typedef struct _VertexNode//顶点结点,这个就是邻接桶
{
	char data;//结点数据
	struct _EdgeNode* first;//指向邻接第一条边
}VertexNode, AdjList;

typedef struct _AdjListGraph
{
	AdjList* adjlist;
	int vex;//顶点数
	int edge;//边数

}AdjListGraph;

//通过顶点对应的字符来寻找顶点在图中的邻接点
int Location(AdjListGraph& G,char c)
{
	for (int i = 0; i < G.vex; i  )
	{
		if (G.adjlist[i].data == c)
		{
			return i;
		}
	}
	return -1;
}

//图的初始化
void initGraph(AdjListGraph& G)
{
	G.adjlist = new AdjList[Max_Size];//左侧的邻接桶
	G.edge = 0;
	G.vex = 0;
	
	for (int i = 0; i < Max_Size; i  )
	{
		visited[i] = false;	
	}
}

//图的创建
void createGraph(AdjListGraph& G)
{
	cout << "请输入该图的顶点数以及边数" << endl;
	cin >> G.vex >> G.edge;
	cout << "请输入顶点data" << endl;
	for (int i = 0; i < G.vex; i  )
	{
		cin >> G.adjlist[i].data;//输入顶点所存数据
		G.adjlist[i].first = NULL;//边和边的关系,置空,先不与任何边相连。
	}	


	//确定顶点与顶点之间的关系,两个顶点形成一条边,有几条边,就有几对i1 i2

	char v1 = 0, v2 = 0;//保存输入的顶点的字符
	int i1 = 0, i2 = 0;//保存顶点在数组中的下标
	//将i1和i2链接起来
	//i1为起点。i2为终点。

	//保存边的权重
	int weight = 0;

	cout << "请输入想关联边的顶点" << endl;
	for (int i = 0; i < G.edge; i  )
	{
		cin >> v1 >> v2 >> weight;//以v1为起点,v2为终点的边,权重是weight
		i1 = Location(G, v1);
		i2 = Location(G, v2);
		//说明存在
		if (i1 != -1 && i2 != -1)
		{
			EdgeNode* temp = new EdgeNode;
			temp->adjvex = i2;
			temp->next = G.adjlist[i1].first;//头插法-类似于hashtable中的插入数据
			temp->weight = weight;
			G.adjlist[i1].first = temp;
		}
	}
}

//图的最短路径算法

int min_weight = 0x7FFFFFFF;//定义一个最大的方便与之比较。(INT_MAX)
int steps = 0;//已走过的步数
int path[Max_Size ] = { 0 };//保存走过的路径
int shortest_path[Max_Size] = { 0 };//保存最短路径

//求图的最短路径——深度优先遍历(前提是连通图)
//                            起点   终点      已走过的权重和   
void DFS(AdjListGraph& G,int start ,int end,int weights)
{
	int cur = -1;

	if (start == end)//已经找到终点了,不需要遍历了
	{
		for (int i = 0; i < steps; i  )
		{
			cout << G.adjlist[path[i]].data << " ";//path中存的是对应结点在邻接桶中的下标,通过这个下标就能找到对应的data,即可找到走过的路径
		}	
		cout << "该路径对应的长度是:" << weights << endl;//输入对应的路径长度

		if (min_weight > weights)//取到当前最小路径
		{
			min_weight = weights;
			memcpy(shortest_path, path, steps * sizeof(int));
		}
		return;
	}
	visited[start] = 1;
	EdgeNode* temp = G.adjlist[start].first;//指向第一条边

	while (temp)
	{
		int weight = temp->weight;
		cur = temp->adjvex;//通过这条边的指向,指过来的这个顶点,在邻接桶中的下标
		if (!visited[cur])
		{
			visited[cur] = 1;//标记已经访问
			path[steps  ] = cur;
			//递归
			DFS(G, cur, end, weights weight);

			visited[cur] = 0;//前一步探索完成后,置空cur,(应该是有路线含有重复结点时起到作用)
			path[--steps] = 0;//路径回退
		}
		temp = temp->next;
	}
}

int main(void)
{
	AdjListGraph G;
	//初始化
	initGraph(G);
	//创建图
	createGraph(G);
	//深度优先-寻找最短路径
	DFS(G, Location(G, 'A'), Location(G, 'D'), 0);
	cout << "成功得到最短路径为" << endl;
	//最短路径
	int i = 0;
	cout << "起点";
	while (shortest_path[i] > 0 && i < Max_Size)
	{
		cout << "->" << G.adjlist[shortest_path[i]].data ;
		i  ;
	}
	cout << endl;
	return 0;

}

输入示例

0 人点赞