迪杰斯特拉Dijkstra算法C++实现

1 Dijkstra算法

1.1 描述

迪杰斯特拉Dijkstra算法C++实现_第1张图片

1.2 实现方法

迪杰斯特拉Dijkstra算法C++实现_第2张图片

1.3 算法流程图

迪杰斯特拉Dijkstra算法C++实现_第3张图片

1.4 伪代码

void Dijkstra( graph G,& path,int v0)
{
	float dist[n];
	for(i=1;i<=n;i++) 
	{
		if(A[v0][i] !=) 
		{
			dist[i]=A[v0][i];
			path[i]=<v0,i>;
		}
		else
		{
			dist[i]=;
			path[i]={};
		}
	}
	for(i=1;i<=n;i++) 
		solved[i]=FALSE;
	solved[v0]=TRUE;
	for(i=1;i<=n;i++)
	{
    	mind=;
    	for(j=1;j<=n;j++) 
    	if( !solved[j] && dist[j] < mind )  
        {
			mind=dist[j]; 
			v=j;
		}
      	solved[v]=TRUE;
      	w=firstadj(G,v);
    	while(w!=0)
		{
    	if(dist[v]+A[v][w]<dist[w])
		{
            dist[w]=dist[v]+A[v][w];
            path[w]=path[v]+{w};
		}
    	w=nextadj(G,v,w);
    	}
	}
}

在这里插入图片描述

1.5 总结

迪杰斯特拉算法的基本思想就是每一次循环都找到和每次循环选择则的起始点最近的一个可达结点,然后再从这个结点出发进行下一步的扩展。

2 程序

2.1 程序流程图

迪杰斯特拉Dijkstra算法C++实现_第4张图片

2.2 源码

#include
#include
#include
#include
using namespace std;

//用邻接矩阵构建有向图
#define MAX 999//表示无穷
#define MVNum 20//最大结点数
typedef int VertexType;//设置结点的数据类型为int型(方便后续修改成char...)
typedef int ArcType;//设置的权值为int型(方便后续修改成float...)

class Graph//Adjacency Matrix Graph有向图,用邻接矩阵表示
{
public:
	void Create();
	int LocateVex(VertexType u);//查找Graph中的顶点u,并返回其对应在顶点表中的下标,未找到则返回-1
	int firstadj(int v);
	int nextadj(int v, int w);
	void Dijkstra(VertexType start_point);//使用迪杰斯特拉算法打印单源最短路径
	void Show();//调试用,打印邻接矩阵
private:
	VertexType vexs[MVNum];//顶点表,将顶点保存的信息存入此处
	ArcType arcs[MVNum][MVNum];//邻接矩阵
	int vexnum, arcnum;//图当前的顶点数和边数
	vector<queue<VertexType>>path;//保存各结点最短路径的path[i]
	ArcType dist[MVNum];//最短路径大小
	bool solved[MVNum];//是否找到最短路径
};
int Graph::LocateVex(VertexType u)
{//查找Graph中的顶点u,并返回其对应在顶点表中的下标,未找到则返回-1
	int i;
	for (i = 0; i < this->vexnum; i++)
	{
		if (u == this->vexs[i])
			return i;
	}
	return -1;
}
int Graph::firstadj(int v)
{
	for (int i = 0; i < this->vexnum; i++)
	{
		if (this->arcs[v][i] != MAX)
			return i;
	}
	return -1;
}
int Graph::nextadj(int v, int w)
{
	for (int i = w + 1; i < this->vexnum; i++)
	{
		if (this->arcs[v][i] != MAX)
			return i;
	}
	return -1;
}
void Graph::Show()
{
	for (int i = 0; i < this->vexnum; i++)
	{
		for (int j = 0; j < this->vexnum; j++)
		{
			cout << setw(4) << this->arcs[i][j] << " ";
		}
		cout << endl;
	}
}
void Graph::Create()
{
	cout << "请输入总结点数和总边数:";
	cin >> this->vexnum >> this->arcnum;//输入总顶点数和总边数
	cout << "请输入各结点的信息:";
	for (int i = 0; i < this->vexnum; i++)
	{
		cin >> this->vexs[i];
	}
	//初始化邻接矩阵
	for (int i = 0; i < this->vexnum; i++)
	{
		for (int j = 0; j < this->vexnum; j++)
		{
			this->arcs[i][j] = MAX;
		}
	}
	//构造邻接矩阵
	for (int i = 0; i < this->arcnum; i++)
	{
		int v1, v2, w;
		cout << "请输入第" << i + 1 << "条边的起点和终点及其对应的权值:";
		cin >> v1 >> v2 >> w;
		int m = LocateVex(v1);
		int n = LocateVex(v2);
		this->arcs[m][n] = w;
	}
	return;
}
void Graph::Dijkstra(VertexType start_point)
{
	//初始化最短距离数组
	for (int i = 0; i < this->vexnum; i++)
	{
		this->dist[i] = MAX;
	}
	dist[this->LocateVex(start_point)] = 0;
	//初始化保存路径的向量
	queue<VertexType>temp;
	temp.push(start_point);
	for (int i = 0; i < this->vexnum; i++)
	{
		//(移到for外)queuetemp;
		//temp.push(start_point);
		path.push_back(temp);
		//(不可行)path[i].push(start_point);//将起点作为最初始的路径加入每个结点对应的队列中
	}
	//初始化solved数组
	for (int i = 0; i < this->vexnum; i++)
	{
		solved[i] = false;
	}
	for (int i = 0; i < this->vexnum; i++)
	{
		if (this->arcs[this->LocateVex(start_point)][i] != MAX)
		{
			dist[i] = this->arcs[this->LocateVex(start_point)][i];
			path[i].push(this->vexs[i]);
		}
	}
	solved[this->LocateVex(start_point)] = true;
	for (int i = 0; i < this->vexnum; i++)
	{//返回地找
		ArcType mind = MAX;
		int v = i;
		for (int j = 0; j < this->vexnum; j++)
		{//一个劲地往前走
			//(移出for)int v = i;
			if (!solved[j] && dist[j] < mind)
			{
				mind = dist[j];
				v = j;
			}
			solved[v] = true;
			int w = this->firstadj(v);
			while (w != -1)
			{
				if (dist[v] + this->arcs[v][w] < dist[w])
				{
					dist[w] = dist[v] + this->arcs[v][w];
					path[w] = path[v];
					path[w].push(vexs[w]);
				}
				w = this->nextadj(v, w);
			}
		}
	}
	cout << "从结点" << start_point << "开始到各点的最短路径和路径长度如下:"<<endl;
	for (int i = 0; i < this->vexnum; i++)
	{
		if (dist[i] == MAX)
		{
			cout << "无法到达结点" << this->vexs[i] << endl;
		}
		else
		{
			cout << "抵达结点" << this->vexs[i] << "的最短路径:";
			int path_length = path[i].size();
			for (int j = 0; j < path_length; j++)
			{
				cout << path[i].front() << " ";
				path[i].pop();
			}
			cout << "长度为" << dist[i] << endl;
		}
	}
}
int main()
{
	Graph s;
	s.Create();
	s.Show();
	VertexType start_point;
	cout << "请输入起点:";
	cin >> start_point;
	s.Dijkstra(start_point);
	system("pause");
	return 0;
}

2.3 测试数据

迪杰斯特拉Dijkstra算法C++实现_第5张图片

2.4 运行结果

迪杰斯特拉Dijkstra算法C++实现_第6张图片

2.5 参考资料

  1. 《数据结构与算法基础》青岛大学-王卓-网课
  2. 《啊哈!算法》在线阅读 Click Here
  3. 《课堂PPT》

你可能感兴趣的:(算法,c++,图论)