【算法概论】图论算法:Dijkstra算法

  • 广度优先搜索算法

  • Dijkstra 算法(迪杰斯特拉算法)


     

广度优先搜索算法:

❗算法描述❗:

       以 s 为源点,将图划分为不同的层次。s 其本身作为一个层次,表示与 s 间距为 0 的顶点,还有与 s 间距为 1 的顶点、间距为 2 的顶点 …… 按层次检索下来,就得到图的广度优先搜索序列。

       从上面的描述就可以看出,广度优先搜索树有这样一个性质:当每条边的长度均为单位长度时,它含有的从 s 出发的所有路径都是最短路径。因此,广度优先搜索树 又被称为 最短路径树。

算法实现✍:

       建立一个队列 Q,初始化队列中有一个源点。

       进行迭代:将 Q 的顶端元素 取出,以其为源点,检索与源点相邻的点,依次加入队列中。

       迭代完成的条件:Q 为空。

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

int vexnum, edgenum;
vector<vector<int>> edge;

void BFSTraverse();

int main()
{
	cout << "请输入顶点、边的数量:" << endl;
	cin >> vexnum >> edgenum;

	edge.resize(vexnum, vector<int>(vexnum, 0));
	cout << "请输入有向图中的边:" << endl;
	for (int i = 0; i < edgenum; ++i)
	{
		int tmp1, tmp2;
		cin >> tmp1 >> tmp2;
		edge[tmp1][tmp2] = 1;
	}

	cout << "广度优先搜索序列为:" << endl;
	BFSTraverse();
	cout << endl;

	return 0;
}

void BFSTraverse()
{
	// 访问数组
	vector<bool> visited(vexnum, false);

	// 存储顶点的队列
	queue<int> Q;
	Q.push(0);
	visited[0] = true;

	while (!Q.empty())
	{
		int s = Q.front();
		Q.pop();
		//visited[s] = true;
		cout << s << ' ';

		for (int i = 0; i < vexnum; ++i)
		{
			// 如果点 i 未被访问 且 s -> i 有路径
			if (edge[s][i] == 1 && !visited[i])
			{
				visited[i] = true;
				Q.push(i);
			}
		}
	}
}
BFS检验?

Dijkstra算法:

       广度优先搜索可以在任何边均为单位长度的图中找到最短路径,对广度优先搜索进行改进,即可得到更有普遍性的迪杰斯特拉算法,它适用于权值为正的图。

❗算法描述❗:

       在广度优先搜索的算法基础上进行改进

       1)将 访问数组 变为 表示距离的dist数组;

       2)改用优先队列实现;

       3)添加 辅助数组 prev,prev[u] 存储 从源点 s 到 u 的最短路径上,紧挨 u 并在 u 之前的顶点。这边于输出最短路径。

算法实现✍:

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

int vexnum, edgenum;
vector<vector<int>> edge;
vector<int> dist;

void Dijkstra();

// 自定义比较方式为 dist值最小者优先
struct cmp
{
	bool operator()(int a, int b)
	{
		if (dist[a] <= dist[b])
		{
			return true;
		}
		else
		{
			return false;
		}
	}
};

int main()
{
	cout << "请输入顶点、边的数量:" << endl;
	cin >> vexnum >> edgenum;

	edge.resize(vexnum, vector<int>(vexnum, 0));
	cout << "请输入有向图中的边及其权值:" << endl;
	for (int i = 0; i < edgenum; ++i)
	{
		int tmp1, tmp2, temp;
		cin >> tmp1 >> tmp2 >> temp;
		edge[tmp1][tmp2] = temp;
	}

	cout << "从源点到其余各点的最小路径长度为:" << endl;
	Dijkstra();
	for (int i = 1; i < vexnum; ++i)
	{
		cout << dist[i] << ' ';
	}
	cout << endl;

	return 0;
}

void Dijkstra()
{
	// dist数组
	dist.resize(vexnum, INT_MAX);
	dist[0] = 0;

	// 存储顶点的优先队列
	priority_queue<int, vector<int>, cmp> Q;
	Q.push(0);

	while (!Q.empty())
	{
		// 返回并删除dist值最小的元素
		int s = Q.top();
		Q.pop();

		for (int i = 0; i < vexnum; ++i)
		{
			// 如果点 i 未被访问 且 s -> i 有路径
			if (edge[s][i] != 0 && dist[i] > dist[s] + edge[s][i])
			{
				dist[i] = dist[s] + edge[s][i];
				Q.push(i);	//将点 i 加入队列并对队列进行原地构造
			}
		}
	}
}
Dijkstra检验?

 

 

C++ priority_queue的自定义比较方式

C++ priority_queue用法详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值